99/103 rejected minecraft source files applied

This commit is contained in:
granny
2026-03-13 17:54:48 -07:00
parent 1f72458912
commit 2df686555d
83 changed files with 1079 additions and 1548 deletions

View File

@@ -1,18 +0,0 @@
From 56a0a83ddb1b7472dbc9762e2aca396605c62085 Mon Sep 17 00:00:00 2001
From: File <noreply+automated@papermc.io>
Date: Sun, 20 Apr 1997 05:37:42 -0800
Subject: [PATCH] purpur File Patches
diff --git a/net/minecraft/world/entity/ai/attributes/RangedAttribute.java b/net/minecraft/world/entity/ai/attributes/RangedAttribute.java
index 0a0e5d9fd64182c1bed4c0aa6a40d8b2cdf8bc9d..353d571b4a2bf18414a08239abe2b079e3750d89 100644
--- a/net/minecraft/world/entity/ai/attributes/RangedAttribute.java
+++ b/net/minecraft/world/entity/ai/attributes/RangedAttribute.java
@@ -29,6 +29,7 @@ public class RangedAttribute extends Attribute {
@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);
}
}

View File

@@ -1,19 +0,0 @@
From 56a0a83ddb1b7472dbc9762e2aca396605c62085 Mon Sep 17 00:00:00 2001
From: File <noreply+automated@papermc.io>
Date: Sun, 20 Apr 1997 05:37:42 -0800
Subject: [PATCH] purpur File Patches
diff --git a/net/minecraft/world/entity/ai/behavior/AcquirePoi.java b/net/minecraft/world/entity/ai/behavior/AcquirePoi.java
index 278addb7dbe4f57e99fb91ce1cd1bf3559e239a3..3e0fd09a0c0047cfe100e878186471090f8909a0 100644
--- a/net/minecraft/world/entity/ai/behavior/AcquirePoi.java
+++ b/net/minecraft/world/entity/ai/behavior/AcquirePoi.java
@@ -85,7 +85,7 @@ public class AcquirePoi {
};
// 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())) {

View File

@@ -1,37 +0,0 @@
From 56a0a83ddb1b7472dbc9762e2aca396605c62085 Mon Sep 17 00:00:00 2001
From: File <noreply+automated@papermc.io>
Date: Sun, 20 Apr 1997 05:37:42 -0800
Subject: [PATCH] purpur File Patches
diff --git a/net/minecraft/world/entity/ai/behavior/InteractWithDoor.java b/net/minecraft/world/entity/ai/behavior/InteractWithDoor.java
index df185d375658d765b07648dfb42ea56c84be671e..5c845d78e8baee41809e0678e3d99523368a2882 100644
--- a/net/minecraft/world/entity/ai/behavior/InteractWithDoor.java
+++ b/net/minecraft/world/entity/ai/behavior/InteractWithDoor.java
@@ -55,7 +55,7 @@ public class InteractWithDoor {
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 +72,7 @@ public class InteractWithDoor {
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 +118,7 @@ public class InteractWithDoor {
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();

View File

@@ -1,18 +0,0 @@
From 56a0a83ddb1b7472dbc9762e2aca396605c62085 Mon Sep 17 00:00:00 2001
From: File <noreply+automated@papermc.io>
Date: Sun, 20 Apr 1997 05:37:42 -0800
Subject: [PATCH] purpur File Patches
diff --git a/net/minecraft/world/entity/ai/behavior/ShowTradesToPlayer.java b/net/minecraft/world/entity/ai/behavior/ShowTradesToPlayer.java
index 338f9850a9ee968ade1a5554936a10b8a3786fe5..8cac46b6fd025f7f10b17903579f021482ed4b18 100644
--- a/net/minecraft/world/entity/ai/behavior/ShowTradesToPlayer.java
+++ b/net/minecraft/world/entity/ai/behavior/ShowTradesToPlayer.java
@@ -45,6 +45,7 @@ public class ShowTradesToPlayer extends Behavior<Villager> {
@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();

View File

@@ -1,62 +0,0 @@
From 56a0a83ddb1b7472dbc9762e2aca396605c62085 Mon Sep 17 00:00:00 2001
From: File <noreply+automated@papermc.io>
Date: Sun, 20 Apr 1997 05:37:42 -0800
Subject: [PATCH] purpur File Patches
diff --git a/net/minecraft/world/entity/ai/behavior/TransportItemsBetweenContainers.java b/net/minecraft/world/entity/ai/behavior/TransportItemsBetweenContainers.java
index 3741e32fa1aa85e3b5b45c3b05fcb3a0a807a6e7..2a7cda7fbc400a13e7ab71a6a82496068d9c7ae6 100644
--- a/net/minecraft/world/entity/ai/behavior/TransportItemsBetweenContainers.java
+++ b/net/minecraft/world/entity/ai/behavior/TransportItemsBetweenContainers.java
@@ -285,7 +285,7 @@ public class TransportItemsBetweenContainers extends Behavior<PathfinderMob> {
LevelChunk chunkNow = level.getChunkSource().getChunkNow(chunkPos.x, chunkPos.z);
if (chunkNow != null) {
for (BlockEntity blockEntity : chunkNow.getBlockEntities().values()) {
- if (blockEntity instanceof ChestBlockEntity chestBlockEntity) {
+ if (blockEntity instanceof net.minecraft.world.level.block.entity.BaseContainerBlockEntity chestBlockEntity) { // Purpur - copper golem can place items in barrels or shulkers option
double d1 = chestBlockEntity.getBlockPos().distToCenterSqr(mob.position());
if (d1 < d) {
TransportItemsBetweenContainers.TransportItemTarget transportItemTarget1 = this.isTargetValidToPick(
@@ -369,7 +369,11 @@ public class TransportItemsBetweenContainers extends Behavior<PathfinderMob> {
}
private boolean isTargetBlocked(Level level, TransportItemsBetweenContainers.TransportItemTarget target) {
- return ChestBlock.isChestBlockedAt(level, target.pos);
+ // Purpur start - copper golem can place items in barrels or shulkers option
+ boolean isBarrelBlocked = !level.purpurConfig.copperGolemCanOpenBarrel && target.state.is(net.minecraft.world.level.block.Blocks.BARREL);
+ boolean isShulkerBlocked = !level.purpurConfig.copperGolemCanOpenShulker && target.blockEntity instanceof net.minecraft.world.level.block.entity.ShulkerBoxBlockEntity shulkerBoxBlockEntity && !net.minecraft.world.level.block.ShulkerBoxBlock.canOpen(target.state, level, target.pos, shulkerBoxBlockEntity);
+ return target.state.is(net.minecraft.world.level.block.Blocks.BARREL) ? isBarrelBlocked : isShulkerBlocked || net.minecraft.world.level.block.ChestBlock.isChestBlockedAt(level, target.pos);
+ // Purpur end - copper golem can place items in barrels or shulkers option
}
private boolean targetHasNotChanged(Level level, TransportItemsBetweenContainers.TransportItemTarget target) {
@@ -446,7 +450,7 @@ public class TransportItemsBetweenContainers extends Behavior<PathfinderMob> {
}
private boolean isWantedBlock(PathfinderMob mob, BlockState state) {
- return isPickingUpItems(mob) ? this.sourceBlockType.test(state) : this.destinationBlockType.test(state);
+ return isPickingUpItems(mob) ? this.sourceBlockType.test(state) : (mob.level().purpurConfig.copperGolemCanOpenBarrel && state.is(net.minecraft.world.level.block.Blocks.BARREL)) || (mob.level().purpurConfig.copperGolemCanOpenShulker && state.is(net.minecraft.tags.BlockTags.SHULKER_BOXES)) || this.destinationBlockType.test(state); // Purpur - copper golem can place items in barrels or shulkers option
}
private static double getInteractionRange(PathfinderMob mob) {
@@ -488,6 +492,11 @@ public class TransportItemsBetweenContainers extends Behavior<PathfinderMob> {
}
private static boolean matchesLeavingItemsRequirement(PathfinderMob mob, Container container) {
+ // Purpur start - copper golem can place items in barrels or shulkers option
+ if (mob.level().purpurConfig.copperGolemCanOpenShulker && container instanceof net.minecraft.world.level.block.entity.ShulkerBoxBlockEntity && mob.getMainHandItem().is(net.minecraft.tags.ItemTags.SHULKER_BOXES)) {
+ return false;
+ }
+ // Purpur end - copper golem can place items in barrels or shulkers option
return container.isEmpty() || hasItemMatchingHandItem(mob, container);
}
@@ -525,7 +534,7 @@ public class TransportItemsBetweenContainers extends Behavior<PathfinderMob> {
int i = 0;
for (ItemStack itemStack : container) {
- if (!itemStack.isEmpty()) {
+ if (!itemStack.isEmpty() && (!(container instanceof net.minecraft.world.level.block.entity.ShulkerBoxBlockEntity) || !itemStack.is(net.minecraft.tags.ItemTags.SHULKER_BOXES))) { // Purpur - copper golem can place items in barrels or shulkers option
int min = Math.min(itemStack.getCount(), 16);
return container.removeItem(i, min);
}

View File

@@ -1,25 +0,0 @@
From 56a0a83ddb1b7472dbc9762e2aca396605c62085 Mon Sep 17 00:00:00 2001
From: File <noreply+automated@papermc.io>
Date: Sun, 20 Apr 1997 05:37:42 -0800
Subject: [PATCH] purpur File Patches
diff --git a/net/minecraft/world/entity/ai/goal/SwellGoal.java b/net/minecraft/world/entity/ai/goal/SwellGoal.java
index 2bc0c7f5973d5d5695ec291f404a836a78e8348e..ccbd344a49a568e97606c364082ab3f74ad5e6ed 100644
--- a/net/minecraft/world/entity/ai/goal/SwellGoal.java
+++ b/net/minecraft/world/entity/ai/goal/SwellGoal.java
@@ -47,6 +47,14 @@ public class SwellGoal extends Goal {
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
}
}
}

View File

@@ -1,19 +0,0 @@
From 56a0a83ddb1b7472dbc9762e2aca396605c62085 Mon Sep 17 00:00:00 2001
From: File <noreply+automated@papermc.io>
Date: Sun, 20 Apr 1997 05:37:42 -0800
Subject: [PATCH] purpur File Patches
diff --git a/net/minecraft/world/entity/ai/sensing/NearestBedSensor.java b/net/minecraft/world/entity/ai/sensing/NearestBedSensor.java
index 066faa704338c573472381e1ebd063e0d52aaaa4..1f96fd5085bacb4c584576c7cb9f51e7898e9b03 100644
--- a/net/minecraft/world/entity/ai/sensing/NearestBedSensor.java
+++ b/net/minecraft/world/entity/ai/sensing/NearestBedSensor.java
@@ -56,7 +56,7 @@ public class NearestBedSensor extends Sensor<Mob> {
// 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()) {

View File

@@ -1,42 +0,0 @@
From 56a0a83ddb1b7472dbc9762e2aca396605c62085 Mon Sep 17 00:00:00 2001
From: File <noreply+automated@papermc.io>
Date: Sun, 20 Apr 1997 05:37:42 -0800
Subject: [PATCH] purpur File Patches
diff --git a/net/minecraft/world/entity/animal/Animal.java b/net/minecraft/world/entity/animal/Animal.java
index 023b68549e3b185d8ad2f505f34bb59556bbf961..2e7e7c1913f5cbc20ce116c5ae3e185fc83094c0 100644
--- a/net/minecraft/world/entity/animal/Animal.java
+++ b/net/minecraft/world/entity/animal/Animal.java
@@ -146,7 +146,7 @@ public abstract class Animal extends AgeableMob {
ItemStack itemInHand = player.getItemInHand(hand);
if (this.isFood(itemInHand)) {
int age = this.getAge();
- if (player instanceof ServerPlayer serverPlayer && age == 0 && this.canFallInLove()) {
+ if (player instanceof ServerPlayer serverPlayer && 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(serverPlayer, breedCopy); // Paper - Fix EntityBreedEvent copying
@@ -227,10 +227,20 @@ public abstract class Animal extends AgeableMob {
public void spawnChildFromBreeding(ServerLevel level, Animal partner) {
AgeableMob breedOffspring = this.getBreedOffspring(level, partner);
if (breedOffspring != null) {
- breedOffspring.setBaby(true);
- breedOffspring.snapTo(this.getX(), this.getY(), this.getZ(), 0.0F, 0.0F);
+ //breedOffspring.setBaby(true); // Purpur - Add adjustable breeding cooldown to config - moved down
+ //breedOffspring.snapTo(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(partner.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.snapTo(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, partner, breeder, this.breedItem, experience);
if (entityBreedEvent.isCancelled()) {

View File

@@ -1,19 +0,0 @@
From 56a0a83ddb1b7472dbc9762e2aca396605c62085 Mon Sep 17 00:00:00 2001
From: File <noreply+automated@papermc.io>
Date: Sun, 20 Apr 1997 05:37:42 -0800
Subject: [PATCH] purpur File Patches
diff --git a/net/minecraft/world/entity/animal/feline/Ocelot.java b/net/minecraft/world/entity/animal/feline/Ocelot.java
index cf940de8767df6d07551d7a221a0e87df4e41785..94fdbae92dabf7505a7c7b518d4c07b4f68c8e9c 100644
--- a/net/minecraft/world/entity/animal/feline/Ocelot.java
+++ b/net/minecraft/world/entity/animal/feline/Ocelot.java
@@ -234,7 +234,7 @@ public class Ocelot extends Animal {
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;
}

View File

@@ -1,20 +0,0 @@
From 56a0a83ddb1b7472dbc9762e2aca396605c62085 Mon Sep 17 00:00:00 2001
From: File <noreply+automated@papermc.io>
Date: Sun, 20 Apr 1997 05:37:42 -0800
Subject: [PATCH] purpur File Patches
diff --git a/net/minecraft/world/entity/animal/fish/WaterAnimal.java b/net/minecraft/world/entity/animal/fish/WaterAnimal.java
index 3965cb8ae6fdd8d9d0135e6695463e6bef624fe2..9ff11eb96bc8d0c9bd611c8d45d8799c67f1fb61 100644
--- a/net/minecraft/world/entity/animal/fish/WaterAnimal.java
+++ b/net/minecraft/world/entity/animal/fish/WaterAnimal.java
@@ -76,8 +76,7 @@ public abstract class WaterAnimal extends PathfinderMob {
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);
}

View File

@@ -1,30 +0,0 @@
From 56a0a83ddb1b7472dbc9762e2aca396605c62085 Mon Sep 17 00:00:00 2001
From: File <noreply+automated@papermc.io>
Date: Sun, 20 Apr 1997 05:37:42 -0800
Subject: [PATCH] purpur File Patches
diff --git a/net/minecraft/world/entity/animal/pig/Pig.java b/net/minecraft/world/entity/animal/pig/Pig.java
index 8f5d1e2d98472e8e313fad285bd1629aea4173a9..943bd459554e9f3374978e595ba369a479d44941 100644
--- a/net/minecraft/world/entity/animal/pig/Pig.java
+++ b/net/minecraft/world/entity/animal/pig/Pig.java
@@ -138,6 +138,19 @@ public class Pig extends Animal implements ItemSteerable {
@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.setItemSlot(EquipmentSlot.SADDLE, ItemStack.EMPTY);
+ 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);

View File

@@ -1,34 +0,0 @@
From 56a0a83ddb1b7472dbc9762e2aca396605c62085 Mon Sep 17 00:00:00 2001
From: File <noreply+automated@papermc.io>
Date: Sun, 20 Apr 1997 05:37:42 -0800
Subject: [PATCH] purpur File Patches
diff --git a/net/minecraft/world/entity/animal/rabbit/Rabbit.java b/net/minecraft/world/entity/animal/rabbit/Rabbit.java
index 17e58836d18afc7cfcc1cf7a8ac5b9e66ceb5f0d..d5e7599c23405eb5a4519e2dfd93ddbe2853fa3b 100644
--- a/net/minecraft/world/entity/animal/rabbit/Rabbit.java
+++ b/net/minecraft/world/entity/animal/rabbit/Rabbit.java
@@ -404,10 +404,23 @@ public class Rabbit extends Animal {
}
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)) {

View File

@@ -1,27 +0,0 @@
From 56a0a83ddb1b7472dbc9762e2aca396605c62085 Mon Sep 17 00:00:00 2001
From: File <noreply+automated@papermc.io>
Date: Sun, 20 Apr 1997 05:37:42 -0800
Subject: [PATCH] purpur File Patches
diff --git a/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java b/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java
index 1daf8f52148043339f723aaebdf6135763dd805b..9c38e3b8c09caa2701a207b91761f344c5e53385 100644
--- a/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java
+++ b/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java
@@ -957,6 +957,7 @@ public class EnderDragon extends Mob implements Enemy {
@Override
protected boolean canRide(Entity entity) {
+ if (this.level().purpurConfig.enderDragonCanRideVehicles) return this.boardingCooldown <= 0; // Purpur - Configs for if Wither/Ender Dragon can ride vehicles
return false;
}
@@ -992,7 +993,7 @@ public class EnderDragon extends Mob implements Enemy {
boolean flag = level.getGameRules().get(GameRules.MOB_DROPS);
int i = 500;
- if (this.dragonFight != null && !this.dragonFight.hasPreviouslyKilledDragon()) {
+ if (this.dragonFight != null && (level().purpurConfig.enderDragonAlwaysDropsFullExp || !this.dragonFight.hasPreviouslyKilledDragon())) { // Purpur - Ender dragon always drop full exp
i = 12000;
}

View File

@@ -1,54 +0,0 @@
From 56a0a83ddb1b7472dbc9762e2aca396605c62085 Mon Sep 17 00:00:00 2001
From: File <noreply+automated@papermc.io>
Date: Sun, 20 Apr 1997 05:37:42 -0800
Subject: [PATCH] purpur File Patches
diff --git a/net/minecraft/world/entity/item/ItemEntity.java b/net/minecraft/world/entity/item/ItemEntity.java
index e82bb8f2d2b0e771dc371fd7e709116e1f5f204f..ddf7fa8e67440beb102b6bf91b30f2b340b52a8e 100644
--- a/net/minecraft/world/entity/item/ItemEntity.java
+++ b/net/minecraft/world/entity/item/ItemEntity.java
@@ -54,6 +54,12 @@ public class ItemEntity extends Entity implements TraceableEntity {
public boolean canMobPickup = true; // Paper - Item#canEntityPickup
private int despawnRate = -1; // Paper - Alternative item-despawn-rate
public net.kyori.adventure.util.TriState frictionState = net.kyori.adventure.util.TriState.NOT_SET; // Paper - Friction API
+ // Purpur start - Item entity immunities
+ public boolean immuneToCactus = false;
+ public boolean immuneToExplosion = false;
+ public boolean immuneToFire = false;
+ public boolean immuneToLightning = false;
+ // Purpur end - Item entity immunities
public ItemEntity(EntityType<? extends ItemEntity> type, Level level) {
super(type, level);
@@ -330,7 +336,16 @@ public class ItemEntity extends Entity implements TraceableEntity {
@Override
public final boolean hurtServer(ServerLevel level, DamageSource damageSource, float amount) {
- if (this.isInvulnerableToBase(damageSource)) {
+ // Purpur start - Item entity immunities
+ if (
+ (immuneToCactus && damageSource.is(net.minecraft.world.damagesource.DamageTypes.CACTUS)) ||
+ (immuneToFire && (damageSource.is(net.minecraft.tags.DamageTypeTags.IS_FIRE) || damageSource.is(net.minecraft.world.damagesource.DamageTypes.ON_FIRE) || damageSource.is(net.minecraft.world.damagesource.DamageTypes.IN_FIRE))) ||
+ (immuneToLightning && damageSource.is(net.minecraft.world.damagesource.DamageTypes.LIGHTNING_BOLT)) ||
+ (immuneToExplosion && damageSource.is(net.minecraft.tags.DamageTypeTags.IS_EXPLOSION))
+ ) {
+ return false;
+ } else if (this.isInvulnerableToBase(damageSource)) {
+ // Purpur end - Item entity immunities
return false;
} else if (!level.getGameRules().get(GameRules.MOB_GRIEFING) && damageSource.getEntity() instanceof Mob) {
return false;
@@ -508,6 +523,12 @@ public class ItemEntity extends Entity implements TraceableEntity {
public void setItem(ItemStack stack) {
this.getEntityData().set(DATA_ITEM, stack);
this.despawnRate = this.level().paperConfig().entities.spawning.altItemDespawnRate.enabled ? this.level().paperConfig().entities.spawning.altItemDespawnRate.items.getOrDefault(stack.getItem(), this.level().spigotConfig.itemDespawnRate) : this.level().spigotConfig.itemDespawnRate; // Paper - Alternative item-despawn-rate
+ // Purpur start - Item entity immunities
+ if (level().purpurConfig.itemImmuneToCactus.contains(stack.getItem())) immuneToCactus = true;
+ if (level().purpurConfig.itemImmuneToExplosion.contains(stack.getItem())) immuneToExplosion = true;
+ if (level().purpurConfig.itemImmuneToFire.contains(stack.getItem())) immuneToFire = true;
+ if (level().purpurConfig.itemImmuneToLightning.contains(stack.getItem())) immuneToLightning = true;
+ // level end - Item entity immunities
}
@Override

View File

@@ -1,22 +0,0 @@
From 56a0a83ddb1b7472dbc9762e2aca396605c62085 Mon Sep 17 00:00:00 2001
From: File <noreply+automated@papermc.io>
Date: Sun, 20 Apr 1997 05:37:42 -0800
Subject: [PATCH] purpur File Patches
diff --git a/net/minecraft/world/entity/monster/Ghast.java b/net/minecraft/world/entity/monster/Ghast.java
index 605c47f3bd5c4e72389587d50e70fcd57f2a2b27..b8774eb91d21e9f154cc70c5d3bd26de25be41c4 100644
--- a/net/minecraft/world/entity/monster/Ghast.java
+++ b/net/minecraft/world/entity/monster/Ghast.java
@@ -156,6 +156,11 @@ public class Ghast extends Mob implements Enemy {
public static boolean checkGhastSpawnRules(
EntityType<Ghast> entityType, LevelAccessor level, EntitySpawnReason spawnReason, BlockPos pos, RandomSource random
) {
+ // Purpur start - Config to disable hostile mob spawn on ice
+ if (net.minecraft.world.entity.monster.Monster.canSpawnInBlueAndPackedIce(level, pos)) {
+ return false;
+ }
+ // Purpur end - Config to disable hostile mob spawn on ice
return level.getDifficulty() != Difficulty.PEACEFUL && random.nextInt(20) == 0 && checkMobSpawnRules(entityType, level, spawnReason, pos, random);
}

View File

@@ -1,23 +0,0 @@
From 56a0a83ddb1b7472dbc9762e2aca396605c62085 Mon Sep 17 00:00:00 2001
From: File <noreply+automated@papermc.io>
Date: Sun, 20 Apr 1997 05:37:42 -0800
Subject: [PATCH] purpur File Patches
diff --git a/net/minecraft/world/entity/monster/Phantom.java b/net/minecraft/world/entity/monster/Phantom.java
index 62c40a04a105eff471599c4535239fee9726dbd1..d26b7970490a2a108affee11c3fb74e38509d92b 100644
--- a/net/minecraft/world/entity/monster/Phantom.java
+++ b/net/minecraft/world/entity/monster/Phantom.java
@@ -166,7 +166,11 @@ public class Phantom extends Mob implements Enemy {
ServerLevelAccessor level, DifficultyInstance difficulty, EntitySpawnReason spawnReason, @Nullable SpawnGroupData spawnGroupData
) {
this.anchorPoint = this.blockPosition().above(5);
- this.setPhantomSize(0);
+ // Purpur start - Configurable phantom size
+ int min = level.getLevel().purpurConfig.phantomMinSize;
+ int max = level.getLevel().purpurConfig.phantomMaxSize;
+ this.setPhantomSize(min == max ? min : level.getRandom().nextInt(max + 1 - min) + min);
+ // Purpur end - Configurable phantom size
return super.finalizeSpawn(level, difficulty, spawnReason, spawnGroupData);
}

View File

@@ -1,67 +0,0 @@
From 56a0a83ddb1b7472dbc9762e2aca396605c62085 Mon Sep 17 00:00:00 2001
From: File <noreply+automated@papermc.io>
Date: Sun, 20 Apr 1997 05:37:42 -0800
Subject: [PATCH] purpur File Patches
diff --git a/net/minecraft/world/entity/monster/Shulker.java b/net/minecraft/world/entity/monster/Shulker.java
index 935c608ba0fc2246a3f79bf4865cfeb6fe68b0f4..6e8400c4d523da8799d586c5c9019ae78710fbcb 100644
--- a/net/minecraft/world/entity/monster/Shulker.java
+++ b/net/minecraft/world/entity/monster/Shulker.java
@@ -93,6 +93,21 @@ public class Shulker extends AbstractGolem implements Enemy {
this.lookControl = new Shulker.ShulkerLookControl(this);
}
+ // Purpur start - Shulker change color with dye
+ @Override
+ protected net.minecraft.world.InteractionResult mobInteract(Player player, net.minecraft.world.InteractionHand hand) {
+ net.minecraft.world.item.ItemStack itemstack = player.getItemInHand(hand);
+ if (player.level().purpurConfig.shulkerChangeColorWithDye && itemstack.getItem() instanceof net.minecraft.world.item.DyeItem dye && dye.getDyeColor() != this.getColor()) {
+ this.setVariant(Optional.of(dye.getDyeColor()));
+ if (!player.getAbilities().instabuild) {
+ itemstack.shrink(1);
+ }
+ return net.minecraft.world.InteractionResult.SUCCESS;
+ }
+ return super.mobInteract(player, hand);
+ }
+ // Purpur end - Shulker change color with dye
+
@Override
protected void registerGoals() {
this.goalSelector.addGoal(1, new LookAtPlayerGoal(this, Player.class, 8.0F, 0.02F, true));
@@ -454,11 +469,21 @@ public class Shulker extends AbstractGolem implements Enemy {
private void hitByShulkerBullet() {
Vec3 vec3 = this.position();
AABB boundingBox = this.getBoundingBox();
- if (!this.isClosed() && this.teleportSomewhere()) {
- int size = this.level().getEntities(EntityType.SHULKER, boundingBox.inflate(8.0), Entity::isAlive).size();
- float f = (size - 1) / 5.0F;
- if (!(this.level().random.nextFloat() < f)) {
+ // Purpur start - Shulker spawn from bullet options
+ if ((!this.level().purpurConfig.shulkerSpawnFromBulletRequireOpenLid || !this.isClosed()) && this.teleportSomewhere()) {
+ float chance = this.level().purpurConfig.shulkerSpawnFromBulletBaseChance;
+ if (!this.level().purpurConfig.shulkerSpawnFromBulletNearbyEquation.isBlank()) {
+ int nearby = this.level().getEntities((net.minecraft.world.level.entity.EntityTypeTest) EntityType.SHULKER, boundingBox.inflate(this.level().purpurConfig.shulkerSpawnFromBulletNearbyRange), Entity::isAlive).size();
+ try {
+ chance -= ((Number) scriptEngine.eval("let nearby = " + nearby + "; " + this.level().purpurConfig.shulkerSpawnFromBulletNearbyEquation)).floatValue();
+ } catch (javax.script.ScriptException e) {
+ e.printStackTrace();
+ chance -= (nearby - 1) / 5.0F;
+ }
+ }
+ if (this.level().random.nextFloat() <= chance) {
Shulker shulker = EntityType.SHULKER.create(this.level(), EntitySpawnReason.BREEDING);
+ // Purpur end - Shulker spawn from bullet options
if (shulker != null) {
shulker.setVariant(this.getVariant());
shulker.snapTo(vec3);
@@ -565,7 +590,7 @@ public class Shulker extends AbstractGolem implements Enemy {
}
public Optional<DyeColor> getVariant() {
- return Optional.ofNullable(this.getColor());
+ return Optional.ofNullable(this.level().purpurConfig.shulkerSpawnFromBulletRandomColor ? DyeColor.random(this.level().random) : this.getColor()); // Purpur - Shulker spawn from bullet options
}
public @Nullable DyeColor getColor() {

View File

@@ -1,36 +0,0 @@
From 56a0a83ddb1b7472dbc9762e2aca396605c62085 Mon Sep 17 00:00:00 2001
From: File <noreply+automated@papermc.io>
Date: Sun, 20 Apr 1997 05:37:42 -0800
Subject: [PATCH] purpur File Patches
diff --git a/net/minecraft/world/entity/monster/piglin/PiglinAi.java b/net/minecraft/world/entity/monster/piglin/PiglinAi.java
index 436b17a709517766fdb9d7198f0ae457facd90a1..49294ccf5c4ac3acf7793c8d7cbc449a0d0f44e6 100644
--- a/net/minecraft/world/entity/monster/piglin/PiglinAi.java
+++ b/net/minecraft/world/entity/monster/piglin/PiglinAi.java
@@ -660,7 +660,10 @@ public class PiglinAi {
public static boolean isWearingSafeArmor(LivingEntity entity) {
for (EquipmentSlot equipmentSlot : EquipmentSlotGroup.ARMOR) {
- if (entity.getItemBySlot(equipmentSlot).is(ItemTags.PIGLIN_SAFE_ARMOR)) {
+ // Purpur start - piglins ignore gold-trimmed armor
+ net.minecraft.world.item.ItemStack itemStack = entity.getItemBySlot(equipmentSlot);
+ if (itemStack.is(ItemTags.PIGLIN_SAFE_ARMOR) || (entity.level().purpurConfig.piglinIgnoresArmorWithGoldTrim && isWearingGoldTrim(itemStack))) {
+ // Purpur end - piglins ignore gold-trimmed armor
return true;
}
}
@@ -668,6 +671,13 @@ public class PiglinAi {
return false;
}
+ // Purpur start - piglins ignore gold-trimmed armor
+ private static boolean isWearingGoldTrim(net.minecraft.world.item.ItemStack itemstack) {
+ net.minecraft.world.item.equipment.trim.ArmorTrim armorTrim = itemstack.getComponents().get(net.minecraft.core.component.DataComponents.TRIM);
+ return armorTrim != null && armorTrim.material().is(net.minecraft.world.item.equipment.trim.TrimMaterials.GOLD);
+ }
+ // Purpur end - piglins ignore gold-trimmed armor
+
private static void stopWalking(Piglin piglin) {
piglin.getBrain().eraseMemory(MemoryModuleType.WALK_TARGET);
piglin.getNavigation().stop();

View File

@@ -1,29 +0,0 @@
From 56a0a83ddb1b7472dbc9762e2aca396605c62085 Mon Sep 17 00:00:00 2001
From: File <noreply+automated@papermc.io>
Date: Sun, 20 Apr 1997 05:37:42 -0800
Subject: [PATCH] purpur File Patches
diff --git a/net/minecraft/world/entity/npc/wanderingtrader/WanderingTraderSpawner.java b/net/minecraft/world/entity/npc/wanderingtrader/WanderingTraderSpawner.java
index 44b43ca9fba989f975133f966cedd582a93d3350..7aef337fc0b6fd52c27ad5ca3f38d74f213d9725 100644
--- a/net/minecraft/world/entity/npc/wanderingtrader/WanderingTraderSpawner.java
+++ b/net/minecraft/world/entity/npc/wanderingtrader/WanderingTraderSpawner.java
@@ -134,7 +134,17 @@ public class WanderingTraderSpawner implements CustomSpawner {
int i1 = pos.getX() + this.random.nextInt(maxDistance * 2) - maxDistance;
int i2 = pos.getZ() + this.random.nextInt(maxDistance * 2) - maxDistance;
int height = level.getHeight(Heightmap.Types.WORLD_SURFACE, i1, i2);
- BlockPos blockPos1 = new BlockPos(i1, height, i2);
+ // Purpur start - Allow toggling special MobSpawners per world - allow traders to spawn below nether roof
+ BlockPos.MutableBlockPos blockPos1 = new BlockPos.MutableBlockPos(i1, height, i2);
+ if (level.dimensionType().hasCeiling()) {
+ do {
+ blockPos1.relative(net.minecraft.core.Direction.DOWN);
+ } while (!level.getBlockState(blockPos1).isAir());
+ do {
+ blockPos1.relative(net.minecraft.core.Direction.DOWN);
+ } while (level.getBlockState(blockPos1).isAir() && blockPos1.getY() > 0);
+ }
+ // Purpur end - Allow toggling special MobSpawners per world
if (placementType.isSpawnPositionOk(level, blockPos1, EntityType.WANDERING_TRADER)) {
blockPos = blockPos1;
break;

View File

@@ -1,25 +0,0 @@
From 56a0a83ddb1b7472dbc9762e2aca396605c62085 Mon Sep 17 00:00:00 2001
From: File <noreply+automated@papermc.io>
Date: Sun, 20 Apr 1997 05:37:42 -0800
Subject: [PATCH] purpur File Patches
diff --git a/net/minecraft/world/inventory/AbstractFurnaceMenu.java b/net/minecraft/world/inventory/AbstractFurnaceMenu.java
index 6e13b05ebd924d98066624d9ff6ee7f61e248617..9304bc239ffafbef3b34c5a5a42039c86acd5e80 100644
--- a/net/minecraft/world/inventory/AbstractFurnaceMenu.java
+++ b/net/minecraft/world/inventory/AbstractFurnaceMenu.java
@@ -121,7 +121,13 @@ public abstract class AbstractFurnaceMenu extends RecipeBookMenu {
} else if (slotIndex != 1 && slotIndex != 0) {
if (this.canSmelt(item)) {
if (!this.moveItemStackTo(item, 0, 1, false)) {
- return ItemStack.EMPTY;
+ // Purpur start - Added the ability to add combustible items
+ if (this.isFuel(item)) {
+ if (!this.moveItemStackTo(item, 1, 2, false)) {
+ return ItemStack.EMPTY;
+ }
+ }
+ // Purpur end - Added the ability to add combustible items
}
} else if (this.isFuel(item)) {
if (!this.moveItemStackTo(item, 1, 2, false)) {

View File

@@ -1,19 +0,0 @@
From 56a0a83ddb1b7472dbc9762e2aca396605c62085 Mon Sep 17 00:00:00 2001
From: File <noreply+automated@papermc.io>
Date: Sun, 20 Apr 1997 05:37:42 -0800
Subject: [PATCH] purpur File Patches
diff --git a/net/minecraft/world/inventory/ArmorSlot.java b/net/minecraft/world/inventory/ArmorSlot.java
index f9fef56709a40e2581170a807a0035b593795b05..cdc95952311e6a2df757c3d8ec1224e3e5ad3069 100644
--- a/net/minecraft/world/inventory/ArmorSlot.java
+++ b/net/minecraft/world/inventory/ArmorSlot.java
@@ -46,7 +46,7 @@ class ArmorSlot extends Slot {
@Override
public boolean mayPickup(Player player) {
ItemStack item = this.getItem();
- return (item.isEmpty() || player.isCreative() || !EnchantmentHelper.has(item, EnchantmentEffectComponents.PREVENT_ARMOR_CHANGE))
+ return (item.isEmpty() || player.isCreative() || (!EnchantmentHelper.has(item, EnchantmentEffectComponents.PREVENT_ARMOR_CHANGE) || player.level().purpurConfig.playerRemoveBindingWithWeakness && player.hasEffect(net.minecraft.world.effect.MobEffects.WEAKNESS))) // Purpur - Config to remove curse of binding with weakness
&& super.mayPickup(player);
}

View File

@@ -1,20 +0,0 @@
From 56a0a83ddb1b7472dbc9762e2aca396605c62085 Mon Sep 17 00:00:00 2001
From: File <noreply+automated@papermc.io>
Date: Sun, 20 Apr 1997 05:37:42 -0800
Subject: [PATCH] purpur File Patches
diff --git a/net/minecraft/world/inventory/ItemCombinerMenu.java b/net/minecraft/world/inventory/ItemCombinerMenu.java
index 1296631fc74e83e6c9d6af0cd46d12d9851a30b1..e6c3a0086963298be31befbbbf8d42e85f379c79 100644
--- a/net/minecraft/world/inventory/ItemCombinerMenu.java
+++ b/net/minecraft/world/inventory/ItemCombinerMenu.java
@@ -156,7 +156,9 @@ public abstract class ItemCombinerMenu extends AbstractContainerMenu {
return ItemStack.EMPTY;
}
+ this.activeQuickItem = itemStack; // Purpur - Anvil API
slot.onTake(player, item);
+ this.activeQuickItem = null; // Purpur - Anvil API
}
return itemStack;

View File

@@ -1,41 +0,0 @@
From 56a0a83ddb1b7472dbc9762e2aca396605c62085 Mon Sep 17 00:00:00 2001
From: File <noreply+automated@papermc.io>
Date: Sun, 20 Apr 1997 05:37:42 -0800
Subject: [PATCH] purpur File Patches
diff --git a/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java b/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java
index 1215ac44fd30dc872f9d319be34e5e08ba880ea2..c0bb687b94f3baa9ffda9c47c69a1d6d244acd4e 100644
--- a/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java
+++ b/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java
@@ -187,6 +187,21 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit
}
ItemStack itemStack = furnace.items.get(1);
+ // Purpur start - Furnace uses lava from underneath
+ boolean usedLavaFromUnderneath = false;
+ if (level.purpurConfig.furnaceUseLavaFromUnderneath && !furnace.isLit() && itemStack.isEmpty() && !furnace.items.get(0).isEmpty() && level.getGameTime() % 20 == 0) {
+ BlockPos below = furnace.getBlockPos().below();
+ BlockState belowState = level.getBlockStateIfLoaded(below);
+ if (belowState != null && belowState.is(Blocks.LAVA)) {
+ net.minecraft.world.level.material.FluidState fluidState = belowState.getFluidState();
+ if (fluidState != null && fluidState.isSource()) {
+ level.setBlock(below, Blocks.AIR.defaultBlockState(), 3);
+ itemStack = Items.LAVA_BUCKET.getDefaultInstance();
+ usedLavaFromUnderneath = true;
+ }
+ }
+ }
+ // Purpur end - Furnace uses lava from underneath
ItemStack itemStack1 = furnace.items.get(0);
boolean flag1 = !itemStack1.isEmpty();
boolean flag2 = !itemStack.isEmpty();
@@ -270,6 +285,8 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit
if (flag) {
setChanged(level, pos, state);
}
+
+ if (usedLavaFromUnderneath) furnace.items.set(1, ItemStack.EMPTY); // Purpur - Furnace uses lava from underneath
}
private static boolean canBurn(

View File

@@ -1,66 +0,0 @@
From 56a0a83ddb1b7472dbc9762e2aca396605c62085 Mon Sep 17 00:00:00 2001
From: File <noreply+automated@papermc.io>
Date: Sun, 20 Apr 1997 05:37:42 -0800
Subject: [PATCH] purpur File Patches
diff --git a/net/minecraft/world/level/block/entity/BeaconBlockEntity.java b/net/minecraft/world/level/block/entity/BeaconBlockEntity.java
index 0db33d7e1227e914326e9eb3b50338b001872938..cc301cff64e1bf604a1432f6e36be8aa17db53e7 100644
--- a/net/minecraft/world/level/block/entity/BeaconBlockEntity.java
+++ b/net/minecraft/world/level/block/entity/BeaconBlockEntity.java
@@ -138,6 +138,16 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider, Name
public double getEffectRange() {
if (this.effectRange < 0) {
+ // Purpur start - Beacon Activation Range Configurable
+ if (this.level != null) {
+ switch (this.levels) {
+ case 1: return this.level.purpurConfig.beaconLevelOne;
+ case 2: return this.level.purpurConfig.beaconLevelTwo;
+ case 3: return this.level.purpurConfig.beaconLevelThree;
+ case 4: return this.level.purpurConfig.beaconLevelFour;
+ }
+ }
+ // Purpur end - Beacon Activation Range Configurable
return this.levels * 10 + 10;
} else {
return effectRange;
@@ -166,6 +176,7 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider, Name
int y = pos.getY();
int z = pos.getZ();
BlockPos blockPos;
+ boolean isTintedGlass = false; // Purpur - allow beacon effects when covered by tinted glass
if (blockEntity.lastCheckY < y) {
blockPos = pos;
blockEntity.checkingBeamSections = Lists.newArrayList();
@@ -195,11 +206,15 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider, Name
}
}
} else {
- if (section == null || blockState.getLightBlock() >= 15 && !blockState.is(Blocks.BEDROCK)) {
+ if (level.purpurConfig.beaconAllowEffectsWithTintedGlass && blockState.getBlock().equals(Blocks.TINTED_GLASS)) {isTintedGlass = true;} // Purpur - allow beacon effects when covered by tinted glass
+ // Purpur start - fix effects being applied when tinted glass is covered
+ if (section == null || blockState.getLightBlock() >= 15 && !blockState.is(Blocks.BEDROCK) && !(blockState.getBlock().equals(Blocks.TINTED_GLASS) && level.purpurConfig.beaconAllowEffectsWithTintedGlass)) {
blockEntity.checkingBeamSections.clear();
blockEntity.lastCheckY = height;
+ isTintedGlass = false;
break;
}
+ // Purpur end - fix effects being applied when tinted glass is covered
section.increaseHeight();
}
@@ -210,11 +225,11 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider, Name
int i = blockEntity.levels; final int originalLevels = i; // Paper - OBFHELPER
if (level.getGameTime() % 80L == 0L) {
- if (!blockEntity.beamSections.isEmpty()) {
+ if (!blockEntity.beamSections.isEmpty() || (level.purpurConfig.beaconAllowEffectsWithTintedGlass && isTintedGlass)) { // Purpur - fix beacon effects persisting with broken base while tinted glass is used
blockEntity.levels = updateBase(level, x, y, z);
}
- if (blockEntity.levels > 0 && !blockEntity.beamSections.isEmpty()) {
+ if (blockEntity.levels > 0 && (!blockEntity.beamSections.isEmpty() || (level.purpurConfig.beaconAllowEffectsWithTintedGlass && isTintedGlass))) { // Purpur - allow beacon effects when covered by tinted glass
applyEffects(level, pos, blockEntity.levels, blockEntity.primaryPower, blockEntity.secondaryPower, blockEntity); // Paper - Custom beacon ranges
playSound(level, pos, SoundEvents.BEACON_AMBIENT);
}

View File

@@ -1,74 +0,0 @@
From 56a0a83ddb1b7472dbc9762e2aca396605c62085 Mon Sep 17 00:00:00 2001
From: File <noreply+automated@papermc.io>
Date: Sun, 20 Apr 1997 05:37:42 -0800
Subject: [PATCH] purpur File Patches
diff --git a/net/minecraft/world/level/block/entity/ConduitBlockEntity.java b/net/minecraft/world/level/block/entity/ConduitBlockEntity.java
index be4b46d56ca67cb5c0fac5e0bbc9456fb5552d78..816d9a0f7f35b95b369ffbfc02e4d1f306b814c5 100644
--- a/net/minecraft/world/level/block/entity/ConduitBlockEntity.java
+++ b/net/minecraft/world/level/block/entity/ConduitBlockEntity.java
@@ -150,7 +150,7 @@ public class ConduitBlockEntity extends BlockEntity {
BlockPos blockPos1 = pos.offset(i, i1, i2x);
BlockState blockState = level.getBlockState(blockPos1);
- for (Block block : VALID_BLOCKS) {
+ for (Block block : level.purpurConfig.conduitBlocks) { // Purpur - Conduit behavior configuration
if (blockState.is(block)) {
positions.add(blockPos1);
}
@@ -165,13 +165,13 @@ public class ConduitBlockEntity extends BlockEntity {
private static void applyEffects(Level level, BlockPos pos, List<BlockPos> positions) {
// CraftBukkit start
- ConduitBlockEntity.applyEffects(level, pos, ConduitBlockEntity.getRange(positions));
+ ConduitBlockEntity.applyEffects(level, pos, ConduitBlockEntity.getRange(positions, level)); // Purpur - Conduit behavior configuration
}
- public static int getRange(List<BlockPos> positions) {
+ public static int getRange(List<BlockPos> positions, Level level) { // Purpur - Conduit behavior configuration
// CraftBukkit end
int size = positions.size();
- int i = size / 7 * 16;
+ int i = size / 7 * level.purpurConfig.conduitDistance; // Purpur - Conduit behavior configuration
// CraftBukkit start
return i;
}
@@ -201,7 +201,7 @@ public class ConduitBlockEntity extends BlockEntity {
EntityReference<LivingEntity> entityReference = updateDestroyTarget(blockEntity.destroyTarget, level, pos, canDestroy);
LivingEntity livingEntity = EntityReference.getLivingEntity(entityReference, level);
if (damageTarget && livingEntity != null) { // CraftBukkit
- if (livingEntity.hurtServer(level, level.damageSources().magic().eventBlockDamager(level, pos), 4.0F)) // CraftBukkit - move up
+ if (livingEntity.hurtServer(level, level.damageSources().magic().eventBlockDamager(level, pos), level.purpurConfig.conduitDamageAmount)) // CraftBukkit - move up // Purpur - Conduit behavior configuration
level.playSound(
null, livingEntity.getX(), livingEntity.getY(), livingEntity.getZ(), SoundEvents.CONDUIT_ATTACK_TARGET, SoundSource.BLOCKS, 1.0F, 1.0F
);
@@ -222,19 +222,25 @@ public class ConduitBlockEntity extends BlockEntity {
return selectNewTarget(level, pos);
} else {
LivingEntity livingEntity = EntityReference.getLivingEntity(destroyTarget, level);
- return livingEntity != null && livingEntity.isAlive() && pos.closerThan(livingEntity.blockPosition(), 8.0) ? destroyTarget : null;
+ return livingEntity != null && livingEntity.isAlive() && pos.closerThan(livingEntity.blockPosition(), level.purpurConfig.conduitDamageDistance) ? destroyTarget : null; // Purpur - Conduit behavior configuration
}
}
private static @Nullable EntityReference<LivingEntity> selectNewTarget(ServerLevel level, BlockPos pos) {
List<LivingEntity> entitiesOfClass = level.getEntitiesOfClass(
- LivingEntity.class, getDestroyRangeAABB(pos), livingEntity -> livingEntity instanceof Enemy && livingEntity.isInWaterOrRain()
+ LivingEntity.class, getDestroyRangeAABB(pos, level), livingEntity -> livingEntity instanceof Enemy && livingEntity.isInWaterOrRain() // Purpur - Conduit behavior configuration
);
return entitiesOfClass.isEmpty() ? null : EntityReference.of(Util.getRandom(entitiesOfClass, level.random));
}
public static AABB getDestroyRangeAABB(BlockPos pos) {
- return new AABB(pos).inflate(8.0);
+ // Purpur start - Conduit behavior configuration
+ return getDestroyRangeAABB(pos, null);
+ }
+
+ private static AABB getDestroyRangeAABB(BlockPos pos, Level level) {
+ // Purpur end - Conduit behavior configuration
+ return new AABB(pos).inflate(level == null ? 8.0 : level.purpurConfig.conduitDamageDistance); // Purpur - Conduit behavior configuration
}
private static void animationTick(Level level, BlockPos pos, List<BlockPos> positions, @Nullable Entity entity, int tickCount) {

View File

@@ -1,14 +1,6 @@
From 56a0a83ddb1b7472dbc9762e2aca396605c62085 Mon Sep 17 00:00:00 2001
From: File <noreply+automated@papermc.io>
Date: Sun, 20 Apr 1997 05:37:42 -0800
Subject: [PATCH] purpur File Patches
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
index ca2caace6aab0dfcb0ab7a0fd28e66555c62fdc5..7a54f6bc2a364c1d3ac1ed58b33ecf720a305840 100644
--- a/net/minecraft/server/MinecraftServer.java
+++ b/net/minecraft/server/MinecraftServer.java
@@ -290,6 +290,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -319,6 +_,7 @@
public joptsimple.OptionSet options;
public org.bukkit.command.ConsoleCommandSender console;
public static int currentTick; // Paper - improve tick loop
@@ -16,7 +8,7 @@ index ca2caace6aab0dfcb0ab7a0fd28e66555c62fdc5..7a54f6bc2a364c1d3ac1ed58b33ecf72
public java.util.Queue<Runnable> processQueue = new java.util.concurrent.ConcurrentLinkedQueue<Runnable>();
public int autosavePeriod;
// Paper - don't store the vanilla dispatcher
@@ -306,6 +307,8 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -335,6 +_,8 @@
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 static final long SERVER_INIT = System.nanoTime(); // Paper - Lag compensation
@@ -25,7 +17,7 @@ index ca2caace6aab0dfcb0ab7a0fd28e66555c62fdc5..7a54f6bc2a364c1d3ac1ed58b33ecf72
// Paper start - improve tick loop
public final ca.spottedleaf.moonrise.common.time.TickData tickTimes1s = new ca.spottedleaf.moonrise.common.time.TickData(java.util.concurrent.TimeUnit.SECONDS.toNanos(1L));
public final ca.spottedleaf.moonrise.common.time.TickData tickTimes5s = new ca.spottedleaf.moonrise.common.time.TickData(java.util.concurrent.TimeUnit.SECONDS.toNanos(5L));
@@ -375,6 +378,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -404,6 +_,7 @@
public double[] computeTPS() {
final long interval = this.tickRateManager().nanosecondsPerTick();
return new double[] {
@@ -33,7 +25,7 @@ index ca2caace6aab0dfcb0ab7a0fd28e66555c62fdc5..7a54f6bc2a364c1d3ac1ed58b33ecf72
getTPS(this.tickTimes1m, interval),
getTPS(this.tickTimes5m, interval),
getTPS(this.tickTimes15m, interval)
@@ -1014,6 +1018,15 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -925,6 +_,15 @@
LOGGER.info("Stopping server");
Commands.COMMAND_SENDING_POOL.shutdownNow(); // Paper - Perf: Async command map building; Shutdown and don't bother finishing
@@ -49,16 +41,16 @@ index ca2caace6aab0dfcb0ab7a0fd28e66555c62fdc5..7a54f6bc2a364c1d3ac1ed58b33ecf72
// CraftBukkit start
if (this.server != null) {
this.server.spark.disable(); // Paper - spark
@@ -1107,6 +1120,8 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
this.safeShutdown(waitForShutdown, false);
@@ -1014,6 +_,8 @@
this.safeShutdown(wait, false);
}
public void safeShutdown(boolean waitForShutdown, boolean isRestarting) {
public void safeShutdown(final boolean wait, final 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
@@ -1284,11 +1299,21 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
if (this.isDebugging()) io.papermc.paper.util.TraceUtil.dumpTraceForThread("Server stopped"); // Paper - Debugging
@@ -1176,11 +_,21 @@
}
// Paper end - Add onboarding message for initial server start
// Paper start - Improve outdated version checking
@@ -80,9 +72,9 @@ index ca2caace6aab0dfcb0ab7a0fd28e66555c62fdc5..7a54f6bc2a364c1d3ac1ed58b33ecf72
+
while (this.running) {
final long tickStart = System.nanoTime(); // Paper - improve tick loop
long l; // Paper - improve tick loop - diff on change, expect this to be tick interval
@@ -1302,9 +1327,11 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
final long ticksBehind = Math.max(1L, this.tickSchedule.getPeriodsAhead(l, tickStart));
long thisTickNanos; // Paper - improve tick loop - diff on change, expect this to be tick interval
@@ -1194,9 +_,11 @@
final long ticksBehind = Math.max(1L, this.tickSchedule.getPeriodsAhead(thisTickNanos, tickStart));
final long catchup = (long)Math.max(
1,
- 5 //ConfigHolder.getConfig().tickLoop.catchupTicks.getOrDefault(MoonriseConfig.TickLoop.DEFAULT_CATCHUP_TICKS).intValue()
@@ -94,21 +86,12 @@ index ca2caace6aab0dfcb0ab7a0fd28e66555c62fdc5..7a54f6bc2a364c1d3ac1ed58b33ecf72
// adjust ticksBehind so that it is not greater-than catchup
if (ticksBehind > catchup) {
final long difference = ticksBehind - catchup;
@@ -1785,7 +1812,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
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;
@@ -1784,7 +_,7 @@
}
ServerPlayer entityplayer = (ServerPlayer) entityhuman;
@@ -1952,7 +1979,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@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) {
public ServerClockManager clockManager() {

View File

@@ -1,29 +1,21 @@
From 56a0a83ddb1b7472dbc9762e2aca396605c62085 Mon Sep 17 00:00:00 2001
From: File <noreply+automated@papermc.io>
Date: Sun, 20 Apr 1997 05:37:42 -0800
Subject: [PATCH] purpur File Patches
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
index dc65503a2d785d64d37b76b0303f51cf66d9769a..5130c0067f01eec31c69b9e71d904f932943b922 100644
--- a/net/minecraft/server/level/ServerLevel.java
+++ b/net/minecraft/server/level/ServerLevel.java
@@ -218,6 +218,8 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
@@ -219,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;
final LevelDebugSynchronizers debugSynchronizers = new LevelDebugSynchronizers(this);
private final LevelDebugSynchronizers debugSynchronizers = new LevelDebugSynchronizers(this);
@@ -622,8 +624,25 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
// CraftBukkit start
@@ -377,8 +_,25 @@
// CraftBukkit end
this.tickTime = tickTime;
this.server = server;
- this.customSpawners = customSpawners;
+ this.customSpawners = new ArrayList<>(); // Purpur - Allow toggling special MobSpawners per world
this.serverLevelData = serverLevelData;
this.serverLevelData = levelData;
+ // Purpur start - Allow toggling special MobSpawners per world
+ if (purpurConfig.phantomSpawning) {
+ this.customSpawners.add(new net.minecraft.world.level.levelgen.PhantomSpawner());
@@ -38,69 +30,33 @@ index dc65503a2d785d64d37b76b0303f51cf66d9769a..5130c0067f01eec31c69b9e71d904f93
+ this.customSpawners.add(new net.minecraft.world.entity.ai.village.VillageSiege());
+ }
+ if (purpurConfig.villagerTraderSpawning) {
+ this.customSpawners.add(new net.minecraft.world.entity.npc.wanderingtrader.WanderingTraderSpawner(serverLevelData));
+ this.customSpawners.add(new net.minecraft.world.entity.npc.wanderingtrader.WanderingTraderSpawner(levelData));
+ }
+ // Purpur end - Allow toggling special MobSpawners per world
ChunkGenerator chunkGenerator = levelStem.generator();
ChunkGenerator generator = levelStem.generator();
// CraftBukkit start
this.serverLevelData.setWorld(this);
@@ -709,6 +728,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
this.chunkDataController = new ca.spottedleaf.moonrise.patches.chunk_system.io.datacontroller.ChunkDataController((ServerLevel)(Object)this, this.chunkTaskScheduler);
// Paper end - rewrite chunk system
@@ -463,6 +_,7 @@
this.environmentAttributes = EnvironmentAttributeSystem.builder().addDefaultLayers(this).build();
this.updateSkyBrightness();
this.getCraftServer().addWorld(this.getWorld()); // CraftBukkit
+ this.preciseTime = this.serverLevelData.getDayTime(); // Purpur - Configurable daylight cycle
}
// Paper start
@@ -760,7 +780,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
@@ -519,7 +_,7 @@
}
int i = this.getGameRules().get(GameRules.PLAYERS_SLEEPING_PERCENTAGE);
- if (this.sleepStatus.areEnoughSleeping(i) && this.sleepStatus.areEnoughDeepSleeping(i, this.players)) {
+ if (this.purpurConfig.playersSkipNight && this.sleepStatus.areEnoughSleeping(i) && this.sleepStatus.areEnoughDeepSleeping(i, 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(
@@ -895,6 +915,13 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
this.serverLevelData.getScheduledEvents().tick(this.server, l);
Profiler.get().pop();
if (this.getGameRules().get(GameRules.ADVANCE_TIME)) {
+ // Purpur start - Configurable daylight cycle
+ int incrementTicks = isBrightOutside() ? 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);
}
}
@@ -902,6 +929,20 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
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 long getDayCount() {
@@ -1010,9 +1051,17 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
&& 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(BlockTags.LIGHTNING_RODS);
if (flag) {
- SkeletonHorse skeletonHorse = EntityType.SKELETON_HORSE.create(this, EntitySpawnReason.EVENT);
int percentage = this.getGameRules().get(GameRules.PLAYERS_SLEEPING_PERCENTAGE);
- if (this.sleepStatus.areEnoughSleeping(percentage) && this.sleepStatus.areEnoughDeepSleeping(percentage, this.players)) {
+ if (this.purpurConfig.playersSkipNight && this.sleepStatus.areEnoughSleeping(percentage) && this.sleepStatus.areEnoughDeepSleeping(percentage, this.players)) { // Purpur - Config for skipping night
Optional<Holder<WorldClock>> defaultClock = this.dimensionType().defaultClock();
org.bukkit.event.world.TimeSkipEvent event = null; // Paper - time skip event
if (this.getGameRules().get(GameRules.ADVANCE_TIME) && defaultClock.isPresent()) {
@@ -725,9 +_,18 @@
&& this.random.nextDouble() < difficulty.getEffectiveDifficulty() * this.paperConfig().entities.spawning.skeletonHorseThunderSpawnChance.or(0.01) // Paper - Configurable spawn chances for skeleton horses
&& !this.getBlockState(pos.below()).is(BlockTags.LIGHTNING_RODS);
if (isTrap) {
+ // Purpur start - Special mobs naturally spawn
+ net.minecraft.world.entity.animal.equine.AbstractHorse skeletonHorse;
+ if (purpurConfig.zombieHorseSpawnChance > 0D && random.nextDouble() <= purpurConfig.zombieHorseSpawnChance) {
@@ -110,16 +66,17 @@ index dc65503a2d785d64d37b76b0303f51cf66d9769a..5130c0067f01eec31c69b9e71d904f93
+ if (skeletonHorse != null) ((SkeletonHorse) skeletonHorse).setTrap(true);
+ }
+ // Purpur end - Special mobs naturally spawn
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
@@ -1047,9 +1096,35 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
if (blockState.is(Blocks.SNOW)) {
int layersValue = blockState.getValue(SnowLayerBlock.LAYERS);
if (layersValue < Math.min(i, 8)) {
SkeletonHorse horse = EntityType.SKELETON_HORSE.create(this, EntitySpawnReason.EVENT);
if (horse != null) {
- horse.setTrap(true);
+ //horse.setTrap(true); // Purpur - Special mobs naturally spawn - moved up
horse.setAge(0);
horse.setPos(pos.getX(), pos.getY(), pos.getZ());
this.addFreshEntity(horse, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.LIGHTNING); // CraftBukkit
@@ -762,9 +_,35 @@
if (state.is(Blocks.SNOW)) {
int currentLayers = state.getValue(SnowLayerBlock.LAYERS);
if (currentLayers < Math.min(maxHeight, 8)) {
+ // Purpur start - Smooth snow accumulation
+ boolean canSnow = true;
+ // Ensure snow doesn't get more than N layers taller than its neighbors
@@ -145,67 +102,67 @@ index dc65503a2d785d64d37b76b0303f51cf66d9769a..5130c0067f01eec31c69b9e71d904f93
+ }
+ if (canSnow) {
+ // Purpur end - Smooth snow accumulation
BlockState blockState1 = blockState.setValue(SnowLayerBlock.LAYERS, layersValue + 1);
Block.pushEntitiesUp(blockState, blockState1, this, heightmapPos);
org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(this, heightmapPos, blockState1, Block.UPDATE_ALL, null); // CraftBukkit
BlockState newState = state.setValue(SnowLayerBlock.LAYERS, currentLayers + 1);
Block.pushEntitiesUp(state, newState, this, topPos);
org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(this, topPos, newState, Block.UPDATE_ALL, null); // CraftBukkit
+ } // Purpur - Smooth snow accumulation
}
} else {
org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(this, heightmapPos, Blocks.SNOW.defaultBlockState(), Block.UPDATE_ALL, null); // CraftBukkit
@@ -1070,7 +1145,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
poiType -> poiType.is(PoiTypes.LIGHTNING_ROD),
blockPos -> blockPos.getY() == this.getHeight(Heightmap.Types.WORLD_SURFACE, blockPos.getX(), blockPos.getZ()) - 1,
pos,
org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(this, topPos, Blocks.SNOW.defaultBlockState(), Block.UPDATE_ALL, null); // CraftBukkit
@@ -785,7 +_,7 @@
p -> p.is(PoiTypes.LIGHTNING_ROD),
lightningRodPos -> lightningRodPos.getY() == this.getHeight(Heightmap.Types.WORLD_SURFACE, lightningRodPos.getX(), lightningRodPos.getZ()) - 1,
center,
- 128,
+ org.purpurmc.purpur.PurpurConfig.lightningRodRange, // Purpur - Make lightning rod range configurable
PoiManager.Occupancy.ANY
);
return optional.map(blockPos -> blockPos.above(1));
@@ -1119,8 +1194,26 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
int i = this.getGameRules().get(GameRules.PLAYERS_SLEEPING_PERCENTAGE);
Component component;
if (this.sleepStatus.areEnoughSleeping(i)) {
return nearbyLightningRod.map(blockPos -> blockPos.above(1));
@@ -833,8 +_,26 @@
int percentage = this.getGameRules().get(GameRules.PLAYERS_SLEEPING_PERCENTAGE);
Component message;
if (this.sleepStatus.areEnoughSleeping(percentage)) {
+ // 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));
+ message = 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");
message = 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,
+ message = 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(i)))));
+ } else
+ // Purpur end - Customizable sleeping actionbar messages
component = Component.translatable("sleep.players_sleeping", this.sleepStatus.amountSleeping(), this.sleepStatus.sleepersNeeded(i));
message = Component.translatable("sleep.players_sleeping", this.sleepStatus.amountSleeping(), this.sleepStatus.sleepersNeeded(percentage));
}
@@ -1275,6 +1368,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
@VisibleForTesting
@@ -1000,6 +_,7 @@
public void resetWeatherCycle() {
WeatherData weatherData = this.getWeatherData();
// 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
weatherData.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....
@@ -1282,6 +1376,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
this.serverLevelData.setRainTime(0);
@@ -1007,6 +_,7 @@
weatherData.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
weatherData.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.
@@ -1954,7 +2049,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
Explosion.BlockInteraction blockInteraction = switch (explosionInteraction) {
@@ -1640,7 +_,7 @@
Explosion.BlockInteraction blockInteraction = switch (interactionType) {
case NONE -> Explosion.BlockInteraction.KEEP;
case BLOCK -> this.getDestroyType(GameRules.BLOCK_EXPLOSION_DROP_DECAY);
- case MOB -> this.getGameRules().get(GameRules.MOB_GRIEFING)
@@ -213,7 +170,7 @@ index dc65503a2d785d64d37b76b0303f51cf66d9769a..5130c0067f01eec31c69b9e71d904f93
? this.getDestroyType(GameRules.MOB_EXPLOSION_DROP_DECAY)
: Explosion.BlockInteraction.KEEP;
case TNT -> this.getDestroyType(GameRules.TNT_EXPLOSION_DROP_DECAY);
@@ -2846,7 +2941,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
@@ -2539,7 +_,7 @@
// Spigot start
if (entity.getBukkitEntity() instanceof org.bukkit.inventory.InventoryHolder && (!(entity instanceof ServerPlayer) || entity.getRemovalReason() != Entity.RemovalReason.KILLED)) { // SPIGOT-6876: closeInventory clears death message
// Paper start - Fix merchant inventory not closing on entity removal

View File

@@ -0,0 +1,20 @@
--- a/net/minecraft/world/clock/ServerClockManager.java
+++ b/net/minecraft/world/clock/ServerClockManager.java
@@ -112,7 +_,7 @@
ServerClockManager.ClockInstance instance = this.getInstance(clock);
action.accept(instance);
Map<Holder<WorldClock>, ClockState> updates = Map.of(clock, instance.packNetworkState(this.server));
- this.server.getPlayerList().broadcastAll(new ClientboundSetTimePacket(this.getGameTime(), updates)); // TODO 26.1 per-player time
+ this.server.getPlayerList().broadcastAll(new ClientboundSetTimePacket(this.getGameTime(), updates)); // TODO 26.1 per-player time // Purpur - TODO: Configurable daylight cycle
this.setDirty();
}
@@ -128,7 +_,7 @@
// Paper end
public ClientboundSetTimePacket createFullSyncPacket() {
- // TODO 26.1 per-player time
+ // TODO 26.1 per-player time // Purpur - TODO: Configurable daylight cycle
return new ClientboundSetTimePacket(this.getGameTime(), Util.mapValues(this.clocks, clock -> clock.packNetworkState(this.server)));
}

View File

@@ -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(final 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);
}
}

View File

@@ -0,0 +1,11 @@
--- a/net/minecraft/world/entity/ai/behavior/AcquirePoi.java
+++ b/net/minecraft/world/entity/ai/behavior/AcquirePoi.java
@@ -89,7 +_,7 @@
}
};
Set<Pair<Holder<PoiType>, BlockPos>> poiPositions = poiManager.findAllClosestFirstWithType(
- poiType, cacheTest, body.blockPosition(), 48, PoiManager.Occupancy.HAS_SPACE
+ poiType, cacheTest, body.blockPosition(), level.purpurConfig.villagerAcquirePoiSearchRadius, PoiManager.Occupancy.HAS_SPACE // Purpur - Configurable villager search radius
)
.limit(5L)
.filter(px -> validPoi.test(level, (BlockPos)px.getSecond()))

View File

@@ -0,0 +1,29 @@
--- a/net/minecraft/world/entity/ai/behavior/InteractWithDoor.java
+++ b/net/minecraft/world/entity/ai/behavior/InteractWithDoor.java
@@ -53,7 +_,7 @@
Node toNode = path.getNextNode();
BlockPos fromPos = fromNode.asBlockPos();
BlockState fromState = level.getBlockState(fromPos);
- if (fromState.is(BlockTags.MOB_INTERACTABLE_DOORS, s -> s.getBlock() instanceof DoorBlock)) {
+ if (fromState.is(BlockTags.MOB_INTERACTABLE_DOORS, s -> s.getBlock() instanceof DoorBlock)&& !DoorBlock.requiresRedstone(entity.level(), blockState, blockPos)) { // Purpur - Option to make doors require redstone
DoorBlock fromBlock = (DoorBlock)fromState.getBlock();
if (!fromBlock.isOpen(fromState)) {
// CraftBukkit start - entities opening doors
@@ -70,7 +_,7 @@
BlockPos toPos = toNode.asBlockPos();
BlockState toState = level.getBlockState(toPos);
- if (toState.is(BlockTags.MOB_INTERACTABLE_DOORS, s -> s.getBlock() instanceof DoorBlock)) {
+ if (toState.is(BlockTags.MOB_INTERACTABLE_DOORS, s -> s.getBlock() instanceof DoorBlock) && !DoorBlock.requiresRedstone(entity.level(), blockState1, blockPos1)) { // Purpur - Option to make doors require redstone
DoorBlock door = (DoorBlock)toState.getBlock();
if (!door.isOpen(toState)) {
// CraftBukkit start - entities opening doors
@@ -117,7 +_,7 @@
iterator.remove();
} else {
BlockState state = level.getBlockState(doorPos);
- if (!state.is(BlockTags.MOB_INTERACTABLE_DOORS, s -> s.getBlock() instanceof DoorBlock)) {
+ if (!state.is(BlockTags.MOB_INTERACTABLE_DOORS, s -> s.getBlock() instanceof DoorBlock) || DoorBlock.requiresRedstone(entity.level(), blockState, blockPos)) { // Purpur - Option to make doors require redstone
iterator.remove();
} else {
DoorBlock block = (DoorBlock)state.getBlock();

View File

@@ -0,0 +1,10 @@
--- a/net/minecraft/world/entity/ai/behavior/ShowTradesToPlayer.java
+++ b/net/minecraft/world/entity/ai/behavior/ShowTradesToPlayer.java
@@ -41,6 +_,7 @@
@Override
public boolean canStillUse(final ServerLevel level, final Villager body, final long timestamp) {
+ if (!body.level().purpurConfig.villagerDisplayTradeItem) return false; // Purpur - Option for villager display trade item
return this.checkExtraStartConditions(level, body) && this.lookTime > 0 && body.getBrain().getMemory(MemoryModuleType.INTERACTION_TARGET).isPresent();
}

View File

@@ -0,0 +1,18 @@
--- a/net/minecraft/world/entity/ai/behavior/SleepInBed.java
+++ b/net/minecraft/world/entity/ai/behavior/SleepInBed.java
@@ -89,7 +_,14 @@
InteractWithDoor.closeDoorsThatIHaveOpenedOrPassedThrough(level, body, null, null, doors, nearestEntities);
}
- body.startSleeping(body.getBrain().getMemory(MemoryModuleType.HOME).get().pos());
+ // Purpur start - Option for beds to explode on villager sleep
+ net.minecraft.core.BlockPos bedPosition = body.getBrain().getMemory(net.minecraft.world.entity.ai.memory.MemoryModuleType.HOME).get().pos();
+ if (level.purpurConfig.bedExplodeOnVillagerSleep && body.is(net.minecraft.world.entity.EntityType.VILLAGER) && level.getBlockState(bedPosition).getBlock() instanceof net.minecraft.world.level.block.BedBlock) {
+ level.explode(null, (double) bedPosition.getX() + 0.5D, (double) bedPosition.getY() + 0.5D, (double) bedPosition.getZ() + 0.5D, (float) level.purpurConfig.bedExplosionPower, level.purpurConfig.bedExplosionFire, level.purpurConfig.bedExplosionEffect);
+ return;
+ }
+ body.startSleeping(bedPosition);
+ // Purpur end - Option for beds to explode on villager sleep
brain.setMemory(MemoryModuleType.LAST_SLEPT, timestamp);
brain.eraseMemory(MemoryModuleType.WALK_TARGET);
brain.eraseMemory(MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE);

View File

@@ -0,0 +1,54 @@
--- a/net/minecraft/world/entity/ai/behavior/TransportItemsBetweenContainers.java
+++ b/net/minecraft/world/entity/ai/behavior/TransportItemsBetweenContainers.java
@@ -286,7 +_,7 @@
LevelChunk levelChunk = level.getChunkSource().getChunkNow(chunkPos.x(), chunkPos.z());
if (levelChunk != null) {
for (BlockEntity potentialTarget : levelChunk.getBlockEntities().values()) {
- if (potentialTarget instanceof ChestBlockEntity chestBlockEntity) {
+ if (potentialTarget instanceof net.minecraft.world.level.block.entity.BaseContainerBlockEntity chestBlockEntity) { // Purpur - copper golem can place items in barrels or shulkers option
double distance = chestBlockEntity.getBlockPos().distToCenterSqr(body.position());
if (distance < closestDistance) {
TransportItemsBetweenContainers.TransportItemTarget targetValidToPick = this.isTargetValidToPick(
@@ -375,7 +_,11 @@
}
private boolean isTargetBlocked(final Level level, final TransportItemsBetweenContainers.TransportItemTarget target) {
- return ChestBlock.isChestBlockedAt(level, target.pos);
+ // Purpur start - copper golem can place items in barrels or shulkers option
+ boolean isBarrelBlocked = !level.purpurConfig.copperGolemCanOpenBarrel && target.state.is(net.minecraft.world.level.block.Blocks.BARREL);
+ boolean isShulkerBlocked = !level.purpurConfig.copperGolemCanOpenShulker && target.blockEntity instanceof net.minecraft.world.level.block.entity.ShulkerBoxBlockEntity shulkerBoxBlockEntity && !net.minecraft.world.level.block.ShulkerBoxBlock.canOpen(target.state, level, target.pos, shulkerBoxBlockEntity);
+ return target.state.is(net.minecraft.world.level.block.Blocks.BARREL) ? isBarrelBlocked : isShulkerBlocked || net.minecraft.world.level.block.ChestBlock.isChestBlockedAt(level, target.pos);
+ // Purpur end - copper golem can place items in barrels or shulkers option
}
private boolean targetHasNotChanged(final Level level, final TransportItemsBetweenContainers.TransportItemTarget target) {
@@ -455,7 +_,7 @@
}
private boolean isWantedBlock(final PathfinderMob mob, final BlockState block) {
- return isPickingUpItems(mob) ? this.sourceBlockType.test(block) : this.destinationBlockType.test(block);
+ return isPickingUpItems(mob) ? this.sourceBlockType.test(block) : (mob.level().purpurConfig.copperGolemCanOpenBarrel && state.is(net.minecraft.world.level.block.Blocks.BARREL)) || (mob.level().purpurConfig.copperGolemCanOpenShulker && state.is(net.minecraft.tags.BlockTags.SHULKER_BOXES)) || this.destinationBlockType.test(block); // Purpur - copper golem can place items in barrels or shulkers option
}
private static double getInteractionRange(final PathfinderMob body) {
@@ -507,6 +_,11 @@
}
private static boolean matchesLeavingItemsRequirement(final PathfinderMob body, final Container container) {
+ // Purpur start - copper golem can place items in barrels or shulkers option
+ if (body.level().purpurConfig.copperGolemCanOpenShulker && container instanceof net.minecraft.world.level.block.entity.ShulkerBoxBlockEntity && body.getMainHandItem().is(net.minecraft.tags.ItemTags.SHULKER_BOXES)) {
+ return false;
+ }
+ // Purpur end - copper golem can place items in barrels or shulkers option
return container.isEmpty() || hasItemMatchingHandItem(body, container);
}
@@ -544,7 +_,7 @@
int slot = 0;
for (ItemStack itemStack : container) {
- if (!itemStack.isEmpty()) {
+ if (!itemStack.isEmpty() && (!(container instanceof net.minecraft.world.level.block.entity.ShulkerBoxBlockEntity) || !itemStack.is(net.minecraft.tags.ItemTags.SHULKER_BOXES))) { // Purpur - copper golem can place items in barrels or shulkers option
int itemCount = Math.min(itemStack.getCount(), 16);
return container.removeItem(slot, itemCount);
}

View File

@@ -0,0 +1,17 @@
--- a/net/minecraft/world/entity/ai/goal/SwellGoal.java
+++ b/net/minecraft/world/entity/ai/goal/SwellGoal.java
@@ -46,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
}
} else {
this.creeper.setSwellDir(-1);

View File

@@ -0,0 +1,14 @@
--- a/net/minecraft/world/entity/ai/sensing/NearestBedSensor.java
+++ b/net/minecraft/world/entity/ai/sensing/NearestBedSensor.java
@@ -54,9 +_,9 @@
}
};
Set<Pair<Holder<PoiType>, BlockPos>> pois = poiManager.findAllWithType(
- e -> e.is(PoiTypes.HOME), cacheTest, body.blockPosition(), 48, PoiManager.Occupancy.ANY
+ e -> e.is(PoiTypes.HOME), cacheTest, body.blockPosition(), level.purpurConfig.villagerNearestBedSensorSearchRadius, PoiManager.Occupancy.ANY
)
- .collect(Collectors.toSet());
+ .collect(Collectors.toSet()); // Purpur - Configurable villager search radius
Path path = AcquirePoi.findPathToPois(body, pois);
if (path != null && path.canReach()) {
BlockPos targetPos = path.getTarget();

View File

@@ -0,0 +1,34 @@
--- a/net/minecraft/world/entity/animal/Animal.java
+++ b/net/minecraft/world/entity/animal/Animal.java
@@ -146,7 +_,7 @@
ItemStack itemStack = player.getItemInHand(hand);
if (this.isFood(itemStack)) {
int age = this.getAge();
- if (player instanceof ServerPlayer serverPlayer && age == 0 && this.canFallInLove()) {
+ if (player instanceof ServerPlayer serverPlayer && 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 = itemStack.copy(); // Paper - Fix EntityBreedEvent copying
this.usePlayerItem(player, hand, itemStack);
this.setInLove(serverPlayer, breedCopy); // Paper - Fix EntityBreedEvent copying
@@ -227,10 +_,20 @@
public void spawnChildFromBreeding(final ServerLevel level, final Animal partner) {
AgeableMob offspring = this.getBreedOffspring(level, partner);
if (offspring != null) {
- offspring.setBaby(true);
- offspring.snapTo(this.getX(), this.getY(), this.getZ(), 0.0F, 0.0F);
+ //offspring.setBaby(true); // Purpur - Add adjustable breeding cooldown to config - moved down
+ //offspring.snapTo(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(partner.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());
+ }
+ offspring.setBaby(true);
+ offspring.snapTo(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(offspring, this, partner, breeder, this.breedItem, experience);
if (entityBreedEvent.isCancelled()) {

View File

@@ -1,29 +1,21 @@
From 56a0a83ddb1b7472dbc9762e2aca396605c62085 Mon Sep 17 00:00:00 2001
From: File <noreply+automated@papermc.io>
Date: Sun, 20 Apr 1997 05:37:42 -0800
Subject: [PATCH] purpur File Patches
diff --git a/net/minecraft/world/entity/animal/bee/Bee.java b/net/minecraft/world/entity/animal/bee/Bee.java
index 0cbcf23b6edba2305dfbbc95abb06a90a6edd42b..7b9280526af353c3ab1f32e5195499e773731352 100644
--- a/net/minecraft/world/entity/animal/bee/Bee.java
+++ b/net/minecraft/world/entity/animal/bee/Bee.java
@@ -171,7 +171,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal {
@@ -172,7 +_,7 @@
// Paper end - Fix MC-167279
this.lookControl = new Bee.BeeLookControl(this);
this.setPathfindingMalus(PathType.DANGER_FIRE, -1.0F);
this.setPathfindingMalus(PathType.FIRE_IN_NEIGHBOR, -1.0F);
- this.setPathfindingMalus(PathType.WATER, -1.0F);
+ if (this.level().purpurConfig.beeCanInstantlyStartDrowning) this.setPathfindingMalus(PathType.WATER, -1.0F); // Purpur - bee can instantly start drowning in water option
this.setPathfindingMalus(PathType.WATER_BORDER, 16.0F);
this.setPathfindingMalus(PathType.COCOA, -1.0F);
this.setPathfindingMalus(PathType.FENCE, -1.0F);
@@ -360,13 +360,19 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal {
@@ -363,13 +_,19 @@
if (this.stayOutOfHiveCountdown <= 0 && !this.beePollinateGoal.isPollinating() && !this.hasStung() && this.getTarget() == null) {
boolean flag = this.hasNectar()
boolean wantsToEnterHive = this.hasNectar()
|| this.isTiredOfLookingForNectar()
- || this.level().environmentAttributes().getValue(EnvironmentAttributes.BEES_STAY_IN_HIVE, this.position());
+ || this.level().environmentAttributes().getValue(EnvironmentAttributes.BEES_STAY_IN_HIVE, this.position()) || isNightOrRaining(this.level()); // Purpur - Bee can work when raining or at night
return flag && !this.isHiveNearFire();
return wantsToEnterHive && !this.isHiveNearFire();
} else {
return false;
}
@@ -35,19 +27,19 @@ index 0cbcf23b6edba2305dfbbc95abb06a90a6edd42b..7b9280526af353c3ab1f32e5195499e7
+ }
+ // Purpur end - Bee can work when raining or at night
+
public void setStayOutOfHiveCountdown(int stayOutOfHiveCountdown) {
this.stayOutOfHiveCountdown = stayOutOfHiveCountdown;
public void setStayOutOfHiveCountdown(final int ticks) {
this.stayOutOfHiveCountdown = ticks;
}
@@ -387,7 +393,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal {
@@ -390,7 +_,7 @@
@Override
protected void customServerAiStep(ServerLevel level) {
protected void customServerAiStep(final ServerLevel level) {
boolean hasStung = this.hasStung();
- if (this.isInWater()) {
+ if (this.level().purpurConfig.beeCanInstantlyStartDrowning && this.isInWater()) { // Purpur - bee can instantly start drowning in water option
this.underWaterTicks++;
} else {
this.underWaterTicks = 0;
@@ -397,6 +403,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal {
@@ -400,6 +_,7 @@
this.hurtServer(level, this.damageSources().drown(), 1.0F);
}
@@ -55,15 +47,15 @@ index 0cbcf23b6edba2305dfbbc95abb06a90a6edd42b..7b9280526af353c3ab1f32e5195499e7
if (hasStung) {
this.timeSinceSting++;
if (this.timeSinceSting % 5 == 0 && this.random.nextInt(Mth.clamp(1200 - this.timeSinceSting, 1, 1200)) == 0) {
@@ -1130,6 +1137,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal {
Bee.this.savedFlowerPos = optional.get();
@@ -1168,6 +_,7 @@
Bee.this.savedFlowerPos = nearbyPos.get();
Bee.this.navigation
.moveTo(Bee.this.savedFlowerPos.getX() + 0.5, Bee.this.savedFlowerPos.getY() + 0.5, Bee.this.savedFlowerPos.getZ() + 0.5, 1.2F);
+ new org.purpurmc.purpur.event.entity.BeeFoundFlowerEvent((org.bukkit.entity.Bee) Bee.this.getBukkitEntity(), org.bukkit.craftbukkit.util.CraftLocation.toBukkit(Bee.this.savedFlowerPos, Bee.this.level())).callEvent(); // Purpur - Bee API
return true;
} else {
Bee.this.remainingCooldownBeforeLocatingNewFlower = Mth.nextInt(Bee.this.random, 20, 60);
@@ -1176,6 +1184,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal {
@@ -1214,6 +_,7 @@
this.pollinating = false;
Bee.this.navigation.stop();
Bee.this.remainingCooldownBeforeLocatingNewFlower = 200;
@@ -71,7 +63,7 @@ index 0cbcf23b6edba2305dfbbc95abb06a90a6edd42b..7b9280526af353c3ab1f32e5195499e7
}
@Override
@@ -1222,6 +1231,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal {
@@ -1260,6 +_,7 @@
this.setWantedPos();
}

View File

@@ -1,25 +1,17 @@
From 56a0a83ddb1b7472dbc9762e2aca396605c62085 Mon Sep 17 00:00:00 2001
From: File <noreply+automated@papermc.io>
Date: Sun, 20 Apr 1997 05:37:42 -0800
Subject: [PATCH] purpur File Patches
diff --git a/net/minecraft/world/entity/animal/cow/AbstractCow.java b/net/minecraft/world/entity/animal/cow/AbstractCow.java
index e10f7d1b264a85798de063b4387bab62621bf54b..f6f251227db315b58bee45f8011624a347eb8fea 100644
--- a/net/minecraft/world/entity/animal/cow/AbstractCow.java
+++ b/net/minecraft/world/entity/animal/cow/AbstractCow.java
@@ -40,7 +40,7 @@ public abstract class AbstractCow extends Animal {
@@ -40,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(3, new TemptGoal(this, 1.25, i -> i.is(ItemTags.COW_FOOD), false));
+ this.goalSelector.addGoal(3, new TemptGoal(this, 1.25, i -> level().purpurConfig.cowFeedMushrooms > 0 && (i.is(net.minecraft.world.level.block.Blocks.RED_MUSHROOM.asItem()) || i.is(net.minecraft.world.level.block.Blocks.BROWN_MUSHROOM.asItem())) || i.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));
@@ -96,6 +96,10 @@ public abstract class AbstractCow extends Animal {
ItemStack itemStack = ItemUtils.createFilledResult(itemInHand, player, org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getItemStack())); // CraftBukkit
player.setItemInHand(hand, itemStack);
@@ -100,6 +_,10 @@
ItemStack bucketOrMilkBucket = ItemUtils.createFilledResult(itemStack, player, org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getItemStack())); // CraftBukkit
player.setItemInHand(hand, bucketOrMilkBucket);
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)) {
@@ -28,8 +20,8 @@ index e10f7d1b264a85798de063b4387bab62621bf54b..f6f251227db315b58bee45f8011624a3
} else {
return super.mobInteract(player, hand);
}
@@ -105,4 +109,67 @@ public abstract class AbstractCow extends Animal {
public EntityDimensions getDefaultDimensions(Pose pose) {
@@ -109,4 +_,67 @@
public EntityDimensions getDefaultDimensions(final Pose pose) {
return this.isBaby() ? BABY_DIMENSIONS : super.getDefaultDimensions(pose);
}
+

View File

@@ -1,30 +1,22 @@
From 56a0a83ddb1b7472dbc9762e2aca396605c62085 Mon Sep 17 00:00:00 2001
From: File <noreply+automated@papermc.io>
Date: Sun, 20 Apr 1997 05:37:42 -0800
Subject: [PATCH] purpur File Patches
diff --git a/net/minecraft/world/entity/animal/dolphin/Dolphin.java b/net/minecraft/world/entity/animal/dolphin/Dolphin.java
index 3a3c9694d3a704aaaa241bd8601c7fd2439436cc..50b8abff1e20855ba8c8acb225c251a1223b8b58 100644
--- a/net/minecraft/world/entity/animal/dolphin/Dolphin.java
+++ b/net/minecraft/world/entity/animal/dolphin/Dolphin.java
@@ -75,6 +75,7 @@ public class Dolphin extends AgeableWaterCreature {
@@ -77,6 +_,7 @@
public static final float BABY_SCALE = 0.65F;
private static final boolean DEFAULT_GOT_FISH = false;
@Nullable public BlockPos treasurePos;
public @Nullable BlockPos treasurePos;
+ private boolean isNaturallyAggressiveToPlayers; // Purpur - Dolphins naturally aggressive to players chance
public Dolphin(EntityType<? extends Dolphin> type, Level level) {
public Dolphin(final EntityType<? extends Dolphin> type, final Level level) {
super(type, level);
@@ -90,6 +91,7 @@ public class Dolphin extends AgeableWaterCreature {
@@ -92,6 +_,7 @@
this.setAirSupply(this.getMaxAirSupply());
this.setXRot(0.0F);
SpawnGroupData spawnGroupData1 = Objects.requireNonNullElseGet(spawnGroupData, () -> new AgeableMob.AgeableMobGroupData(0.1F));
SpawnGroupData spawnGroupData = Objects.requireNonNullElseGet(groupData, () -> 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);
return super.finalizeSpawn(level, difficulty, spawnReason, spawnGroupData);
}
@@ -155,17 +157,19 @@ public class Dolphin extends AgeableWaterCreature {
@@ -157,18 +_,20 @@
protected void registerGoals() {
this.goalSelector.addGoal(0, new BreathAirGoal(this));
this.goalSelector.addGoal(0, new TryFindWaterGoal(this));
@@ -38,14 +30,15 @@ index 3a3c9694d3a704aaaa241bd8601c7fd2439436cc..50b8abff1e20855ba8c8acb225c251a1
- 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(8, new FollowPlayerRiddenEntityGoal(this, AbstractBoat.class));
this.goalSelector.addGoal(8, new FollowPlayerRiddenEntityGoal(this, AbstractNautilus.class));
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() {
@@ -392,6 +396,7 @@ public class Dolphin extends AgeableWaterCreature {
@@ -395,6 +_,7 @@
@Override
public boolean canUse() {

View File

@@ -1,22 +1,14 @@
From 56a0a83ddb1b7472dbc9762e2aca396605c62085 Mon Sep 17 00:00:00 2001
From: File <noreply+automated@papermc.io>
Date: Sun, 20 Apr 1997 05:37:42 -0800
Subject: [PATCH] purpur File Patches
diff --git a/net/minecraft/world/entity/animal/equine/Llama.java b/net/minecraft/world/entity/animal/equine/Llama.java
index 1522efc1e6937bc8a24a2df77d5421ae04a6642b..cceb66525a4d017b2db21bd301e63670c639223f 100644
--- a/net/minecraft/world/entity/animal/equine/Llama.java
+++ b/net/minecraft/world/entity/animal/equine/Llama.java
@@ -76,6 +76,7 @@ public class Llama extends AbstractChestedHorse implements RangedAttackMob {
boolean didSpit;
@@ -75,6 +_,7 @@
private boolean didSpit;
private @Nullable Llama caravanHead;
public @Nullable Llama caravanTail; // Paper - public
+ public boolean shouldJoinCaravan = true; // Purpur - Llama API
public Llama(EntityType<? extends Llama> type, Level level) {
public Llama(final EntityType<? extends Llama> type, final Level level) {
super(type, level);
@@ -105,6 +106,7 @@ public class Llama extends AbstractChestedHorse implements RangedAttackMob {
@@ -104,6 +_,7 @@
super.addAdditionalSaveData(output);
output.store("Variant", Llama.Variant.LEGACY_CODEC, this.getVariant());
output.putInt("Strength", this.getStrength());
@@ -24,7 +16,7 @@ index 1522efc1e6937bc8a24a2df77d5421ae04a6642b..cceb66525a4d017b2db21bd301e63670
}
@Override
@@ -112,6 +114,7 @@ public class Llama extends AbstractChestedHorse implements RangedAttackMob {
@@ -111,6 +_,7 @@
this.setStrength(input.getIntOr("Strength", 0));
super.readAdditionalSaveData(input);
this.setVariant(input.read("Variant", Llama.Variant.LEGACY_CODEC).orElse(Llama.Variant.DEFAULT));
@@ -32,7 +24,7 @@ index 1522efc1e6937bc8a24a2df77d5421ae04a6642b..cceb66525a4d017b2db21bd301e63670
}
@Override
@@ -388,6 +391,7 @@ public class Llama extends AbstractChestedHorse implements RangedAttackMob {
@@ -387,6 +_,7 @@
public void leaveCaravan() {
if (this.caravanHead != null) {
@@ -40,11 +32,11 @@ index 1522efc1e6937bc8a24a2df77d5421ae04a6642b..cceb66525a4d017b2db21bd301e63670
this.caravanHead.caravanTail = null;
}
@@ -395,6 +399,7 @@ public class Llama extends AbstractChestedHorse implements RangedAttackMob {
@@ -394,6 +_,7 @@
}
public void joinCaravan(Llama caravanHead) {
public void joinCaravan(final Llama tail) {
+ if (!this.level().purpurConfig.llamaJoinCaravans || !shouldJoinCaravan || !new org.purpurmc.purpur.event.entity.LlamaJoinCaravanEvent((org.bukkit.entity.Llama) getBukkitEntity(), (org.bukkit.entity.Llama) caravanHead.getBukkitEntity()).callEvent()) return; // Purpur - Llama API // Purpur - Config to disable Llama caravans
this.caravanHead = caravanHead;
this.caravanHead = tail;
this.caravanHead.caravanTail = this;
}

View File

@@ -1,15 +1,7 @@
From 56a0a83ddb1b7472dbc9762e2aca396605c62085 Mon Sep 17 00:00:00 2001
From: File <noreply+automated@papermc.io>
Date: Sun, 20 Apr 1997 05:37:42 -0800
Subject: [PATCH] purpur File Patches
diff --git a/net/minecraft/world/entity/animal/feline/Cat.java b/net/minecraft/world/entity/animal/feline/Cat.java
index f17d7a4ef7061d6ede9a755b5a77324a28c3eeaa..6acd39413ab4fed1eaf251d3b6d9b9e184060e5c 100644
--- a/net/minecraft/world/entity/animal/feline/Cat.java
+++ b/net/minecraft/world/entity/animal/feline/Cat.java
@@ -354,6 +354,14 @@ public class Cat extends TamableAnimal {
return this.isTame() && otherAnimal instanceof Cat cat && cat.isTame() && super.canMate(otherAnimal);
@@ -382,6 +_,14 @@
return this.isTame() && partner instanceof Cat cat && cat.isTame() && super.canMate(partner);
}
+ // Purpur start - Configurable default collar color
@@ -22,11 +14,11 @@ index f17d7a4ef7061d6ede9a755b5a77324a28c3eeaa..6acd39413ab4fed1eaf251d3b6d9b9e1
+
@Override
public @Nullable SpawnGroupData finalizeSpawn(
ServerLevelAccessor level, DifficultyInstance difficulty, EntitySpawnReason spawnReason, @Nullable SpawnGroupData spawnGroupData
@@ -451,7 +459,7 @@ public class Cat extends TamableAnimal {
final ServerLevelAccessor level, final DifficultyInstance difficulty, final EntitySpawnReason spawnReason, @Nullable SpawnGroupData groupData
@@ -476,7 +_,7 @@
}
private void tryToTame(Player player) {
private void tryToTame(final 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);

View File

@@ -0,0 +1,11 @@
--- a/net/minecraft/world/entity/animal/feline/Ocelot.java
+++ b/net/minecraft/world/entity/animal/feline/Ocelot.java
@@ -234,7 +_,7 @@
public boolean checkSpawnObstruction(final LevelReader level) {
if (level.isUnobstructed(this) && !level.containsAnyLiquid(this.getBoundingBox())) {
BlockPos pos = this.blockPosition();
- if (pos.getY() < level.getSeaLevel()) {
+ if (!level().purpurConfig.ocelotSpawnUnderSeaLevel && pos.getY() < level.getSeaLevel()) { // Purpur - Option Ocelot Spawn Under Sea Level
return false;
}

View File

@@ -0,0 +1,12 @@
--- a/net/minecraft/world/entity/animal/fish/WaterAnimal.java
+++ b/net/minecraft/world/entity/animal/fish/WaterAnimal.java
@@ -80,8 +_,7 @@
seaLevel = level.getMinecraftWorld().paperConfig().entities.spawning.wateranimalSpawnHeight.maximum.or(seaLevel);
minSpawnLevel = level.getMinecraftWorld().paperConfig().entities.spawning.wateranimalSpawnHeight.minimum.or(minSpawnLevel);
// Paper end - Make water animal spawn height configurable
- return pos.getY() >= minSpawnLevel
- && pos.getY() <= seaLevel
+ return ((spawnReason == EntitySpawnReason.SPAWNER && level.getMinecraftWorld().purpurConfig.spawnerFixMC238526) || (pos.getY() >= minSpawnLevel && 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);
}

View File

@@ -1,31 +1,23 @@
From 56a0a83ddb1b7472dbc9762e2aca396605c62085 Mon Sep 17 00:00:00 2001
From: File <noreply+automated@papermc.io>
Date: Sun, 20 Apr 1997 05:37:42 -0800
Subject: [PATCH] purpur File Patches
diff --git a/net/minecraft/world/entity/animal/golem/CopperGolemAi.java b/net/minecraft/world/entity/animal/golem/CopperGolemAi.java
index 56872b4674ae4ce0ebcb6c28ae606265384777cd..fd556e10ff87eac5e965a5eef31cfe0c0f8fbd66 100644
--- a/net/minecraft/world/entity/animal/golem/CopperGolemAi.java
+++ b/net/minecraft/world/entity/animal/golem/CopperGolemAi.java
@@ -43,7 +43,7 @@ public class CopperGolemAi {
@@ -41,7 +_,7 @@
private static final int TICK_TO_START_ON_REACHED_INTERACTION = 1;
private static final int TICK_TO_PLAY_ON_REACHED_SOUND = 9;
private static final Predicate<BlockState> TRANSPORT_ITEM_SOURCE_BLOCK = state -> state.is(BlockTags.COPPER_CHESTS);
- private static final Predicate<BlockState> TRANSPORT_ITEM_DESTINATION_BLOCK = state -> state.is(Blocks.CHEST) || state.is(Blocks.TRAPPED_CHEST);
+ private static final Predicate<BlockState> TRANSPORT_ITEM_DESTINATION_BLOCK = state -> state.is(Blocks.CHEST) || state.is(Blocks.TRAPPED_CHEST); // Purpur - copper golem can place items in barrels or shulkers option - diff on change
private static final ImmutableList<SensorType<? extends Sensor<? super CopperGolem>>> SENSOR_TYPES = ImmutableList.of(
SensorType.NEAREST_LIVING_ENTITIES, SensorType.HURT_BY
);
@@ -158,6 +158,11 @@ public class CopperGolemAi {
private static final Predicate<BlockState> TRANSPORT_ITEM_SOURCE_BLOCK = block -> block.is(BlockTags.COPPER_CHESTS);
- private static final Predicate<BlockState> TRANSPORT_ITEM_DESTINATION_BLOCK = block -> block.is(Blocks.CHEST) || block.is(Blocks.TRAPPED_CHEST);
+ private static final Predicate<BlockState> TRANSPORT_ITEM_DESTINATION_BLOCK = block -> block.is(Blocks.CHEST) || block.is(Blocks.TRAPPED_CHEST); // Purpur - copper golem can place items in barrels or shulkers option - diff on change
protected static List<ActivityData<CopperGolem>> getActivities() {
return List.of(initCoreActivity(), initIdleActivity());
@@ -130,6 +_,11 @@
}
if (integer == 60) {
if (ticksSinceReachingTarget == 60) {
+ // Purpur start - copper golem can place items in barrels or shulkers option
+ if (container instanceof net.minecraft.world.level.block.entity.ShulkerBoxBlockEntity shulkerBoxBlockEntity && shulkerBoxBlockEntity.openCount > 0) {
+ container.stopOpen(copperGolem);
+ }
+ // Purpur end - copper golem can place items in barrels or shulkers option
if (container.getEntitiesWithContainerOpen().contains(pathfinderMob)) {
if (container.getEntitiesWithContainerOpen().contains(body)) {
container.stopOpen(copperGolem);
}

View File

@@ -1,20 +1,12 @@
From 56a0a83ddb1b7472dbc9762e2aca396605c62085 Mon Sep 17 00:00:00 2001
From: File <noreply+automated@papermc.io>
Date: Sun, 20 Apr 1997 05:37:42 -0800
Subject: [PATCH] purpur File Patches
diff --git a/net/minecraft/world/entity/animal/golem/IronGolem.java b/net/minecraft/world/entity/animal/golem/IronGolem.java
index b2c4e93f6063ded665b18ba3b4eaa0eb4cd98732..32425f0aaa748c7f80f2e5cf95ef27238fe50489 100644
--- a/net/minecraft/world/entity/animal/golem/IronGolem.java
+++ b/net/minecraft/world/entity/animal/golem/IronGolem.java
@@ -58,13 +58,25 @@ public class IronGolem extends AbstractGolem implements NeutralMob {
@@ -58,13 +_,25 @@
private static final UniformInt PERSISTENT_ANGER_TIME = TimeUtil.rangeOfSeconds(20, 39);
private long persistentAngerEndTime;
private @Nullable EntityReference<LivingEntity> persistentAngerTarget;
+ private java.util.@Nullable UUID summoner; // Purpur - Summoner API
public IronGolem(EntityType<? extends IronGolem> type, Level level) {
public IronGolem(final EntityType<? extends IronGolem> type, final Level level) {
super(type, level);
}
@@ -34,26 +26,26 @@ index b2c4e93f6063ded665b18ba3b4eaa0eb4cd98732..32425f0aaa748c7f80f2e5cf95ef2723
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));
@@ -142,6 +154,7 @@ public class IronGolem extends AbstractGolem implements NeutralMob {
protected void addAdditionalSaveData(ValueOutput output) {
@@ -142,6 +_,7 @@
protected void addAdditionalSaveData(final ValueOutput output) {
super.addAdditionalSaveData(output);
output.putBoolean("PlayerCreated", this.isPlayerCreated());
+ output.storeNullable("Purpur.Summoner", net.minecraft.core.UUIDUtil.CODEC, getSummoner()); // Purpur - Summoner API
this.addPersistentAngerSaveData(output);
}
@@ -149,6 +162,7 @@ public class IronGolem extends AbstractGolem implements NeutralMob {
protected void readAdditionalSaveData(ValueInput input) {
@@ -149,6 +_,7 @@
protected void readAdditionalSaveData(final ValueInput input) {
super.readAdditionalSaveData(input);
this.setPlayerCreated(input.getBooleanOr("PlayerCreated", false));
+ this.setSummoner(input.read("Purpur.Summoner", net.minecraft.core.UUIDUtil.CODEC).orElse(null)); // Purpur - Summoner API
this.readPersistentAngerSaveData(this.level(), input);
}
@@ -267,6 +281,7 @@ public class IronGolem extends AbstractGolem implements NeutralMob {
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);
@@ -267,6 +_,7 @@
float pitch = 1.0F + (this.random.nextFloat() - this.random.nextFloat()) * 0.2F;
this.playSound(SoundEvents.IRON_GOLEM_REPAIR, 1.0F, pitch);
itemStack.consume(1, player);
+ if (this.level().purpurConfig.ironGolemHealCalm && isAngry() && getHealth() == getMaxHealth()) stopBeingAngry(); // Purpur - Iron golem calm anger options
return InteractionResult.SUCCESS;
}

View File

@@ -1,14 +1,6 @@
From 56a0a83ddb1b7472dbc9762e2aca396605c62085 Mon Sep 17 00:00:00 2001
From: File <noreply+automated@papermc.io>
Date: Sun, 20 Apr 1997 05:37:42 -0800
Subject: [PATCH] purpur File Patches
diff --git a/net/minecraft/world/entity/animal/parrot/Parrot.java b/net/minecraft/world/entity/animal/parrot/Parrot.java
index 62a26395ee0c3ee450ad3b1ac88bc85523dd27b4..0337ddcd664cd0329d98286214d1aa4daf83e1ea 100644
--- a/net/minecraft/world/entity/animal/parrot/Parrot.java
+++ b/net/minecraft/world/entity/animal/parrot/Parrot.java
@@ -164,6 +164,7 @@ public class Parrot extends ShoulderRidingEntity implements FlyingAnimal {
@@ -164,6 +_,7 @@
protected void registerGoals() {
this.goalSelector.addGoal(0, new TamableAnimal.TamableAnimalPanicGoal(1.25));
this.goalSelector.addGoal(0, new FloatGoal(this));
@@ -16,7 +8,7 @@ index 62a26395ee0c3ee450ad3b1ac88bc85523dd27b4..0337ddcd664cd0329d98286214d1aa4d
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));
@@ -269,7 +270,7 @@ public class Parrot extends ShoulderRidingEntity implements FlyingAnimal {
@@ -270,7 +_,7 @@
}
if (!this.level().isClientSide()) {
@@ -25,33 +17,33 @@ index 62a26395ee0c3ee450ad3b1ac88bc85523dd27b4..0337ddcd664cd0329d98286214d1aa4d
this.tame(player);
this.level().broadcastEntityEvent(this, EntityEvent.TAMING_SUCCEEDED);
} else {
@@ -277,6 +278,7 @@ public class Parrot extends ShoulderRidingEntity implements FlyingAnimal {
@@ -278,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)) {
} else if (!itemStack.is(ItemTags.PARROT_POISONOUS_FOOD)) {
if (!this.isFlying() && this.isTame() && this.isOwnedBy(player)) {
@@ -301,7 +303,7 @@ public class Parrot extends ShoulderRidingEntity implements FlyingAnimal {
@@ -302,7 +_,7 @@
@Override
public boolean isFood(ItemStack stack) {
public boolean isFood(final ItemStack itemStack) {
- return false;
+ return this.level().purpurConfig.parrotBreedable && stack.is(ItemTags.PARROT_FOOD); // Purpur - Breedable parrots
}
public static boolean checkParrotSpawnRules(
@@ -316,12 +318,12 @@ public class Parrot extends ShoulderRidingEntity implements FlyingAnimal {
@@ -317,12 +_,12 @@
@Override
public boolean canMate(Animal otherAnimal) {
public boolean canMate(final Animal partner) {
- return false;
+ return super.canMate(otherAnimal); // Purpur - Breedable parrots
}
@Override
public @Nullable AgeableMob getBreedOffspring(ServerLevel level, AgeableMob partner) {
public @Nullable AgeableMob getBreedOffspring(final ServerLevel level, final AgeableMob partner) {
- return null;
+ return level.purpurConfig.parrotBreedable ? EntityType.PARROT.create(level, EntitySpawnReason.BREEDING) : null; // Purpur - Breedable parrots
}

View File

@@ -0,0 +1,22 @@
--- a/net/minecraft/world/entity/animal/pig/Pig.java
+++ b/net/minecraft/world/entity/animal/pig/Pig.java
@@ -158,6 +_,19 @@
@Override
public InteractionResult mobInteract(final Player player, final InteractionHand hand) {
boolean hasFood = this.isFood(player.getItemInHand(hand));
+ // Purpur start - Pigs give saddle back
+ if (level().purpurConfig.pigGiveSaddleBack && player.isSecondaryUseActive() && !hasFood && isSaddled() && !isVehicle()) {
+ this.setItemSlot(EquipmentSlot.SADDLE, ItemStack.EMPTY);
+ 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 (!hasFood && this.isSaddled() && !this.isVehicle() && !player.isSecondaryUseActive()) {
if (!this.level().isClientSide()) {
player.startRiding(this);

View File

@@ -1,14 +1,6 @@
From 56a0a83ddb1b7472dbc9762e2aca396605c62085 Mon Sep 17 00:00:00 2001
From: File <noreply+automated@papermc.io>
Date: Sun, 20 Apr 1997 05:37:42 -0800
Subject: [PATCH] purpur File Patches
diff --git a/net/minecraft/world/entity/animal/polarbear/PolarBear.java b/net/minecraft/world/entity/animal/polarbear/PolarBear.java
index 8fd0d632e7c6fc7fcb7e9cf141638b5171800799..df4b4a4d32019ef3a667841a0ce4485a8325e897 100644
--- a/net/minecraft/world/entity/animal/polarbear/PolarBear.java
+++ b/net/minecraft/world/entity/animal/polarbear/PolarBear.java
@@ -66,6 +66,29 @@ public class PolarBear extends Animal implements NeutralMob {
@@ -67,6 +_,29 @@
super(type, level);
}
@@ -36,21 +28,21 @@ index 8fd0d632e7c6fc7fcb7e9cf141638b5171800799..df4b4a4d32019ef3a667841a0ce4485a
+ // Purpur end - Breedable Polar Bears
+
@Override
public @Nullable AgeableMob getBreedOffspring(ServerLevel level, AgeableMob partner) {
public @Nullable AgeableMob getBreedOffspring(final ServerLevel level, final AgeableMob partner) {
return EntityType.POLAR_BEAR.create(level, EntitySpawnReason.BREEDING);
@@ -73,7 +96,7 @@ public class PolarBear extends Animal implements NeutralMob {
@@ -74,7 +_,7 @@
@Override
public boolean isFood(ItemStack stack) {
public boolean isFood(final ItemStack itemStack) {
- return false;
+ return level().purpurConfig.polarBearBreedableItem != null && stack.getItem() == level().purpurConfig.polarBearBreedableItem; // Purpur - Breedable Polar Bears
+ return level().purpurConfig.polarBearBreedableItem != null && itemStack.getItem() == level().purpurConfig.polarBearBreedableItem; // Purpur - Breedable Polar Bears
}
@Override
@@ -82,6 +105,12 @@ public class PolarBear extends Animal implements NeutralMob {
@@ -83,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));
this.goalSelector.addGoal(1, new PanicGoal(this, 2.0, bear -> bear.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));

View File

@@ -0,0 +1,26 @@
--- a/net/minecraft/world/entity/animal/rabbit/Rabbit.java
+++ b/net/minecraft/world/entity/animal/rabbit/Rabbit.java
@@ -419,10 +_,23 @@
}
this.setVariant(variant);
+
+ // Purpur start - Special mobs naturally spawn
+ if (variant != 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, groupData);
}
private static Rabbit.Variant getRandomRabbitVariant(final LevelAccessor level, final 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 randomVal = level.getRandom().nextInt(100);
if (biome.is(BiomeTags.SPAWNS_WHITE_RABBITS)) {

View File

@@ -1,16 +1,8 @@
From 56a0a83ddb1b7472dbc9762e2aca396605c62085 Mon Sep 17 00:00:00 2001
From: File <noreply+automated@papermc.io>
Date: Sun, 20 Apr 1997 05:37:42 -0800
Subject: [PATCH] purpur File Patches
diff --git a/net/minecraft/world/entity/animal/squid/Squid.java b/net/minecraft/world/entity/animal/squid/Squid.java
index 0e13879ce2802ff8ef0ee9b745a23396727c3e30..504573bf4cbdf1debfa9f9bd071fa40d443b860d 100644
--- a/net/minecraft/world/entity/animal/squid/Squid.java
+++ b/net/minecraft/world/entity/animal/squid/Squid.java
@@ -48,10 +48,29 @@ public class Squid extends AgeableWaterCreature {
@@ -51,10 +_,29 @@
public Squid(EntityType<? extends Squid> type, Level level) {
public Squid(final EntityType<? extends Squid> type, final Level level) {
super(type, 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
@@ -39,20 +31,20 @@ index 0e13879ce2802ff8ef0ee9b745a23396727c3e30..504573bf4cbdf1debfa9f9bd071fa40d
@Override
protected void registerGoals() {
this.goalSelector.addGoal(0, new Squid.SquidRandomMovementGoal(this));
@@ -128,6 +147,7 @@ public class Squid extends AgeableWaterCreature {
@@ -131,6 +_,7 @@
}
if (this.isInWater()) {
+ 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;
@@ -308,7 +328,7 @@ public class Squid extends AgeableWaterCreature {
float tentacleScale = this.tentacleMovement / (float) Math.PI;
this.tentacleAngle = Mth.sin(tentacleScale * tentacleScale * (float) Math.PI) * (float) Math.PI * 0.25F;
@@ -321,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);
float angle = this.squid.getRandom().nextFloat() * (float) (Math.PI * 2);
this.squid.movementVector = new Vec3(Mth.cos(angle) * 0.2F, -0.1F + this.squid.getRandom().nextFloat() * 0.2F, Mth.sin(angle) * 0.2F);
}

View File

@@ -1,17 +1,9 @@
From 56a0a83ddb1b7472dbc9762e2aca396605c62085 Mon Sep 17 00:00:00 2001
From: File <noreply+automated@papermc.io>
Date: Sun, 20 Apr 1997 05:37:42 -0800
Subject: [PATCH] purpur File Patches
diff --git a/net/minecraft/world/entity/animal/wolf/Wolf.java b/net/minecraft/world/entity/animal/wolf/Wolf.java
index ffad6072280fb4d02f0a37a97d8c83fba85d3bc2..725624f63a2fbf0bd489a92e2c5862c82d72556c 100644
--- a/net/minecraft/world/entity/animal/wolf/Wolf.java
+++ b/net/minecraft/world/entity/animal/wolf/Wolf.java
@@ -100,6 +100,37 @@ public class Wolf extends TamableAnimal implements NeutralMob {
EntityType<?> type = entity.getType();
return type == EntityType.SHEEP || type == EntityType.RABBIT || type == EntityType.FOX;
};
@@ -97,6 +_,37 @@
public static final TargetingConditions.Selector PREY_SELECTOR = (target, level) -> target.is(EntityType.SHEEP)
|| target.is(EntityType.RABBIT)
|| target.is(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;
@@ -46,8 +38,8 @@ index ffad6072280fb4d02f0a37a97d8c83fba85d3bc2..725624f63a2fbf0bd489a92e2c5862c8
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;
@@ -121,12 +152,47 @@ public class Wolf extends TamableAnimal implements NeutralMob {
this.setPathfindingMalus(PathType.DANGER_POWDER_SNOW, -1.0F);
@@ -118,12 +_,47 @@
this.setPathfindingMalus(PathType.ON_TOP_OF_POWDER_SNOW, -1.0F);
}
+ // Purpur start - Configurable chance for wolves to spawn rabid
@@ -94,7 +86,7 @@ index ffad6072280fb4d02f0a37a97d8c83fba85d3bc2..725624f63a2fbf0bd489a92e2c5862c8
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));
@@ -139,7 +205,7 @@ public class Wolf extends TamableAnimal implements NeutralMob {
@@ -136,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));
@@ -103,15 +95,15 @@ index ffad6072280fb4d02f0a37a97d8c83fba85d3bc2..725624f63a2fbf0bd489a92e2c5862c8
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));
@@ -229,6 +295,7 @@ public class Wolf extends TamableAnimal implements NeutralMob {
protected void addAdditionalSaveData(ValueOutput output) {
@@ -231,6 +_,7 @@
protected void addAdditionalSaveData(final ValueOutput output) {
super.addAdditionalSaveData(output);
output.store("CollarColor", DyeColor.LEGACY_ID_CODEC, this.getCollarColor());
+ output.putBoolean("Purpur.IsRabid", this.isRabid); // Purpur - Configurable chance for wolves to spawn rabid
VariantUtils.writeVariant(output, this.getVariant());
this.addPersistentAngerSaveData(output);
this.getSoundVariant()
@@ -243,6 +310,10 @@ public class Wolf extends TamableAnimal implements NeutralMob {
@@ -245,6 +_,10 @@
super.readAdditionalSaveData(input);
VariantUtils.readVariant(input, Registries.WOLF_VARIANT).ifPresent(this::setVariant);
this.setCollarColor(input.read("CollarColor", DyeColor.LEGACY_ID_CODEC).orElse(DEFAULT_COLLAR_COLOR));
@@ -121,8 +113,8 @@ index ffad6072280fb4d02f0a37a97d8c83fba85d3bc2..725624f63a2fbf0bd489a92e2c5862c8
+ // Purpur end - Configurable chance for wolves to spawn rabid
this.readPersistentAngerSaveData(this.level(), input);
input.read("sound_variant", ResourceKey.codec(Registries.WOLF_SOUND_VARIANT))
.flatMap(resourceKey -> this.registryAccess().lookupOrThrow(Registries.WOLF_SOUND_VARIANT).get((ResourceKey<WolfSoundVariant>)resourceKey))
@@ -266,6 +337,10 @@ public class Wolf extends TamableAnimal implements NeutralMob {
.flatMap(soundVariant -> this.registryAccess().lookupOrThrow(Registries.WOLF_SOUND_VARIANT).get((ResourceKey<WolfSoundVariant>)soundVariant))
@@ -268,6 +_,10 @@
}
this.setSoundVariant(WolfSoundVariants.pickRandomSoundVariant(this.registryAccess(), level.getRandom()));
@@ -130,10 +122,10 @@ index ffad6072280fb4d02f0a37a97d8c83fba85d3bc2..725624f63a2fbf0bd489a92e2c5862c8
+ 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);
return super.finalizeSpawn(level, difficulty, spawnReason, groupData);
}
@@ -316,6 +391,11 @@ public class Wolf extends TamableAnimal implements NeutralMob {
@@ -316,6 +_,11 @@
public void tick() {
super.tick();
if (this.isAlive()) {
@@ -145,8 +137,8 @@ index ffad6072280fb4d02f0a37a97d8c83fba85d3bc2..725624f63a2fbf0bd489a92e2c5862c8
this.interestedAngleO = this.interestedAngle;
if (this.isInterested()) {
this.interestedAngle = this.interestedAngle + (1.0F - this.interestedAngle) * 0.4F;
@@ -517,13 +597,27 @@ public class Wolf extends TamableAnimal implements NeutralMob {
itemInHand.consume(1, player);
@@ -504,13 +_,27 @@
itemStack.consume(1, player);
this.tryToTame(player);
return InteractionResult.SUCCESS_SERVER;
+ // Purpur start - Configurable chance for wolves to spawn rabid
@@ -168,7 +160,7 @@ index ffad6072280fb4d02f0a37a97d8c83fba85d3bc2..725624f63a2fbf0bd489a92e2c5862c8
return super.mobInteract(player, hand);
}
private void tryToTame(Player player) {
private void tryToTame(final Player player) {
- if (this.random.nextInt(3) == 0 && !org.bukkit.craftbukkit.event.CraftEventFactory.callEntityTameEvent(this, player).isCancelled()) { // CraftBukkit - added event call
+ 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 // Purpur - Config to always tame in Creative
this.tame(player);

View File

@@ -1,14 +1,6 @@
From 56a0a83ddb1b7472dbc9762e2aca396605c62085 Mon Sep 17 00:00:00 2001
From: File <noreply+automated@papermc.io>
Date: Sun, 20 Apr 1997 05:37:42 -0800
Subject: [PATCH] purpur File Patches
diff --git a/net/minecraft/world/entity/boss/enderdragon/EndCrystal.java b/net/minecraft/world/entity/boss/enderdragon/EndCrystal.java
index c095f42aa103b7874fb5d8dcece1b1484c2e2968..d1c593ccfab7bee4366ee7c56606a230964e3fb7 100644
--- a/net/minecraft/world/entity/boss/enderdragon/EndCrystal.java
+++ b/net/minecraft/world/entity/boss/enderdragon/EndCrystal.java
@@ -39,6 +39,24 @@ public class EndCrystal extends Entity {
@@ -39,6 +_,24 @@
this.setPos(x, y, z);
}
@@ -33,7 +25,7 @@ index c095f42aa103b7874fb5d8dcece1b1484c2e2968..d1c593ccfab7bee4366ee7c56606a230
@Override
protected Entity.MovementEmission getMovementEmission() {
return Entity.MovementEmission.NONE;
@@ -75,6 +93,8 @@ public class EndCrystal extends Entity {
@@ -75,6 +_,8 @@
}
}
// Paper end - Fix invulnerable end crystals
@@ -42,12 +34,12 @@ index c095f42aa103b7874fb5d8dcece1b1484c2e2968..d1c593ccfab7bee4366ee7c56606a230
}
@Override
@@ -115,15 +135,17 @@ public class EndCrystal extends Entity {
@@ -115,15 +_,17 @@
}
// CraftBukkit end
if (!damageSource.is(DamageTypeTags.IS_EXPLOSION)) {
if (!source.is(DamageTypeTags.IS_EXPLOSION)) {
+ if (shouldExplode()) {// Purpur - End crystal explosion options
DamageSource damageSource1 = damageSource.getEntity() != null ? this.damageSources().explosion(this, damageSource.getEntity()) : null;
DamageSource damageSource = source.getEntity() != null ? this.damageSources().explosion(this, source.getEntity()) : null;
// CraftBukkit start
- org.bukkit.event.entity.ExplosionPrimeEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callExplosionPrimeEvent(this, 6.0F, false);
+ org.bukkit.event.entity.ExplosionPrimeEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callExplosionPrimeEvent(this, getExplosionPower(), hasExplosionFire()); // Purpur - End crystal explosion options
@@ -56,8 +48,8 @@ index c095f42aa103b7874fb5d8dcece1b1484c2e2968..d1c593ccfab7bee4366ee7c56606a230
}
this.remove(Entity.RemovalReason.KILLED, org.bukkit.event.entity.EntityRemoveEvent.Cause.EXPLODE); // Paper - add Bukkit remove cause
- level.explode(this, damageSource1, null, this.getX(), this.getY(), this.getZ(), event.getRadius(), event.getFire(), Level.ExplosionInteraction.BLOCK);
+ level.explode(this, damageSource1, null, this.getX(), this.getY(), this.getZ(), event.getRadius(), event.getFire(), getExplosionEffect()); // Purpur - End crystal explosion options
- level.explode(this, damageSource, null, this.getX(), this.getY(), this.getZ(), event.getRadius(), event.getFire(), Level.ExplosionInteraction.BLOCK);
+ level.explode(this, damageSource, null, this.getX(), this.getY(), this.getZ(), event.getRadius(), event.getFire(), getExplosionEffect()); // Purpur - End crystal explosion options
+ } else this.unsetRemoved(); // Purpur - End crystal explosion options
} else {
this.remove(Entity.RemovalReason.KILLED, org.bukkit.event.entity.EntityRemoveEvent.Cause.DEATH); // Paper - add Bukkit remove cause

View File

@@ -0,0 +1,19 @@
--- a/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java
+++ b/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java
@@ -964,6 +_,7 @@
@Override
protected boolean canRide(final Entity vehicle) {
+ if (this.level().purpurConfig.enderDragonCanRideVehicles) return this.boardingCooldown <= 0; // Purpur - Configs for if Wither/Ender Dragon can ride vehicles
return false;
}
@@ -999,7 +_,7 @@
boolean shouldDrop = level.getGameRules().get(GameRules.MOB_DROPS);
int xpCount = 500;
- if (this.dragonFight != null && !this.dragonFight.hasPreviouslyKilledDragon()) {
+ if (this.dragonFight != null && (level().purpurConfig.enderDragonAlwaysDropsFullExp || !this.dragonFight.hasPreviouslyKilledDragon())) { // Purpur - Ender dragon always drop full exp
xpCount = 12000;
}

View File

@@ -1,22 +1,14 @@
From 56a0a83ddb1b7472dbc9762e2aca396605c62085 Mon Sep 17 00:00:00 2001
From: File <noreply+automated@papermc.io>
Date: Sun, 20 Apr 1997 05:37:42 -0800
Subject: [PATCH] purpur File Patches
diff --git a/net/minecraft/world/entity/boss/wither/WitherBoss.java b/net/minecraft/world/entity/boss/wither/WitherBoss.java
index 86b6b94c3e63bb52917fe0f708d24aa813f433c7..be74b2f6e21e9adb1e5c96414854a5c4f07655fc 100644
--- a/net/minecraft/world/entity/boss/wither/WitherBoss.java
+++ b/net/minecraft/world/entity/boss/wither/WitherBoss.java
@@ -80,6 +80,7 @@ public class WitherBoss extends Monster implements RangedAttackMob {
private static final TargetingConditions.Selector LIVING_ENTITY_SELECTOR = (entity, level) -> !entity.getType().is(EntityTypeTags.WITHER_FRIENDS)
&& entity.attackable();
@@ -82,6 +_,7 @@
private static final TargetingConditions.Selector LIVING_ENTITY_SELECTOR = (target, level) -> !target.is(EntityTypeTags.WITHER_FRIENDS)
&& target.attackable();
private static final TargetingConditions TARGETING_CONDITIONS = TargetingConditions.forCombat().range(20.0).selector(LIVING_ENTITY_SELECTOR);
+ private java.util.@Nullable UUID summoner; // Purpur - Summoner API
public WitherBoss(EntityType<? extends WitherBoss> type, Level level) {
public WitherBoss(final EntityType<? extends WitherBoss> type, final Level level) {
super(type, level);
@@ -88,6 +89,16 @@ public class WitherBoss extends Monster implements RangedAttackMob {
@@ -90,6 +_,16 @@
this.xpReward = 50;
}
@@ -31,17 +23,17 @@ index 86b6b94c3e63bb52917fe0f708d24aa813f433c7..be74b2f6e21e9adb1e5c96414854a5c4
+ // Purpur end - Summoner API
+
@Override
protected PathNavigation createNavigation(Level level) {
protected PathNavigation createNavigation(final Level level) {
FlyingPathNavigation flyingPathNavigation = new FlyingPathNavigation(this, level);
@@ -120,6 +131,7 @@ public class WitherBoss extends Monster implements RangedAttackMob {
protected void addAdditionalSaveData(ValueOutput output) {
@@ -122,6 +_,7 @@
protected void addAdditionalSaveData(final ValueOutput output) {
super.addAdditionalSaveData(output);
output.putInt("Invul", this.getInvulnerableTicks());
+ output.storeNullable("Purpur.Summoner", net.minecraft.core.UUIDUtil.CODEC, getSummoner()); // Purpur - Summoner API
}
@Override
@@ -129,6 +141,7 @@ public class WitherBoss extends Monster implements RangedAttackMob {
@@ -131,6 +_,7 @@
if (this.hasCustomName()) {
this.bossEvent.setName(this.getDisplayName());
}
@@ -49,7 +41,7 @@ index 86b6b94c3e63bb52917fe0f708d24aa813f433c7..be74b2f6e21e9adb1e5c96414854a5c4
}
@Override
@@ -272,7 +285,7 @@ public class WitherBoss extends Monster implements RangedAttackMob {
@@ -274,7 +_,7 @@
level.explode(this, this.getX(), this.getEyeY(), this.getZ(), event.getRadius(), event.getFire(), Level.ExplosionInteraction.MOB);
}
// CraftBukkit end
@@ -58,7 +50,7 @@ index 86b6b94c3e63bb52917fe0f708d24aa813f433c7..be74b2f6e21e9adb1e5c96414854a5c4
// CraftBukkit start - Use relative location for far away sounds
// level.globalLevelEvent(LevelEvent.SOUND_WITHER_BOSS_SPAWN, this.blockPosition(), 0);
int viewDistance = level.getCraftServer().getViewDistance() * 16;
@@ -379,8 +392,10 @@ public class WitherBoss extends Monster implements RangedAttackMob {
@@ -378,8 +_,10 @@
}
}
@@ -71,10 +63,10 @@ index 86b6b94c3e63bb52917fe0f708d24aa813f433c7..be74b2f6e21e9adb1e5c96414854a5c4
}
this.bossEvent.setProgress(this.getHealth() / this.getMaxHealth());
@@ -577,6 +592,7 @@ public class WitherBoss extends Monster implements RangedAttackMob {
@@ -576,6 +_,7 @@
@Override
protected boolean canRide(Entity entity) {
protected boolean canRide(final Entity vehicle) {
+ if (this.level().purpurConfig.witherCanRideVehicles) return this.boardingCooldown <= 0; // Purpur - Configs for if Wither/Ender Dragon can ride vehicles
return false;
}

View File

@@ -0,0 +1,46 @@
--- a/net/minecraft/world/entity/item/ItemEntity.java
+++ b/net/minecraft/world/entity/item/ItemEntity.java
@@ -54,6 +_,12 @@
public boolean canMobPickup = true; // Paper - Item#canEntityPickup
private int despawnRate = -1; // Paper - Alternative item-despawn-rate
public net.kyori.adventure.util.TriState frictionState = net.kyori.adventure.util.TriState.NOT_SET; // Paper - Friction API
+ // Purpur start - Item entity immunities
+ public boolean immuneToCactus = false;
+ public boolean immuneToExplosion = false;
+ public boolean immuneToFire = false;
+ public boolean immuneToLightning = false;
+ // Purpur end - Item entity immunities
public ItemEntity(final EntityType<? extends ItemEntity> type, final Level level) {
super(type, level);
@@ -314,7 +_,16 @@
@Override
public final boolean hurtServer(final ServerLevel level, final DamageSource source, final float damage) {
- if (this.isInvulnerableToBase(source)) {
+ // Purpur start - Item entity immunities
+ if (
+ (immuneToCactus && source.is(net.minecraft.world.damagesource.DamageTypes.CACTUS)) ||
+ (immuneToFire && (source.is(net.minecraft.tags.DamageTypeTags.IS_FIRE) || source.is(net.minecraft.world.damagesource.DamageTypes.ON_FIRE) || source.is(net.minecraft.world.damagesource.DamageTypes.IN_FIRE))) ||
+ (immuneToLightning && source.is(net.minecraft.world.damagesource.DamageTypes.LIGHTNING_BOLT)) ||
+ (immuneToExplosion && source.is(net.minecraft.tags.DamageTypeTags.IS_EXPLOSION))
+ ) {
+ return false;
+ } else if (this.isInvulnerableToBase(source)) {
+ // Purpur end - Item entity immunities
return false;
} else if (!level.getGameRules().get(GameRules.MOB_GRIEFING) && source.getEntity() instanceof Mob) {
return false;
@@ -492,6 +_,12 @@
public void setItem(final ItemStack itemStack) {
this.getEntityData().set(DATA_ITEM, itemStack);
this.despawnRate = this.level().paperConfig().entities.spawning.altItemDespawnRate.enabled ? this.level().paperConfig().entities.spawning.altItemDespawnRate.items.getOrDefault(itemStack.getItem(), this.level().spigotConfig.itemDespawnRate) : this.level().spigotConfig.itemDespawnRate; // Paper - Alternative item-despawn-rate
+ // Purpur start - Item entity immunities
+ if (level().purpurConfig.itemImmuneToCactus.contains(itemStack.getItem())) immuneToCactus = true;
+ if (level().purpurConfig.itemImmuneToExplosion.contains(itemStack.getItem())) immuneToExplosion = true;
+ if (level().purpurConfig.itemImmuneToFire.contains(itemStack.getItem())) immuneToFire = true;
+ if (level().purpurConfig.itemImmuneToLightning.contains(itemStack.getItem())) immuneToLightning = true;
+ // level end - Item entity immunities
}
public void setTarget(final @Nullable UUID target) {

View File

@@ -1,22 +1,14 @@
From 56a0a83ddb1b7472dbc9762e2aca396605c62085 Mon Sep 17 00:00:00 2001
From: File <noreply+automated@papermc.io>
Date: Sun, 20 Apr 1997 05:37:42 -0800
Subject: [PATCH] purpur File Patches
diff --git a/net/minecraft/world/entity/monster/Creeper.java b/net/minecraft/world/entity/monster/Creeper.java
index e6d93c7a339f06c40b78f554f4e7070fb7fcad02..168003b7159b5e9ea3e3ca19d0b939ed1cfd2311 100644
--- a/net/minecraft/world/entity/monster/Creeper.java
+++ b/net/minecraft/world/entity/monster/Creeper.java
@@ -56,6 +56,7 @@ public class Creeper extends Monster {
@@ -56,6 +_,7 @@
public int explosionRadius = 3;
public boolean droppedSkulls;
public @Nullable Entity entityIgniter; // CraftBukkit
+ private boolean exploding = false; // Purpur - Config to make Creepers explode on death
public Creeper(EntityType<? extends Creeper> type, Level level) {
public Creeper(final EntityType<? extends Creeper> type, final Level level) {
super(type, level);
@@ -159,6 +160,27 @@ public class Creeper extends Monster {
@@ -159,6 +_,27 @@
return false; // CraftBukkit
}
@@ -42,28 +34,28 @@ index e6d93c7a339f06c40b78f554f4e7070fb7fcad02..168003b7159b5e9ea3e3ca19d0b939ed
+ // Purpur end - Config to make Creepers explode on death
+
@Override
public SoundEvent getHurtSound(DamageSource damageSource) {
public SoundEvent getHurtSound(final DamageSource source) {
return SoundEvents.CREEPER_HURT;
@@ -243,14 +265,16 @@ public class Creeper extends Monster {
@@ -243,14 +_,16 @@
}
public void explodeCreeper() {
+ this.exploding = true; // Purpur - Config to make Creepers explode on death
if (this.level() instanceof ServerLevel serverLevel) {
float f = this.isPowered() ? 2.0F : 1.0F;
+ float multiplier = serverLevel.purpurConfig.creeperHealthRadius ? this.getHealth() / this.getMaxHealth() : 1; // Purpur - Config for health to impact Creeper explosion radius
if (this.level() instanceof ServerLevel level) {
float explosionMultiplier = this.isPowered() ? 2.0F : 1.0F;
+ float multiplier = level.purpurConfig.creeperHealthRadius ? this.getHealth() / this.getMaxHealth() : 1; // Purpur - Config for health to impact Creeper explosion radius
// CraftBukkit start
- org.bukkit.event.entity.ExplosionPrimeEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callExplosionPrimeEvent(this, this.explosionRadius * f, false);
+ org.bukkit.event.entity.ExplosionPrimeEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callExplosionPrimeEvent(this, (this.explosionRadius * f) * multiplier, false); // Purpur - Config for health to impact Creeper explosion radius
- org.bukkit.event.entity.ExplosionPrimeEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callExplosionPrimeEvent(this, this.explosionRadius * explosionMultiplier, false);
+ org.bukkit.event.entity.ExplosionPrimeEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callExplosionPrimeEvent(this, (this.explosionRadius * explosionMultiplier) * multiplier, false); // Purpur - Config for health to impact Creeper explosion radius
if (!event.isCancelled()) {
// CraftBukkit end
this.dead = true;
- serverLevel.explode(this, this.getX(), this.getY(), this.getZ(), event.getRadius(), event.getFire(), Level.ExplosionInteraction.MOB); // CraftBukkit // Paper - fix DamageSource API (revert to vanilla, no, just no, don't change this)
+ serverLevel.explode(this, this.getX(), this.getY(), this.getZ(), event.getRadius(), event.getFire(), serverLevel.getGameRules().get(net.minecraft.world.level.gamerules.GameRules.MOB_GRIEFING) && level().purpurConfig.creeperAllowGriefing ? Level.ExplosionInteraction.MOB : Level.ExplosionInteraction.NONE); // CraftBukkit // Paper - fix DamageSource API (revert to vanilla, no, just no, don't change this) // Purpur - Add enderman and creeper griefing controls
- level.explode(this, this.getX(), this.getY(), this.getZ(), event.getRadius(), event.getFire(), Level.ExplosionInteraction.MOB); // CraftBukkit // Paper - fix DamageSource API (revert to vanilla, no, just no, don't change this)
+ level.explode(this, this.getX(), this.getY(), this.getZ(), event.getRadius(), event.getFire(), level.getGameRules().get(net.minecraft.world.level.gamerules.GameRules.MOB_GRIEFING) && level().purpurConfig.creeperAllowGriefing ? Level.ExplosionInteraction.MOB : Level.ExplosionInteraction.NONE); // CraftBukkit // Paper - fix DamageSource API (revert to vanilla, no, just no, don't change this) // Purpur - Add enderman and creeper griefing controls
this.spawnLingeringCloud();
this.triggerOnDeathMobEffects(serverLevel, Entity.RemovalReason.KILLED);
this.triggerOnDeathMobEffects(level, Entity.RemovalReason.KILLED);
this.discard(org.bukkit.event.entity.EntityRemoveEvent.Cause.EXPLODE); // CraftBukkit - add Bukkit remove cause
@@ -261,6 +285,7 @@ public class Creeper extends Monster {
@@ -261,6 +_,7 @@
}
// CraftBukkit end
}

View File

@@ -0,0 +1,14 @@
--- a/net/minecraft/world/entity/monster/Ghast.java
+++ b/net/minecraft/world/entity/monster/Ghast.java
@@ -156,6 +_,11 @@
public static boolean checkGhastSpawnRules(
final EntityType<Ghast> type, final LevelAccessor level, final EntitySpawnReason spawnReason, final BlockPos pos, final RandomSource random
) {
+ // Purpur start - Config to disable hostile mob spawn on ice
+ if (net.minecraft.world.entity.monster.Monster.canSpawnInBlueAndPackedIce(level, pos)) {
+ return false;
+ }
+ // Purpur end - Config to disable hostile mob spawn on ice
return level.getDifficulty() != Difficulty.PEACEFUL && random.nextInt(20) == 0 && checkMobSpawnRules(type, level, spawnReason, pos, random);
}

View File

@@ -1,17 +1,9 @@
From 56a0a83ddb1b7472dbc9762e2aca396605c62085 Mon Sep 17 00:00:00 2001
From: File <noreply+automated@papermc.io>
Date: Sun, 20 Apr 1997 05:37:42 -0800
Subject: [PATCH] purpur File Patches
diff --git a/net/minecraft/world/entity/monster/Monster.java b/net/minecraft/world/entity/monster/Monster.java
index 07293a33c45a0834f3b623a47a1bd25f3e059f54..54033572e325f8486a438e31dde34f8407f9180a 100644
--- a/net/minecraft/world/entity/monster/Monster.java
+++ b/net/minecraft/world/entity/monster/Monster.java
@@ -84,6 +84,11 @@ public abstract class Monster extends PathfinderMob implements Enemy {
@@ -84,6 +_,11 @@
}
public static boolean isDarkEnoughToSpawn(ServerLevelAccessor level, BlockPos pos, RandomSource random) {
public static boolean isDarkEnoughToSpawn(final ServerLevelAccessor level, final BlockPos pos, final RandomSource random) {
+ // Purpur start - Config to disable hostile mob spawn on ice
+ if (canSpawnInBlueAndPackedIce(level, pos)) {
+ return false;
@@ -20,19 +12,19 @@ index 07293a33c45a0834f3b623a47a1bd25f3e059f54..54033572e325f8486a438e31dde34f84
if (level.getBrightness(LightLayer.SKY, pos) > random.nextInt(32)) {
return false;
} else {
@@ -109,6 +114,11 @@ public abstract class Monster extends PathfinderMob implements Enemy {
@@ -113,6 +_,11 @@
public static boolean checkAnyLightMonsterSpawnRules(
EntityType<? extends Monster> entityType, LevelAccessor level, EntitySpawnReason spawnReason, BlockPos pos, RandomSource random
final EntityType<? extends Monster> type, final LevelAccessor level, final EntitySpawnReason spawnReason, final BlockPos pos, final RandomSource random
) {
+ // Purpur start - Config to disable hostile mob spawn on ice
+ if (canSpawnInBlueAndPackedIce(level, pos)) {
+ return false;
+ }
+ // Purpur end - Config to disable hostile mob spawn on ice
return level.getDifficulty() != Difficulty.PEACEFUL && checkMobSpawnRules(entityType, level, spawnReason, pos, random);
return level.getDifficulty() != Difficulty.PEACEFUL && checkMobSpawnRules(type, level, spawnReason, pos, random);
}
@@ -146,4 +156,12 @@ public abstract class Monster extends PathfinderMob implements Enemy {
@@ -154,4 +_,12 @@
return ItemStack.EMPTY;
}
}

View File

@@ -0,0 +1,15 @@
--- a/net/minecraft/world/entity/monster/Phantom.java
+++ b/net/minecraft/world/entity/monster/Phantom.java
@@ -167,7 +_,11 @@
final ServerLevelAccessor level, final DifficultyInstance difficulty, final EntitySpawnReason spawnReason, final @Nullable SpawnGroupData groupData
) {
this.anchorPoint = this.blockPosition().above(5);
- this.setPhantomSize(0);
+ // Purpur start - Configurable phantom size
+ int min = level.getLevel().purpurConfig.phantomMinSize;
+ int max = level.getLevel().purpurConfig.phantomMaxSize;
+ this.setPhantomSize(min == max ? min : level.getRandom().nextInt(max + 1 - min) + min);
+ // Purpur end - Configurable phantom size
return super.finalizeSpawn(level, difficulty, spawnReason, groupData);
}

View File

@@ -1,14 +1,6 @@
From 56a0a83ddb1b7472dbc9762e2aca396605c62085 Mon Sep 17 00:00:00 2001
From: File <noreply+automated@papermc.io>
Date: Sun, 20 Apr 1997 05:37:42 -0800
Subject: [PATCH] purpur File Patches
diff --git a/net/minecraft/world/entity/monster/Ravager.java b/net/minecraft/world/entity/monster/Ravager.java
index 631092f088355be45f598bb91bd5d38a39a55d5b..a10c693a8948d1b7c4bd06b957a08a9cea9170ad 100644
--- a/net/minecraft/world/entity/monster/Ravager.java
+++ b/net/minecraft/world/entity/monster/Ravager.java
@@ -76,6 +76,7 @@ public class Ravager extends Raider {
@@ -74,6 +_,7 @@
protected void registerGoals() {
super.registerGoals();
this.goalSelector.addGoal(0, new FloatGoal(this));
@@ -16,12 +8,12 @@ index 631092f088355be45f598bb91bd5d38a39a55d5b..a10c693a8948d1b7c4bd06b957a08a9c
this.goalSelector.addGoal(4, new MeleeAttackGoal(this, 1.0, true));
this.goalSelector.addGoal(5, new WaterAvoidingRandomStrollGoal(this, 0.4));
this.goalSelector.addGoal(6, new LookAtPlayerGoal(this, Player.class, 6.0F));
@@ -154,7 +155,7 @@ public class Ravager extends Raider {
@@ -152,7 +_,7 @@
)) {
BlockState blockState = serverLevel.getBlockState(blockPos);
Block block = blockState.getBlock();
BlockState state = serverLevel.getBlockState(pos);
Block block = state.getBlock();
- if (block instanceof LeavesBlock) {
+ if (this.level().purpurConfig.ravagerGriefableBlocks.contains(block)) { // Purpur - Configurable ravager griefable blocks list
// CraftBukkit start
if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(this, blockPos, blockState.getFluidState().createLegacyBlock())) { // Paper - fix wrong block state
if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(this, pos, state.getFluidState().createLegacyBlock())) { // Paper - fix wrong block state
continue;

View File

@@ -9,3 +9,60 @@
private float currentPeekAmountO;
private float currentPeekAmount;
private @Nullable BlockPos clientOldAttachPosition;
@@ -94,6 +_,21 @@
this.lookControl = new Shulker.ShulkerLookControl(this);
}
+ // Purpur start - Shulker change color with dye
+ @Override
+ protected net.minecraft.world.InteractionResult mobInteract(Player player, net.minecraft.world.InteractionHand hand) {
+ net.minecraft.world.item.ItemStack itemstack = player.getItemInHand(hand);
+ if (player.level().purpurConfig.shulkerChangeColorWithDye && itemstack.getItem() instanceof net.minecraft.world.item.DyeItem dye && dye.getDyeColor() != this.getColor()) {
+ this.setVariant(Optional.of(dye.getDyeColor()));
+ if (!player.getAbilities().instabuild) {
+ itemstack.shrink(1);
+ }
+ return net.minecraft.world.InteractionResult.SUCCESS;
+ }
+ return super.mobInteract(player, hand);
+ }
+ // Purpur end - Shulker change color with dye
+
@Override
protected void registerGoals() {
this.goalSelector.addGoal(1, new LookAtPlayerGoal(this, Player.class, 8.0F, 0.02F, true));
@@ -455,11 +_,21 @@
private void hitByShulkerBullet() {
Vec3 oldPosition = this.position();
AABB oldAabb = this.getBoundingBox();
- if (!this.isClosed() && this.teleportSomewhere()) {
- int shulkerCount = this.level().getEntities(EntityType.SHULKER, oldAabb.inflate(8.0), Entity::isAlive).size();
- float failureChance = (shulkerCount - 1) / 5.0F;
- if (!(this.level().getRandom().nextFloat() < failureChance)) {
+ // Purpur start - Shulker spawn from bullet options
+ if ((!this.level().purpurConfig.shulkerSpawnFromBulletRequireOpenLid || !this.isClosed()) && this.teleportSomewhere()) {
+ float failureChance = this.level().purpurConfig.shulkerSpawnFromBulletBaseChance;
+ if (!this.level().purpurConfig.shulkerSpawnFromBulletNearbyEquation.isBlank()) {
+ int shulkerCount = this.level().getEntities((net.minecraft.world.level.entity.EntityTypeTest) EntityType.SHULKER, oldAabb.inflate(this.level().purpurConfig.shulkerSpawnFromBulletNearbyRange), Entity::isAlive).size();
+ try {
+ failureChance -= ((Number) scriptEngine.eval("let shulkerCount = " + shulkerCount + "; " + this.level().purpurConfig.shulkerSpawnFromBulletNearbyEquation)).floatValue();
+ } catch (javax.script.ScriptException e) {
+ e.printStackTrace();
+ failureChance -= (shulkerCount - 1) / 5.0F;
+ }
+ }
+ if (this.level().getRandom().nextFloat() <= failureChance) {
Shulker baby = EntityType.SHULKER.create(this.level(), EntitySpawnReason.BREEDING);
+ // Purpur end - Shulker spawn from bullet options
if (baby != null) {
baby.setVariant(this.getVariant());
baby.snapTo(oldPosition);
@@ -566,7 +_,7 @@
}
public Optional<DyeColor> getVariant() {
- return Optional.ofNullable(this.getColor());
+ return Optional.ofNullable(this.level().purpurConfig.shulkerSpawnFromBulletRandomColor ? DyeColor.random(this.level().random) : this.getColor()); // Purpur - Shulker spawn from bullet options
}
public @Nullable DyeColor getColor() {

View File

@@ -1,17 +1,9 @@
From 56a0a83ddb1b7472dbc9762e2aca396605c62085 Mon Sep 17 00:00:00 2001
From: File <noreply+automated@papermc.io>
Date: Sun, 20 Apr 1997 05:37:42 -0800
Subject: [PATCH] purpur File Patches
diff --git a/net/minecraft/world/entity/monster/Strider.java b/net/minecraft/world/entity/monster/Strider.java
index b451566378401e471a98db63df502b7c4cd20f42..beaffb771e6c8d4b992437997ab27be218425c5a 100644
--- a/net/minecraft/world/entity/monster/Strider.java
+++ b/net/minecraft/world/entity/monster/Strider.java
@@ -390,6 +390,18 @@ public class Strider extends Animal implements ItemSteerable {
@@ -400,6 +_,18 @@
@Override
public InteractionResult mobInteract(Player player, InteractionHand hand) {
boolean isFood = this.isFood(player.getItemInHand(hand));
public InteractionResult mobInteract(final Player player, final InteractionHand hand) {
boolean hasFood = this.isFood(player.getItemInHand(hand));
+ // Purpur start
+ if (level().purpurConfig.striderGiveSaddleBack && player.isSecondaryUseActive() && !isFood && isSaddled() && !isVehicle()) {
+ this.setItemSlot(EquipmentSlot.SADDLE, ItemStack.EMPTY);
@@ -24,6 +16,6 @@ index b451566378401e471a98db63df502b7c4cd20f42..beaffb771e6c8d4b992437997ab27be2
+ return InteractionResult.SUCCESS;
+ }
+ // Purpur end
if (!isFood && this.isSaddled() && !this.isVehicle() && !player.isSecondaryUseActive()) {
if (!hasFood && this.isSaddled() && !this.isVehicle() && !player.isSecondaryUseActive()) {
if (!this.level().isClientSide()) {
player.startRiding(this);

View File

@@ -1,14 +1,6 @@
From 56a0a83ddb1b7472dbc9762e2aca396605c62085 Mon Sep 17 00:00:00 2001
From: File <noreply+automated@papermc.io>
Date: Sun, 20 Apr 1997 05:37:42 -0800
Subject: [PATCH] purpur File Patches
diff --git a/net/minecraft/world/entity/monster/illager/Vindicator.java b/net/minecraft/world/entity/monster/illager/Vindicator.java
index bfad794ff21e2f97654fbb1207b14fd088aec721..0cdc52cf3b1bb9c00e6ca8c8e564de60e195d6fc 100644
--- a/net/minecraft/world/entity/monster/illager/Vindicator.java
+++ b/net/minecraft/world/entity/monster/illager/Vindicator.java
@@ -131,6 +131,11 @@ public class Vindicator extends AbstractIllager {
@@ -131,6 +_,11 @@
RandomSource random = level.getRandom();
this.populateDefaultEquipmentSlots(random, difficulty);
this.populateDefaultEquipmentEnchantments(level, random, difficulty);
@@ -17,6 +9,6 @@ index bfad794ff21e2f97654fbb1207b14fd088aec721..0cdc52cf3b1bb9c00e6ca8c8e564de60
+ setCustomName(Component.translatable("Johnny"));
+ }
+ // Purpur end - Special mobs naturally spawn
return spawnGroupData1;
return spawnGroupData;
}

View File

@@ -0,0 +1,29 @@
--- a/net/minecraft/world/entity/monster/piglin/PiglinAi.java
+++ b/net/minecraft/world/entity/monster/piglin/PiglinAi.java
@@ -669,14 +_,24 @@
}
public static boolean isWearingSafeArmor(final LivingEntity livingEntity) {
- for (EquipmentSlot slot : EquipmentSlotGroup.ARMOR) {
- if (livingEntity.getItemBySlot(slot).is(ItemTags.PIGLIN_SAFE_ARMOR)) {
+ for (EquipmentSlot equipmentSlot : EquipmentSlotGroup.ARMOR) {
+ // Purpur start - piglins ignore gold-trimmed armor
+ net.minecraft.world.item.ItemStack itemStack = livingEntity.getItemBySlot(equipmentSlot);
+ if (itemStack.is(ItemTags.PIGLIN_SAFE_ARMOR) || (livingEntity.level().purpurConfig.piglinIgnoresArmorWithGoldTrim && isWearingGoldTrim(itemStack))) {
+ // Purpur end - piglins ignore gold-trimmed armor
return true;
}
}
return false;
}
+
+ // Purpur start - piglins ignore gold-trimmed armor
+ private static boolean isWearingGoldTrim(net.minecraft.world.item.ItemStack itemstack) {
+ net.minecraft.world.item.equipment.trim.ArmorTrim armorTrim = itemstack.getComponents().get(net.minecraft.core.component.DataComponents.TRIM);
+ return armorTrim != null && armorTrim.material().is(net.minecraft.world.item.equipment.trim.TrimMaterials.GOLD);
+ }
+ // Purpur end - piglins ignore gold-trimmed armor
private static void stopWalking(final Piglin body) {
body.getBrain().eraseMemory(MemoryModuleType.WALK_TARGET);

View File

@@ -1,14 +1,6 @@
From 56a0a83ddb1b7472dbc9762e2aca396605c62085 Mon Sep 17 00:00:00 2001
From: File <noreply+automated@papermc.io>
Date: Sun, 20 Apr 1997 05:37:42 -0800
Subject: [PATCH] purpur File Patches
diff --git a/net/minecraft/world/entity/monster/skeleton/AbstractSkeleton.java b/net/minecraft/world/entity/monster/skeleton/AbstractSkeleton.java
index 0f5bfbfc97c2826de72985c4e2e1dec1d94337f2..1ba7777164c7fd8516c97e1bd964183df37c029f 100644
--- a/net/minecraft/world/entity/monster/skeleton/AbstractSkeleton.java
+++ b/net/minecraft/world/entity/monster/skeleton/AbstractSkeleton.java
@@ -137,7 +137,7 @@ public abstract class AbstractSkeleton extends Monster implements RangedAttackMo
@@ -142,7 +_,7 @@
this.populateDefaultEquipmentEnchantments(level, random, difficulty);
this.reassessWeaponGoal();
this.setCanPickUpLoot(level.getLevel().paperConfig().entities.behavior.mobsCanAlwaysPickUpLoot.skeletons || random.nextFloat() < 0.55F * difficulty.getSpecialMultiplier()); // Paper - Add world settings for mobs picking up loot
@@ -17,12 +9,12 @@ index 0f5bfbfc97c2826de72985c4e2e1dec1d94337f2..1ba7777164c7fd8516c97e1bd964183d
this.setItemSlot(EquipmentSlot.HEAD, new ItemStack(random.nextFloat() < 0.1F ? Blocks.JACK_O_LANTERN : Blocks.CARVED_PUMPKIN));
this.setDropChance(EquipmentSlot.HEAD, 0.0F);
}
@@ -184,7 +184,7 @@ public abstract class AbstractSkeleton extends Monster implements RangedAttackMo
double squareRoot = Math.sqrt(d * d + d2 * d2);
@@ -189,7 +_,7 @@
double distanceToTarget = Math.sqrt(xd * xd + zd * zd);
if (this.level() instanceof ServerLevel serverLevel) {
Projectile.Delayed<AbstractArrow> delayedEntity = Projectile.spawnProjectileUsingShootDelayed( // Paper - delayed
- arrow, serverLevel, projectile, d, d1 + squareRoot * 0.2F, d2, 1.6F, 14 - serverLevel.getDifficulty().getId() * 4
+ arrow, serverLevel, projectile, d, d1 + squareRoot * 0.2F, d2, 1.6F, serverLevel.purpurConfig.skeletonBowAccuracyMap.getOrDefault(serverLevel.getDifficulty().getId(), (float) (14 - serverLevel.getDifficulty().getId() * 4)) // Purpur - skeleton bow accuracy option
- arrow, serverLevel, projectile, xd, yd + distanceToTarget * 0.2F, zd, 1.6F, 14 - serverLevel.getDifficulty().getId() * 4
+ arrow, serverLevel, projectile, xd, yd + distanceToTarget * 0.2F, zd, 1.6F, serverLevel.purpurConfig.skeletonBowAccuracyMap.getOrDefault(serverLevel.getDifficulty().getId(), (float) (14 - serverLevel.getDifficulty().getId() * 4)) // Purpur - skeleton bow accuracy option
);
// Paper start - call EntityShootBowEvent

View File

@@ -1,21 +1,13 @@
From 56a0a83ddb1b7472dbc9762e2aca396605c62085 Mon Sep 17 00:00:00 2001
From: File <noreply+automated@papermc.io>
Date: Sun, 20 Apr 1997 05:37:42 -0800
Subject: [PATCH] purpur File Patches
diff --git a/net/minecraft/world/entity/monster/zombie/Drowned.java b/net/minecraft/world/entity/monster/zombie/Drowned.java
index db164101d440c503e2e88b1f31af7f0638faaec5..604d5e6a4962de61fb97988a2f3de2965908bada 100644
--- a/net/minecraft/world/entity/monster/zombie/Drowned.java
+++ b/net/minecraft/world/entity/monster/zombie/Drowned.java
@@ -86,10 +86,23 @@ public class Drowned extends Zombie implements RangedAttackMob {
@@ -93,10 +_,23 @@
this.goalSelector.addGoal(2, new Drowned.DrownedAttackGoal(this, 1.0, false));
this.goalSelector.addGoal(5, new Drowned.DrownedGoToBeachGoal(this, 1.0));
this.goalSelector.addGoal(6, new Drowned.DrownedSwimUpGoal(this, 1.0, this.level().getSeaLevel()));
+ if (level().purpurConfig.drownedBreakDoors) this.goalSelector.addGoal(6, new net.minecraft.world.entity.ai.goal.MoveThroughVillageGoal(this, 1.0D, true, 4, this::canBreakDoors)); // Purpur - Option to make drowned break doors
this.goalSelector.addGoal(7, new RandomStrollGoal(this, 1.0));
this.targetSelector.addGoal(1, new HurtByTargetGoal(this, Drowned.class).setAlertOthers(ZombifiedPiglin.class));
this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, Player.class, 10, true, false, (entity, level) -> this.okTarget(entity)));
this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, Player.class, 10, true, false, (target, level) -> this.okTarget(target)));
- if (this.level().spigotConfig.zombieAggressiveTowardsVillager) this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, AbstractVillager.class, false)); // Paper - Check drowned for villager aggression config
+ // Purpur start - Add option to disable zombie aggressiveness towards villagers
+ if (this.level().spigotConfig.zombieAggressiveTowardsVillager) this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, AbstractVillager.class, false) { // Paper - Check drowned for villager aggression config

View File

@@ -1,20 +1,12 @@
From 56a0a83ddb1b7472dbc9762e2aca396605c62085 Mon Sep 17 00:00:00 2001
From: File <noreply+automated@papermc.io>
Date: Sun, 20 Apr 1997 05:37:42 -0800
Subject: [PATCH] purpur File Patches
diff --git a/net/minecraft/world/entity/monster/zombie/ZombieVillager.java b/net/minecraft/world/entity/monster/zombie/ZombieVillager.java
index 8af935a11a0988f10a2908f6337504f7f6e13d1b..c6f271a921fde124df1a7c5d175cb83b420cd2e3 100644
--- a/net/minecraft/world/entity/monster/zombie/ZombieVillager.java
+++ b/net/minecraft/world/entity/monster/zombie/ZombieVillager.java
@@ -159,10 +159,10 @@ public class ZombieVillager extends Zombie implements VillagerDataHolder {
public InteractionResult mobInteract(Player player, InteractionHand hand) {
ItemStack itemInHand = player.getItemInHand(hand);
if (itemInHand.is(Items.GOLDEN_APPLE)) {
@@ -170,10 +_,10 @@
public InteractionResult mobInteract(final Player player, final InteractionHand hand) {
ItemStack itemStack = player.getItemInHand(hand);
if (itemStack.is(Items.GOLDEN_APPLE)) {
- if (this.hasEffect(MobEffects.WEAKNESS)) {
+ if (this.hasEffect(MobEffects.WEAKNESS) && level().purpurConfig.zombieVillagerCureEnabled) { // Purpur - Add option to disable zombie villagers cure
itemInHand.consume(1, player);
itemStack.consume(1, player);
if (!this.level().isClientSide()) {
- this.startConverting(player.getUUID(), this.random.nextInt(2401) + 3600);
+ this.startConverting(player.getUUID(), this.random.nextInt(level().purpurConfig.zombieVillagerCuringTimeMax - level().purpurConfig.zombieVillagerCuringTimeMin + 1) + level().purpurConfig.zombieVillagerCuringTimeMin); // Purpur - Customizable Zombie Villager curing times

View File

@@ -1,24 +1,16 @@
From 56a0a83ddb1b7472dbc9762e2aca396605c62085 Mon Sep 17 00:00:00 2001
From: File <noreply+automated@papermc.io>
Date: Sun, 20 Apr 1997 05:37:42 -0800
Subject: [PATCH] purpur File Patches
diff --git a/net/minecraft/world/entity/npc/villager/Villager.java b/net/minecraft/world/entity/npc/villager/Villager.java
index 89844d7e804cc8a2110b694e448bc5993991bea7..e117ae1b114c7e2ca314a00335473efc41137f7f 100644
--- a/net/minecraft/world/entity/npc/villager/Villager.java
+++ b/net/minecraft/world/entity/npc/villager/Villager.java
@@ -179,6 +179,8 @@ public class Villager extends AbstractVillager implements ReputationEventHandler
@@ -181,6 +_,8 @@
MemoryModuleType.MEETING_POINT,
(villager, poiType) -> poiType.is(PoiTypes.MEETING)
);
+ private boolean isLobotomized = false; public boolean isLobotomized() { return this.isLobotomized; } // Purpur - Lobotomize stuck villagers
+ private int notLobotomizedCount = 0; // Purpur - Lobotomize stuck villagers
public Villager(EntityType<? extends Villager> type, Level level) {
public Villager(final EntityType<? extends Villager> type, final Level level) {
this(type, level, VillagerType.PLAINS);
@@ -197,6 +199,57 @@ public class Villager extends AbstractVillager implements ReputationEventHandler
this.setVillagerData(this.getVillagerData().withType(villagerType).withProfession(level.registryAccess(), VillagerProfession.NONE));
@@ -199,6 +_,57 @@
this.setVillagerData(this.getVillagerData().withType(type).withProfession(level.registryAccess(), VillagerProfession.NONE));
}
+ // Purpur start - Allow leashing villagers
@@ -74,17 +66,12 @@ index 89844d7e804cc8a2110b694e448bc5993991bea7..e117ae1b114c7e2ca314a00335473efc
+
@Override
public Brain<Villager> getBrain() {
return (Brain<Villager>)super.getBrain();
@@ -293,11 +346,22 @@ public class Villager extends AbstractVillager implements ReputationEventHandler
// Paper start - EAR 2
this.customServerAiStep(level, false);
}
- protected void customServerAiStep(ServerLevel level, final boolean inactive) {
+ protected void customServerAiStep(ServerLevel level, boolean inactive) { // Purpur - Lobotomize stuck villagers - not final
// Paper end - EAR 2
ProfilerFiller profilerFiller = Profiler.get();
profilerFiller.push("villagerBrain");
- if (!inactive) this.getBrain().tick(level, this); // Paper - EAR 2
return (Brain<Villager>) super.getBrain();
@@ -248,7 +_,18 @@
protected void customServerAiStep(final ServerLevel level) {
ProfilerFiller profiler = Profiler.get();
profiler.push("villagerBrain");
- this.getBrain().tick(level, this);
+ // Purpur start - Lobotomize stuck villagers
+ if (this.level().purpurConfig.villagerLobotomizeEnabled) {
+ // treat as inactive if lobotomized
@@ -97,10 +84,10 @@ index 89844d7e804cc8a2110b694e448bc5993991bea7..e117ae1b114c7e2ca314a00335473efc
+ }
+ else if (this.isLobotomized && shouldRestock(level)) restock();
+ // Purpur end - Lobotomize stuck villagers
profilerFiller.pop();
profiler.pop();
if (this.assignProfessionWhenSpawned) {
this.assignProfessionWhenSpawned = false;
@@ -369,6 +433,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler
@@ -319,6 +_,7 @@
return InteractionResult.CONSUME;
}
@@ -108,16 +95,16 @@ index 89844d7e804cc8a2110b694e448bc5993991bea7..e117ae1b114c7e2ca314a00335473efc
this.startTrading(player);
}
@@ -500,7 +565,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler
@@ -460,7 +_,7 @@
public void updateDemand() {
for (MerchantOffer merchantOffer : this.getOffers()) {
- merchantOffer.updateDemand();
+ merchantOffer.updateDemand(this.level().purpurConfig.villagerMinimumDemand); // Purpur - Configurable minimum demand for trades
for (MerchantOffer offer : this.getOffers()) {
- offer.updateDemand();
+ offer.updateDemand(this.level().purpurConfig.villagerMinimumDemand); // Purpur - Configurable minimum demand for trades
}
}
@@ -692,7 +757,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler
@@ -660,7 +_,7 @@
@Override
public boolean canBreed() {
@@ -126,24 +113,11 @@ index 89844d7e804cc8a2110b694e448bc5993991bea7..e117ae1b114c7e2ca314a00335473efc
}
private boolean hungry() {
@@ -915,6 +980,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler
@@ -867,6 +_,7 @@
}
public void spawnGolemIfNeeded(ServerLevel level, long gameTime, int minVillagerAmount) {
public void spawnGolemIfNeeded(final ServerLevel level, final long timestamp, final int villagersNeededToAgree) {
+ if (level.purpurConfig.villagerSpawnIronGolemRadius > 0 && level.getEntitiesOfClass(net.minecraft.world.entity.animal.golem.IronGolem.class, getBoundingBox().inflate(level.purpurConfig.villagerSpawnIronGolemRadius)).size() > level.purpurConfig.villagerSpawnIronGolemLimit) return; // Purpur - Implement configurable search radius for villagers to spawn iron golems
if (this.wantsToSpawnGolem(gameTime)) {
AABB aabb = this.getBoundingBox().inflate(10.0, 10.0, 10.0);
List<Villager> entitiesOfClass = level.getEntitiesOfClass(Villager.class, aabb);
@@ -982,6 +1048,12 @@ public class Villager extends AbstractVillager implements ReputationEventHandler
@Override
public void startSleeping(BlockPos pos) {
+ // Purpur start - Option for beds to explode on villager sleep
+ if (level().purpurConfig.bedExplodeOnVillagerSleep && this.level().getBlockState(pos).getBlock() instanceof net.minecraft.world.level.block.BedBlock) {
+ this.level().explode(null, (double) pos.getX() + 0.5D, (double) pos.getY() + 0.5D, (double) pos.getZ() + 0.5D, (float) this.level().purpurConfig.bedExplosionPower, this.level().purpurConfig.bedExplosionFire, this.level().purpurConfig.bedExplosionEffect);
+ return;
+ }
+ // Purpur end - Option for beds to explode on villager sleep
super.startSleeping(pos);
this.brain.setMemory(MemoryModuleType.LAST_SLEPT, this.level().getGameTime());
this.brain.eraseMemory(MemoryModuleType.WALK_TARGET);
if (this.wantsToSpawnGolem(timestamp)) {
AABB villagerSearchBox = this.getBoundingBox().inflate(10.0, 10.0, 10.0);
List<Villager> nearbyVillagers = level.getEntitiesOfClass(Villager.class, villagerSearchBox);

View File

@@ -0,0 +1,21 @@
--- a/net/minecraft/world/entity/npc/wanderingtrader/WanderingTraderSpawner.java
+++ b/net/minecraft/world/entity/npc/wanderingtrader/WanderingTraderSpawner.java
@@ -133,7 +_,17 @@
int xPosition = referencePosition.getX() + this.random.nextInt(radius * 2) - radius;
int zPosition = referencePosition.getZ() + this.random.nextInt(radius * 2) - radius;
int yPosition = level.getHeight(SpawnPlacements.getHeightmapType(EntityType.WANDERING_TRADER), xPosition, zPosition);
- BlockPos spawnPos = new BlockPos(xPosition, yPosition, zPosition);
+ // Purpur start - Allow toggling special MobSpawners per world - allow traders to spawn below nether roof
+ BlockPos.MutableBlockPos spawnPos = new BlockPos.MutableBlockPos(xPosition, yPosition, zPosition);
+ if (level.dimensionType().hasCeiling()) {
+ do {
+ spawnPos.relative(net.minecraft.core.Direction.DOWN);
+ } while (!level.getBlockState(spawnPos).isAir());
+ do {
+ spawnPos.relative(net.minecraft.core.Direction.DOWN);
+ } while (level.getBlockState(spawnPos).isAir() && spawnPos.getY() > 0);
+ }
+ // Purpur end - Allow toggling special MobSpawners per world
if (wanderingTraderSpawnType.isSpawnPositionOk(level, spawnPos, EntityType.WANDERING_TRADER)) {
spawnPosition = spawnPos;
break;

View File

@@ -0,0 +1,17 @@
--- a/net/minecraft/world/inventory/AbstractFurnaceMenu.java
+++ b/net/minecraft/world/inventory/AbstractFurnaceMenu.java
@@ -122,7 +_,13 @@
} else if (slotIndex != 1 && slotIndex != 0) {
if (this.canSmelt(stack)) {
if (!this.moveItemStackTo(stack, 0, 1, false)) {
- return ItemStack.EMPTY;
+ // Purpur start - Added the ability to add combustible items
+ if (this.isFuel(item)) {
+ if (!this.moveItemStackTo(item, 1, 2, false)) {
+ return ItemStack.EMPTY;
+ }
+ }
+ // Purpur end - Added the ability to add combustible items
}
} else if (this.isFuel(stack)) {
if (!this.moveItemStackTo(stack, 1, 2, false)) {

View File

@@ -1,14 +1,6 @@
From 56a0a83ddb1b7472dbc9762e2aca396605c62085 Mon Sep 17 00:00:00 2001
From: File <noreply+automated@papermc.io>
Date: Sun, 20 Apr 1997 05:37:42 -0800
Subject: [PATCH] purpur File Patches
diff --git a/net/minecraft/world/inventory/AnvilMenu.java b/net/minecraft/world/inventory/AnvilMenu.java
index 7939f19b87364a32a40e58e001cea14e06348f86..b790b9476ec0a0569470d5de4067caa5373b2f6b 100644
--- a/net/minecraft/world/inventory/AnvilMenu.java
+++ b/net/minecraft/world/inventory/AnvilMenu.java
@@ -23,6 +23,12 @@ import net.minecraft.world.level.block.state.BlockState;
@@ -23,6 +_,12 @@
import org.jspecify.annotations.Nullable;
import org.slf4j.Logger;
@@ -21,7 +13,7 @@ index 7939f19b87364a32a40e58e001cea14e06348f86..b790b9476ec0a0569470d5de4067caa5
public class AnvilMenu extends ItemCombinerMenu {
public static final int INPUT_SLOT = 0;
public static final int ADDITIONAL_SLOT = 1;
@@ -51,6 +57,10 @@ public class AnvilMenu extends ItemCombinerMenu {
@@ -51,6 +_,10 @@
private org.bukkit.craftbukkit.inventory.view.CraftAnvilView bukkitEntity;
// CraftBukkit end
public boolean bypassEnchantmentLevelRestriction = false; // Paper - bypass anvil level restrictions
@@ -30,20 +22,20 @@ index 7939f19b87364a32a40e58e001cea14e06348f86..b790b9476ec0a0569470d5de4067caa5
+ public boolean canDoUnsafeEnchants = false;
+ // Purpur end - Anvil API
public AnvilMenu(int containerId, Inventory playerInventory) {
this(containerId, playerInventory, ContainerLevelAccess.NULL);
@@ -76,12 +86,17 @@ public class AnvilMenu extends ItemCombinerMenu {
public AnvilMenu(final int containerId, final Inventory inventory) {
this(containerId, inventory, ContainerLevelAccess.NULL);
@@ -76,12 +_,17 @@
@Override
protected boolean mayPickup(Player player, boolean hasStack) {
- return (player.hasInfiniteMaterials() || player.experienceLevel >= this.cost.get()) && this.cost.get() > AnvilMenu.DEFAULT_DENIED_COST && hasStack; // CraftBukkit - allow cost 0 like a free item
+ return (player.hasInfiniteMaterials() || player.experienceLevel >= this.cost.get()) && (this.bypassCost || this.cost.get() > AnvilMenu.DEFAULT_DENIED_COST) && hasStack; // CraftBukkit - allow cost 0 like a free item // Purpur - Anvil API
protected boolean mayPickup(final Player player, final boolean hasItem) {
- return (player.hasInfiniteMaterials() || player.experienceLevel >= this.cost.get()) && this.cost.get() > AnvilMenu.DEFAULT_DENIED_COST && hasItem; // CraftBukkit - allow cost 0 like a free item
+ return (player.hasInfiniteMaterials() || player.experienceLevel >= this.cost.get()) && (this.bypassCost || this.cost.get() > AnvilMenu.DEFAULT_DENIED_COST) && hasItem; // CraftBukkit - allow cost 0 like a free item // Purpur - Anvil API
}
@Override
protected void onTake(Player player, ItemStack stack) {
protected void onTake(final Player player, final ItemStack carried) {
+ // Purpur start - Anvil API
+ ItemStack itemstack = this.activeQuickItem != null ? this.activeQuickItem : stack;
+ ItemStack itemstack = this.activeQuickItem != null ? this.activeQuickItem : carried;
+ if (org.purpurmc.purpur.event.inventory.AnvilTakeResultEvent.getHandlerList().getRegisteredListeners().length > 0) new org.purpurmc.purpur.event.inventory.AnvilTakeResultEvent(player.getBukkitEntity(), getBukkitView(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack)).callEvent();
+ // Purpur end - Anvil API
if (!player.hasInfiniteMaterials()) {
@@ -51,7 +43,7 @@ index 7939f19b87364a32a40e58e001cea14e06348f86..b790b9476ec0a0569470d5de4067caa5
player.giveExperienceLevels(-this.cost.get());
}
@@ -134,13 +149,19 @@ public class AnvilMenu extends ItemCombinerMenu {
@@ -134,13 +_,19 @@
@Override
public void createResult() {
@@ -61,60 +53,60 @@ index 7939f19b87364a32a40e58e001cea14e06348f86..b790b9476ec0a0569470d5de4067caa5
+ if (org.purpurmc.purpur.event.inventory.AnvilUpdateResultEvent.getHandlerList().getRegisteredListeners().length > 0) new org.purpurmc.purpur.event.inventory.AnvilUpdateResultEvent(getBukkitView()).callEvent();
+ // Purpur end - Anvil API
+
ItemStack item = this.inputSlots.getItem(0);
ItemStack input = this.inputSlots.getItem(0);
this.onlyRenaming = false;
this.cost.set(1);
int i = 0;
long l = 0L;
int i1 = 0;
- if (!item.isEmpty() && EnchantmentHelper.canStoreEnchantments(item)) {
+ if (!item.isEmpty() && this.canDoUnsafeEnchants || EnchantmentHelper.canStoreEnchantments(item)) { // Purpur - Anvil API
ItemStack itemStack = item.copy();
ItemStack item1 = this.inputSlots.getItem(1);
ItemEnchantments.Mutable mutable = new ItemEnchantments.Mutable(EnchantmentHelper.getEnchantmentsForCrafting(itemStack));
@@ -198,23 +219,34 @@ public class AnvilMenu extends ItemCombinerMenu {
int intValue = entry.getIntValue();
intValue = level == intValue ? intValue + 1 : Math.max(intValue, level);
Enchantment enchantment = holder.value();
- boolean canEnchant = enchantment.canEnchant(item);
int price = 0;
long tax = 0L;
int namingCost = 0;
- if (!input.isEmpty() && EnchantmentHelper.canStoreEnchantments(input)) {
+ if (!input.isEmpty() && this.canDoUnsafeEnchants || EnchantmentHelper.canStoreEnchantments(input)) { // Purpur - Anvil API
ItemStack result = input.copy();
ItemStack addition = this.inputSlots.getItem(1);
ItemEnchantments.Mutable enchantments = new ItemEnchantments.Mutable(EnchantmentHelper.getEnchantmentsForCrafting(result));
@@ -198,23 +_,34 @@
int level = entry.getIntValue();
level = current == level ? level + 1 : Math.max(level, current);
Enchantment enchantment = enchantmentHolder.value();
- boolean compatible = enchantment.canEnchant(input);
+ // Purpur start - Config to allow unsafe enchants
+ boolean canEnchant = this.canDoUnsafeEnchants || org.purpurmc.purpur.PurpurConfig.allowInapplicableEnchants || enchantment.canEnchant(item); // whether the enchantment can be applied on specific item type
+ boolean compatible = this.canDoUnsafeEnchants || org.purpurmc.purpur.PurpurConfig.allowInapplicableEnchants || enchantment.canEnchant(input); // whether the enchantment can be applied on specific item type
+ boolean canEnchant1 = true; // whether two incompatible enchantments can be applied on a single item
+ // Purpur end - Config to allow unsafe enchants
if (this.player.hasInfiniteMaterials() || item.is(Items.ENCHANTED_BOOK)) {
canEnchant = true;
if (this.player.hasInfiniteMaterials() || input.is(Items.ENCHANTED_BOOK)) {
compatible = true;
}
+ java.util.Set<Holder<Enchantment>> removedEnchantments = new java.util.HashSet<>(); // Purpur - Config to allow unsafe enchants
for (Holder<Enchantment> holder1 : mutable.keySet()) {
if (!holder1.equals(holder) && !Enchantment.areCompatible(holder, holder1)) {
- canEnchant = false;
for (Holder<Enchantment> other : enchantments.keySet()) {
if (!other.equals(enchantmentHolder) && !Enchantment.areCompatible(enchantmentHolder, other)) {
- compatible = false;
+ canEnchant1 = this.canDoUnsafeEnchants || org.purpurmc.purpur.PurpurConfig.allowIncompatibleEnchants; // Purpur - Anvil API // Purpur - canEnchant -> canEnchant1 - Config to allow unsafe enchants
+ // Purpur start - Config to allow unsafe enchants
+ if (!canEnchant1 && org.purpurmc.purpur.PurpurConfig.replaceIncompatibleEnchants) {
+ removedEnchantments.add(holder1);
+ removedEnchantments.add(other);
+ canEnchant1 = true;
+ }
+ // Purpur end - Config to allow unsafe enchants
i++;
price++;
}
}
+ mutable.removeIf(removedEnchantments::contains); // Purpur - Config to allow unsafe enchants
- if (!canEnchant) {
+ if (!canEnchant || !canEnchant1) { // Purpur - Config to allow unsafe enchants
flag1 = true;
- if (!compatible) {
+ if (!compatible || !canEnchant1) { // Purpur - Config to allow unsafe enchants
isAnyEnchantmentNotCompatible = true;
} else {
flag = true;
- if (intValue > enchantment.getMaxLevel() && !this.bypassEnchantmentLevelRestriction) { // Paper - bypass anvil level restrictions
+ if (!org.purpurmc.purpur.PurpurConfig.allowHigherEnchantsLevels && intValue > enchantment.getMaxLevel() && !this.bypassEnchantmentLevelRestriction) { // Paper - bypass anvil level restrictions // Purpur - Config to allow unsafe enchants
intValue = enchantment.getMaxLevel();
isAnyEnchantmentCompatible = true;
- if (level > enchantment.getMaxLevel() && !this.bypassEnchantmentLevelRestriction) { // Paper - bypass anvil level restrictions
+ if (!org.purpurmc.purpur.PurpurConfig.allowHigherEnchantsLevels && level > enchantment.getMaxLevel() && !this.bypassEnchantmentLevelRestriction) { // Paper - bypass anvil level restrictions // Purpur - Config to allow unsafe enchants
level = enchantment.getMaxLevel();
}
@@ -243,6 +275,54 @@ public class AnvilMenu extends ItemCombinerMenu {
if (!this.itemName.equals(item.getHoverName().getString())) {
i1 = 1;
i += i1;
@@ -243,6 +_,54 @@
if (!this.itemName.equals(input.getHoverName().getString())) {
namingCost = 1;
price += namingCost;
+ // Purpur start - Allow anvil colors
+ if (this.player != null) {
+ org.bukkit.craftbukkit.entity.CraftHumanEntity player = this.player.getBukkitEntity();
@@ -159,14 +151,14 @@ index 7939f19b87364a32a40e58e001cea14e06348f86..b790b9476ec0a0569470d5de4067caa5
+ if (removeItalics) {
+ component = component.decoration(net.kyori.adventure.text.format.TextDecoration.ITALIC, false);
+ }
+ itemStack.set(DataComponents.CUSTOM_NAME, io.papermc.paper.adventure.PaperAdventure.asVanilla(component));
+ result.set(DataComponents.CUSTOM_NAME, io.papermc.paper.adventure.PaperAdventure.asVanilla(component));
+ }
+ else
+ // Purpur end - Allow anvil colors
itemStack.set(DataComponents.CUSTOM_NAME, Component.literal(this.itemName));
result.set(DataComponents.CUSTOM_NAME, Component.literal(this.itemName));
}
} else if (item.has(DataComponents.CUSTOM_NAME)) {
@@ -267,6 +347,12 @@ public class AnvilMenu extends ItemCombinerMenu {
} else if (input.has(DataComponents.CUSTOM_NAME)) {
@@ -267,6 +_,12 @@
this.onlyRenaming = true;
}
@@ -177,11 +169,11 @@ index 7939f19b87364a32a40e58e001cea14e06348f86..b790b9476ec0a0569470d5de4067caa5
+ // Purpur end - Anvil API
+
if (this.cost.get() >= this.maximumRepairCost && !this.player.hasInfiniteMaterials()) { // CraftBukkit
itemStack = ItemStack.EMPTY;
result = ItemStack.EMPTY;
}
@@ -287,6 +373,13 @@ public class AnvilMenu extends ItemCombinerMenu {
@@ -287,6 +_,13 @@
org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareAnvilEvent(this.getBukkitView(), itemStack); // CraftBukkit
org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareAnvilEvent(this.getBukkitView(), result); // CraftBukkit
this.broadcastChanges();
+
+ // Purpur start - Anvil API
@@ -193,12 +185,12 @@ index 7939f19b87364a32a40e58e001cea14e06348f86..b790b9476ec0a0569470d5de4067caa5
} else {
org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareAnvilEvent(this.getBukkitView(), ItemStack.EMPTY); // CraftBukkit
this.cost.set(AnvilMenu.DEFAULT_DENIED_COST); // CraftBukkit - use a variable for set a cost for denied item
@@ -295,7 +388,7 @@ public class AnvilMenu extends ItemCombinerMenu {
@@ -295,7 +_,7 @@
}
public static int calculateIncreasedRepairCost(int oldRepairCost) {
- return (int)Math.min(oldRepairCost * 2L + 1L, 2147483647L);
+ return org.purpurmc.purpur.PurpurConfig.anvilCumulativeCost ? (int)Math.min(oldRepairCost * 2L + 1L, 2147483647L) : 0; // Purpur - Make anvil cumulative cost configurable
public static int calculateIncreasedRepairCost(final int baseCost) {
- return (int)Math.min(baseCost * 2L + 1L, 2147483647L);
+ return org.purpurmc.purpur.PurpurConfig.anvilCumulativeCost ? (int)Math.min(baseCost * 2L + 1L, 2147483647L) : 0; // Purpur - Make anvil cumulative cost configurable
}
public boolean setItemName(String itemName) {
public boolean setItemName(final String name) {

View File

@@ -0,0 +1,11 @@
--- a/net/minecraft/world/inventory/ArmorSlot.java
+++ b/net/minecraft/world/inventory/ArmorSlot.java
@@ -54,7 +_,7 @@
@Override
public boolean mayPickup(final Player player) {
ItemStack itemStack = this.getItem();
- return (itemStack.isEmpty() || player.isCreative() || !EnchantmentHelper.has(itemStack, EnchantmentEffectComponents.PREVENT_ARMOR_CHANGE))
+ return (itemStack.isEmpty() || player.isCreative() || (!EnchantmentHelper.has(itemStack, EnchantmentEffectComponents.PREVENT_ARMOR_CHANGE) || player.level().purpurConfig.playerRemoveBindingWithWeakness && player.hasEffect(net.minecraft.world.effect.MobEffects.WEAKNESS))) // Purpur - Config to remove curse of binding with weakness
&& super.mayPickup(player);
}

View File

@@ -1,14 +1,6 @@
From 56a0a83ddb1b7472dbc9762e2aca396605c62085 Mon Sep 17 00:00:00 2001
From: File <noreply+automated@papermc.io>
Date: Sun, 20 Apr 1997 05:37:42 -0800
Subject: [PATCH] purpur File Patches
diff --git a/net/minecraft/world/inventory/EnchantmentMenu.java b/net/minecraft/world/inventory/EnchantmentMenu.java
index 385eecd0c59d3c9510e39f96aa9614a7a57fb65a..40860d2facd6720300793dcc2cf99cb3367e61f7 100644
--- a/net/minecraft/world/inventory/EnchantmentMenu.java
+++ b/net/minecraft/world/inventory/EnchantmentMenu.java
@@ -63,6 +63,22 @@ public class EnchantmentMenu extends AbstractContainerMenu {
@@ -64,6 +_,22 @@
return access.getLocation();
}
// CraftBukkit end
@@ -31,7 +23,7 @@ index 385eecd0c59d3c9510e39f96aa9614a7a57fb65a..40860d2facd6720300793dcc2cf99cb3
};
// Paper end - Add missing InventoryHolders
this.access = access;
@@ -83,6 +99,16 @@ public class EnchantmentMenu extends AbstractContainerMenu {
@@ -92,6 +_,16 @@
return EnchantmentMenu.EMPTY_SLOT_LAPIS_LAZULI;
}
});
@@ -45,12 +37,12 @@ index 385eecd0c59d3c9510e39f96aa9614a7a57fb65a..40860d2facd6720300793dcc2cf99cb3
+ }
+ });
+ // Purpur end - Enchantment Table Persists Lapis
this.addStandardInventorySlots(playerInventory, 8, 84);
this.addStandardInventorySlots(inventory, 8, 84);
this.addDataSlot(DataSlot.shared(this.costs, 0));
this.addDataSlot(DataSlot.shared(this.costs, 1));
@@ -299,7 +325,7 @@ public class EnchantmentMenu extends AbstractContainerMenu {
@@ -308,7 +_,7 @@
@Override
public void removed(Player player) {
public void removed(final Player player) {
super.removed(player);
- this.access.execute((level, pos) -> this.clearContainer(player, this.enchantSlots));
+ this.access.execute((level, pos) -> {if (level.purpurConfig.enchantmentTableLapisPersists) this.getSlot(1).set(ItemStack.EMPTY);this.clearContainer(player, this.enchantSlots);}); // Purpur - Enchantment Table Persists Lapis

View File

@@ -1,44 +1,36 @@
From 56a0a83ddb1b7472dbc9762e2aca396605c62085 Mon Sep 17 00:00:00 2001
From: File <noreply+automated@papermc.io>
Date: Sun, 20 Apr 1997 05:37:42 -0800
Subject: [PATCH] purpur File Patches
diff --git a/net/minecraft/world/inventory/GrindstoneMenu.java b/net/minecraft/world/inventory/GrindstoneMenu.java
index ad70a0f7debee27d9f3b2ff39cb0429b39485190..e991ca16d069fddc3e4eb6d8c78c0dbffeb75a54 100644
--- a/net/minecraft/world/inventory/GrindstoneMenu.java
+++ b/net/minecraft/world/inventory/GrindstoneMenu.java
@@ -92,11 +92,13 @@ public class GrindstoneMenu extends AbstractContainerMenu {
@@ -105,11 +_,13 @@
@Override
public void onTake(Player player, ItemStack stack) {
access.execute((level, blockPos) -> {
public void onTake(final Player player, final ItemStack carried) {
access.execute((level, pos) -> {
+ ItemStack itemstack = activeQuickItem == null ? stack : activeQuickItem; // Purpur - Grindstone API
if (level instanceof ServerLevel) {
// Paper start - Fire BlockExpEvent on grindstone use
org.bukkit.event.block.BlockExpEvent event = new org.bukkit.event.block.BlockExpEvent(org.bukkit.craftbukkit.block.CraftBlock.at(level, blockPos), this.getExperienceAmount(level));
org.bukkit.event.block.BlockExpEvent event = new org.bukkit.event.block.BlockExpEvent(org.bukkit.craftbukkit.block.CraftBlock.at(level, pos), this.getExperienceAmount(level));
event.callEvent();
- ExperienceOrb.awardWithDirection((ServerLevel) level, Vec3.atCenterOf(blockPos), Vec3.ZERO, event.getExpToDrop(), org.bukkit.entity.ExperienceOrb.SpawnReason.GRINDSTONE, player, null);
- ExperienceOrb.awardWithDirection((ServerLevel) level, Vec3.atCenterOf(pos), Vec3.ZERO, event.getExpToDrop(), org.bukkit.entity.ExperienceOrb.SpawnReason.GRINDSTONE, player, null);
+ org.purpurmc.purpur.event.inventory.GrindstoneTakeResultEvent grindstoneTakeResultEvent = new org.purpurmc.purpur.event.inventory.GrindstoneTakeResultEvent(player.getBukkitEntity(), getBukkitView(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack), event.getExpToDrop()); grindstoneTakeResultEvent.callEvent(); // Purpur - Grindstone API
+ ExperienceOrb.awardWithDirection((ServerLevel) level, Vec3.atCenterOf(blockPos), Vec3.ZERO, grindstoneTakeResultEvent.getExperienceAmount(), org.bukkit.entity.ExperienceOrb.SpawnReason.GRINDSTONE, player, null); // Purpur - Grindstone API
+ ExperienceOrb.awardWithDirection((ServerLevel) level, Vec3.atCenterOf(pos), Vec3.ZERO, grindstoneTakeResultEvent.getExperienceAmount(), org.bukkit.entity.ExperienceOrb.SpawnReason.GRINDSTONE, player, null); // Purpur - Grindstone API
// Paper end - Fire BlockExpEvent on grindstone use
}
@@ -125,7 +127,7 @@ public class GrindstoneMenu extends AbstractContainerMenu {
for (Entry<Holder<Enchantment>> entry : enchantmentsForCrafting.entrySet()) {
Holder<Enchantment> holder = entry.getKey();
int intValue = entry.getIntValue();
- if (!holder.is(EnchantmentTags.CURSE)) {
@@ -138,7 +_,7 @@
for (Entry<Holder<Enchantment>> entry : enchantments.entrySet()) {
Holder<Enchantment> enchant = entry.getKey();
int lvl = entry.getIntValue();
- if (!enchant.is(EnchantmentTags.CURSE)) {
+ if (!org.purpurmc.purpur.PurpurConfig.grindstoneIgnoredEnchants.contains(holder.value())) { // Purpur - Config for grindstones
i += holder.value().getMinCost(intValue);
amount += enchant.value().getMinCost(lvl);
}
}
@@ -203,15 +205,75 @@ public class GrindstoneMenu extends AbstractContainerMenu {
@@ -216,16 +_,76 @@
for (Entry<Holder<Enchantment>> entry : enchantmentsForCrafting.entrySet()) {
Holder<Enchantment> holder = entry.getKey();
- if (!holder.is(EnchantmentTags.CURSE) || mutable.getLevel(holder) == 0) {
+ if (!org.purpurmc.purpur.PurpurConfig.grindstoneIgnoredEnchants.contains(holder.value()) || mutable.getLevel(holder) == 0) { // Purpur - Config for grindstones
mutable.upgrade(holder, entry.getIntValue());
for (Entry<Holder<Enchantment>> entry : enchantments.entrySet()) {
Holder<Enchantment> enchant = entry.getKey();
- if (!enchant.is(EnchantmentTags.CURSE) || newEnchantments.getLevel(enchant) == 0) {
+ if (!org.purpurmc.purpur.PurpurConfig.grindstoneIgnoredEnchants.contains(enchant.value()) || newEnchantments.getLevel(enchant) == 0) { // Purpur - Config for grindstones
newEnchantments.upgrade(enchant, entry.getIntValue());
}
}
});
@@ -105,15 +97,16 @@ index ad70a0f7debee27d9f3b2ff39cb0429b39485190..e991ca16d069fddc3e4eb6d8c78c0dbf
+ );
+ // Purpur end - Config for grindstones
private ItemStack removeNonCursesFrom(ItemStack item) {
- ItemEnchantments itemEnchantments = EnchantmentHelper.updateEnchantments(item, mutable -> mutable.removeIf(holder -> !holder.is(EnchantmentTags.CURSE)));
+ ItemEnchantments itemEnchantments = EnchantmentHelper.updateEnchantments(item, mutable -> mutable.removeIf(holder -> !org.purpurmc.purpur.PurpurConfig.grindstoneIgnoredEnchants.contains(holder.value()))); // Purpur - Config for grindstones
if (item.is(Items.ENCHANTED_BOOK) && itemEnchantments.isEmpty()) {
ItemEnchantments newEnchantments = EnchantmentHelper.updateEnchantments(
- item, enchantments -> enchantments.removeIf(enchantment -> !enchantment.is(EnchantmentTags.CURSE))
+ item, enchantments -> enchantments.removeIf(enchantment -> !org.purpurmc.purpur.PurpurConfig.grindstoneIgnoredEnchants.contains(enchantment.value())) // Purpur - Config for grindstones
);
if (item.is(Items.ENCHANTED_BOOK) && newEnchantments.isEmpty()) {
item = item.transmuteCopy(Items.BOOK);
}
@@ -223,6 +285,23 @@ public class GrindstoneMenu extends AbstractContainerMenu {
@@ -238,6 +_,22 @@
}
item.set(DataComponents.REPAIR_COST, i);
item.set(DataComponents.REPAIR_COST, repairCost);
+
+ // Purpur start - Config for grindstones
+ net.minecraft.core.component.DataComponentPatch.Builder builder = net.minecraft.core.component.DataComponentPatch.builder();
@@ -130,11 +123,10 @@ index ad70a0f7debee27d9f3b2ff39cb0429b39485190..e991ca16d069fddc3e4eb6d8c78c0dbf
+ }
+ item.applyComponents(builder.build());
+ // Purpur end - Config for grindstones
+
return item;
}
@@ -279,7 +358,9 @@ public class GrindstoneMenu extends AbstractContainerMenu {
@@ -294,7 +_,9 @@
return ItemStack.EMPTY;
}
@@ -143,4 +135,4 @@ index ad70a0f7debee27d9f3b2ff39cb0429b39485190..e991ca16d069fddc3e4eb6d8c78c0dbf
+ this.activeQuickItem = null; // Purpur - Grindstone API
}
return itemStack;
return clicked;

View File

@@ -0,0 +1,12 @@
--- a/net/minecraft/world/inventory/ItemCombinerMenu.java
+++ b/net/minecraft/world/inventory/ItemCombinerMenu.java
@@ -177,7 +_,9 @@
return ItemStack.EMPTY;
}
+ this.activeQuickItem = clicked; // Purpur - Anvil API
slot.onTake(player, stack);
+ this.activeQuickItem = null; // Purpur - Anvil API
}
return clicked;

View File

@@ -1,23 +1,15 @@
From 56a0a83ddb1b7472dbc9762e2aca396605c62085 Mon Sep 17 00:00:00 2001
From: File <noreply+automated@papermc.io>
Date: Sun, 20 Apr 1997 05:37:42 -0800
Subject: [PATCH] purpur File Patches
diff --git a/net/minecraft/world/level/block/FarmBlock.java b/net/minecraft/world/level/block/FarmBlock.java
index da822a89e134e98696308315799d872944e7712f..75b38812b538e0938bbbde62427fa9fd23d372a1 100644
--- a/net/minecraft/world/level/block/FarmBlock.java
+++ b/net/minecraft/world/level/block/FarmBlock.java
@@ -112,7 +112,7 @@ public class FarmBlock extends Block {
public void fallOn(Level level, BlockState state, BlockPos pos, Entity entity, double fallDistance) {
--- a/net/minecraft/world/level/block/FarmlandBlock.java
+++ b/net/minecraft/world/level/block/FarmlandBlock.java
@@ -111,7 +_,7 @@
public void fallOn(final Level level, final BlockState state, final BlockPos pos, final Entity entity, final double fallDistance) {
super.fallOn(level, state, pos, entity, fallDistance); // CraftBukkit - moved here as game rules / events shouldn't affect fall damage.
if (level instanceof ServerLevel serverLevel
- && level.random.nextFloat() < fallDistance - 0.5
+ && (serverLevel.purpurConfig.farmlandTrampleHeight >= 0D ? fallDistance >= serverLevel.purpurConfig.farmlandTrampleHeight : level.random.nextFloat() < fallDistance - 0.5) // Purpur - Configurable farmland trample height
- && level.getRandom().nextFloat() < fallDistance - 0.5
+ && (serverLevel.purpurConfig.farmlandTrampleHeight >= 0D ? fallDistance >= serverLevel.purpurConfig.farmlandTrampleHeight : level.getRandom().nextFloat() < fallDistance - 0.5) // Purpur - Configurable farmland trample height
&& entity instanceof LivingEntity
&& (entity instanceof Player || serverLevel.getGameRules().get(GameRules.MOB_GRIEFING))
&& entity.getBbWidth() * entity.getBbWidth() * entity.getBbHeight() > 0.512F) {
@@ -129,6 +129,28 @@ public class FarmBlock extends Block {
@@ -128,6 +_,28 @@
return;
}
@@ -46,7 +38,7 @@ index da822a89e134e98696308315799d872944e7712f..75b38812b538e0938bbbde62427fa9fd
if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(entity, pos, Blocks.DIRT.defaultBlockState())) {
return;
}
@@ -177,7 +199,7 @@ public class FarmBlock extends Block {
@@ -176,7 +_,7 @@
}
}

View File

@@ -0,0 +1,33 @@
--- a/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java
+++ b/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java
@@ -195,6 +_,21 @@
}
ItemStack fuel = entity.items.get(1);
+ // Purpur start - Furnace uses lava from underneath
+ boolean usedLavaFromUnderneath = false;
+ if (level.purpurConfig.furnaceUseLavaFromUnderneath && !entity.isLit() && fuel.isEmpty() && !entity.items.get(0).isEmpty() && level.getGameTime() % 20 == 0) {
+ BlockPos below = entity.getBlockPos().below();
+ BlockState belowState = level.getBlockStateIfLoaded(below);
+ if (belowState != null && belowState.is(net.minecraft.world.level.block.Blocks.LAVA)) {
+ net.minecraft.world.level.material.FluidState fluidState = belowState.getFluidState();
+ if (fluidState != null && fluidState.isSource()) {
+ level.setBlock(below, net.minecraft.world.level.block.Blocks.AIR.defaultBlockState(), 3);
+ fuel = Items.LAVA_BUCKET.getDefaultInstance();
+ usedLavaFromUnderneath = true;
+ }
+ }
+ }
+ // Purpur end - Furnace uses lava from underneath
ItemStack ingredient = entity.items.get(0);
boolean hasIngredient = !ingredient.isEmpty();
boolean hasFuel = !fuel.isEmpty();
@@ -273,6 +_,8 @@
if (changed) {
setChanged(level, pos, state);
}
+
+ if (usedLavaFromUnderneath) furnace.items.set(1, ItemStack.EMPTY); // Purpur - Furnace uses lava from underneath
}
private static void consumeFuel(final NonNullList<ItemStack> items, final ItemStack fuel) {

View File

@@ -0,0 +1,58 @@
--- a/net/minecraft/world/level/block/entity/BeaconBlockEntity.java
+++ b/net/minecraft/world/level/block/entity/BeaconBlockEntity.java
@@ -142,6 +_,16 @@
public double getEffectRange() {
if (this.effectRange < 0) {
+ // Purpur start - Beacon Activation Range Configurable
+ if (this.level != null) {
+ switch (this.levels) {
+ case 1: return this.level.purpurConfig.beaconLevelOne;
+ case 2: return this.level.purpurConfig.beaconLevelTwo;
+ case 3: return this.level.purpurConfig.beaconLevelThree;
+ case 4: return this.level.purpurConfig.beaconLevelFour;
+ }
+ }
+ // Purpur end - Beacon Activation Range Configurable
return this.levels * 10 + 10;
} else {
return effectRange;
@@ -170,6 +_,7 @@
int y = pos.getY();
int z = pos.getZ();
BlockPos checkPos;
+ boolean isTintedGlass = false; // Purpur - allow beacon effects when covered by tinted glass
if (entity.lastCheckY < y) {
checkPos = pos;
entity.checkingBeamSections = Lists.newArrayList();
@@ -199,11 +_,15 @@
}
}
} else {
- if (lastBeamSection == null || state.getLightDampening() >= 15 && !state.is(Blocks.BEDROCK)) {
+ if (level.purpurConfig.beaconAllowEffectsWithTintedGlass && blockState.getBlock().equals(Blocks.TINTED_GLASS)) {isTintedGlass = true;} // Purpur - allow beacon effects when covered by tinted glass
+ // Purpur start - fix effects being applied when tinted glass is covered
+ if (lastBeamSection == null || state.getLightDampening() >= 15 && !state.is(Blocks.BEDROCK) && !(blockState.getBlock().equals(Blocks.TINTED_GLASS) && level.purpurConfig.beaconAllowEffectsWithTintedGlass)) {
entity.checkingBeamSections.clear();
entity.lastCheckY = lastSetBlock;
+ isTintedGlass = false;
break;
}
+ // Purpur end - fix effects being applied when tinted glass is covered
lastBeamSection.increaseHeight();
}
@@ -214,11 +_,11 @@
int previousLevels = entity.levels;
if (level.getGameTime() % 80L == 0L) {
- if (!entity.beamSections.isEmpty()) {
+ if (!entity.beamSections.isEmpty() || (level.purpurConfig.beaconAllowEffectsWithTintedGlass && isTintedGlass)) { // Purpur - fix beacon effects persisting with broken base while tinted glass is used
entity.levels = updateBase(level, x, y, z);
}
- if (entity.levels > 0 && !entity.beamSections.isEmpty()) {
+ if (entity.levels > 0 && (!entity.beamSections.isEmpty() || (level.purpurConfig.beaconAllowEffectsWithTintedGlass && isTintedGlass))) { // Purpur - allow beacon effects when covered by tinted glass
applyEffects(level, pos, entity.levels, entity.primaryPower, entity.secondaryPower, entity); // Paper - Custom beacon ranges
playSound(level, pos, SoundEvents.BEACON_AMBIENT);
}

View File

@@ -1,14 +1,6 @@
From 56a0a83ddb1b7472dbc9762e2aca396605c62085 Mon Sep 17 00:00:00 2001
From: File <noreply+automated@papermc.io>
Date: Sun, 20 Apr 1997 05:37:42 -0800
Subject: [PATCH] purpur File Patches
diff --git a/net/minecraft/world/level/block/entity/BeehiveBlockEntity.java b/net/minecraft/world/level/block/entity/BeehiveBlockEntity.java
index c989b7d52e16d93e65afb0f921d514c68b814921..9261bc38258ee80aa6ec2f4bcb27a48c01f84b8f 100644
--- a/net/minecraft/world/level/block/entity/BeehiveBlockEntity.java
+++ b/net/minecraft/world/level/block/entity/BeehiveBlockEntity.java
@@ -79,7 +79,7 @@ public class BeehiveBlockEntity extends BlockEntity {
@@ -80,7 +_,7 @@
"leash",
"UUID"
);
@@ -17,8 +9,8 @@ index c989b7d52e16d93e65afb0f921d514c68b814921..9261bc38258ee80aa6ec2f4bcb27a48c
private static final int MIN_TICKS_BEFORE_REENTERING_HIVE = 400;
private static final int MIN_OCCUPATION_TICKS_NECTAR = 2400;
public static final int MIN_OCCUPATION_TICKS_NECTARLESS = 600;
@@ -153,11 +153,33 @@ public class BeehiveBlockEntity extends BlockEntity {
return list;
@@ -156,11 +_,33 @@
return spawned;
}
+ // Purpur start - Stored Bee API
@@ -51,11 +43,11 @@ index c989b7d52e16d93e65afb0f921d514c68b814921..9261bc38258ee80aa6ec2f4bcb27a48c
// Paper start - Add EntityBlockStorage clearEntities
public void clearBees() {
this.stored.clear();
@@ -398,8 +420,8 @@ public class BeehiveBlockEntity extends BlockEntity {
registrar.register(DebugSubscriptions.BEE_HIVES, () -> DebugHiveInfo.pack(this));
@@ -399,8 +_,8 @@
registration.register(DebugSubscriptions.BEE_HIVES, () -> DebugHiveInfo.pack(this));
}
- static class BeeData {
- private static class BeeData {
- private final BeehiveBlockEntity.Occupant occupant;
+ public static class BeeData { // Purpur - make public - Stored Bee API
+ public final BeehiveBlockEntity.Occupant occupant; // Purpur - make public - Stored Bee API

View File

@@ -1,14 +1,6 @@
From 56a0a83ddb1b7472dbc9762e2aca396605c62085 Mon Sep 17 00:00:00 2001
From: File <noreply+automated@papermc.io>
Date: Sun, 20 Apr 1997 05:37:42 -0800
Subject: [PATCH] purpur File Patches
diff --git a/net/minecraft/world/level/block/entity/BlockEntity.java b/net/minecraft/world/level/block/entity/BlockEntity.java
index fb22ebe9758014ebf2aebcda21155f1c4c83fafe..7cbb92c23f0b3d49b8ea6cd66ed4f377dd22ee98 100644
--- a/net/minecraft/world/level/block/entity/BlockEntity.java
+++ b/net/minecraft/world/level/block/entity/BlockEntity.java
@@ -105,6 +105,10 @@ public abstract class BlockEntity implements DebugValueSource {
@@ -107,6 +_,10 @@
input.read("PublicBukkitValues", CompoundTag.CODEC)
.ifPresent(this.persistentDataContainer::putAll);
// Paper end - read persistent data container
@@ -18,11 +10,11 @@ index fb22ebe9758014ebf2aebcda21155f1c4c83fafe..7cbb92c23f0b3d49b8ea6cd66ed4f377
+
}
public final void loadWithComponents(ValueInput input) {
@@ -117,6 +121,11 @@ public abstract class BlockEntity implements DebugValueSource {
public final void loadWithComponents(final ValueInput input) {
@@ -119,6 +_,11 @@
}
protected void saveAdditional(ValueOutput output) {
protected void saveAdditional(final ValueOutput output) {
+ // Purpur start - Persistent BlockEntity Lore and DisplayName
+ if (this.persistentLore != null) {
+ output.store("Purpur.persistentLore", net.minecraft.world.item.component.ItemLore.CODEC, this.persistentLore);
@@ -30,8 +22,8 @@ index fb22ebe9758014ebf2aebcda21155f1c4c83fafe..7cbb92c23f0b3d49b8ea6cd66ed4f377
+ // Purpur end - Persistent BlockEntity Lore and DisplayName
}
public final CompoundTag saveWithFullMetadata(HolderLookup.Provider registries) {
@@ -402,4 +411,16 @@ public abstract class BlockEntity implements DebugValueSource {
public final CompoundTag saveWithFullMetadata(final HolderLookup.Provider registries) {
@@ -412,4 +_,16 @@
return this.blockEntity.getNameForReporting() + "@" + this.blockEntity.getBlockPos();
}
}

View File

@@ -0,0 +1,66 @@
--- a/net/minecraft/world/level/block/entity/ConduitBlockEntity.java
+++ b/net/minecraft/world/level/block/entity/ConduitBlockEntity.java
@@ -150,7 +_,7 @@
BlockPos testPos = worldPosition.offset(ox, oy, ozx);
BlockState testBlock = level.getBlockState(testPos);
- for (Block type : VALID_BLOCKS) {
+ for (Block type : level.purpurConfig.conduitBlocks) { // Purpur - Conduit behavior configuration
if (testBlock.is(type)) {
effectBlocks.add(testPos);
}
@@ -165,13 +_,13 @@
private static void applyEffects(final Level level, final BlockPos worldPosition, final List<BlockPos> effectBlocks) {
// CraftBukkit start
- ConduitBlockEntity.applyEffects(level, worldPosition, ConduitBlockEntity.getRange(effectBlocks));
+ ConduitBlockEntity.applyEffects(level, worldPosition, ConduitBlockEntity.getRange(effectBlocks, level)); // Purpur - Conduit behavior configuration
}
- public static int getRange(List<BlockPos> effectBlocks) {
+ public static int getRange(List<BlockPos> effectBlocks, Level level) { // Purpur - Conduit behavior configuration
// CraftBukkit end
int activeSize = effectBlocks.size();
- int effectRange = activeSize / 7 * 16;
+ int effectRange = activeSize / 7 * level.purpurConfig.conduitDistance; // Purpur - Conduit behavior configuration
// CraftBukkit start
return effectRange;
}
@@ -204,7 +_,7 @@
EntityReference<LivingEntity> newDestroyTarget = updateDestroyTarget(entity.destroyTarget, level, worldPosition, isActive);
LivingEntity targetEntity = EntityReference.getLivingEntity(newDestroyTarget, level);
if (damageTarget && targetEntity != null) { // CraftBukkit
- if (targetEntity.hurtServer(level, level.damageSources().magic().eventBlockDamager(level, worldPosition), 4.0F)) // CraftBukkit - move up
+ if (targetEntity.hurtServer(level, level.damageSources().magic().eventBlockDamager(level, worldPosition), level.purpurConfig.conduitDamageAmount)) // CraftBukkit - move up // Purpur - Conduit behavior configuration
level.playSound(
null, targetEntity.getX(), targetEntity.getY(), targetEntity.getZ(), SoundEvents.CONDUIT_ATTACK_TARGET, SoundSource.BLOCKS, 1.0F, 1.0F
);
@@ -225,19 +_,25 @@
return selectNewTarget(level, pos);
} else {
LivingEntity targetEntity = EntityReference.getLivingEntity(target, level);
- return targetEntity != null && targetEntity.isAlive() && pos.closerThan(targetEntity.blockPosition(), 8.0) ? target : null;
+ return targetEntity != null && targetEntity.isAlive() && pos.closerThan(targetEntity.blockPosition(), level.purpurConfig.conduitDamageDistance) ? target : null; // Purpur - Conduit behavior configuration
}
}
private static @Nullable EntityReference<LivingEntity> selectNewTarget(final ServerLevel level, final BlockPos pos) {
List<LivingEntity> candidates = level.getEntitiesOfClass(
- LivingEntity.class, getDestroyRangeAABB(pos), input -> input instanceof Enemy && input.isInWaterOrRain()
+ LivingEntity.class, getDestroyRangeAABB(pos, level), input -> input instanceof Enemy && input.isInWaterOrRain() // Purpur - Conduit behavior configuration
);
return candidates.isEmpty() ? null : EntityReference.of(Util.getRandom(candidates, level.getRandom()));
}
public static AABB getDestroyRangeAABB(final BlockPos worldPosition) {
- return new AABB(worldPosition).inflate(8.0);
+ // Purpur start - Conduit behavior configuration
+ return getDestroyRangeAABB(worldPosition, null);
+ }
+
+ private static AABB getDestroyRangeAABB(final BlockPos worldPosition, final Level level) {
+ // Purpur end - Conduit behavior configuration
+ return new AABB(worldPosition).inflate(level == null ? 8.0 : level.purpurConfig.conduitDamageDistance); // Purpur - Conduit behavior configuration
}
private static void animationTick(

View File

@@ -1,15 +1,7 @@
From 56a0a83ddb1b7472dbc9762e2aca396605c62085 Mon Sep 17 00:00:00 2001
From: File <noreply+automated@papermc.io>
Date: Sun, 20 Apr 1997 05:37:42 -0800
Subject: [PATCH] purpur File Patches
diff --git a/net/minecraft/world/level/block/entity/SignBlockEntity.java b/net/minecraft/world/level/block/entity/SignBlockEntity.java
index ce6108ea608463a28f9349010e912f23a7a1cb0c..e93f399c02aa3c47b08e33b8cf2f8b474273c33b 100644
--- a/net/minecraft/world/level/block/entity/SignBlockEntity.java
+++ b/net/minecraft/world/level/block/entity/SignBlockEntity.java
@@ -149,16 +149,32 @@ public class SignBlockEntity extends BlockEntity {
return this.setText(updater.apply(text), isFrontText);
@@ -149,16 +_,32 @@
return this.setText(function.apply(text), isFrontText);
}
+ // Purpur start - Signs allow color codes
@@ -26,27 +18,28 @@ index ce6108ea608463a28f9349010e912f23a7a1cb0c..e93f399c02aa3c47b08e33b8cf2f8b47
+ }
+ // Purpur end - Signs allow color codes
+
private SignText setMessages(Player player, List<FilteredText> filteredText, SignText text, boolean front) { // CraftBukkit
private SignText setMessages(final Player player, final List<FilteredText> lines, SignText text, final boolean front) { // CraftBukkit
SignText originalText = text; // CraftBukkit
for (int i = 0; i < filteredText.size(); i++) {
FilteredText filteredText1 = filteredText.get(i);
Style style = text.getMessage(i, player.isTextFilteringEnabled()).getStyle();
for (int i = 0; i < lines.size(); i++) {
FilteredText line = lines.get(i);
Style currentTextStyle = text.getMessage(i, player.isTextFilteringEnabled()).getStyle();
+
+ org.bukkit.entity.Player craftPlayer = (org.bukkit.craftbukkit.entity.CraftPlayer) player.getBukkitEntity(); // Purpur - Signs allow color codes
if (player.isTextFilteringEnabled()) {
- text = text.setMessage(i, Component.literal(net.minecraft.util.StringUtil.filterText(filteredText1.filteredOrEmpty())).setStyle(style)); // Paper - filter sign text to chat only
+ text = text.setMessage(i, translateColors(craftPlayer, net.minecraft.util.StringUtil.filterText(filteredText1.filteredOrEmpty()), style)); // Paper - filter sign text to chat only // Purpur - Signs allow color codes
- text = text.setMessage(i, Component.literal(net.minecraft.util.StringUtil.filterText(line.filteredOrEmpty())).setStyle(currentTextStyle)); // Paper - filter sign text to chat only
+ text = text.setMessage(i, translateColors(craftPlayer, net.minecraft.util.StringUtil.filterText(line.filteredOrEmpty()), currentTextStyle)); // Paper - filter sign text to chat only // Purpur - Signs allow color codes
} else {
text = text.setMessage(
- i, Component.literal(filteredText1.raw()).setStyle(style), Component.literal(net.minecraft.util.StringUtil.filterText(filteredText1.filteredOrEmpty())).setStyle(style) // Paper - filter sign text to chat only
+ i, translateColors(craftPlayer, net.minecraft.util.StringUtil.filterText(filteredText1.raw()), style), translateColors(craftPlayer, net.minecraft.util.StringUtil.filterText(filteredText1.filteredOrEmpty()), style) // Paper - filter sign text to chat only // Purpur - Signs allow color codes
- i, Component.literal(line.raw()).setStyle(currentTextStyle), Component.literal(net.minecraft.util.StringUtil.filterText(line.filteredOrEmpty())).setStyle(currentTextStyle) // Paper - filter sign text to chat only
+ i, translateColors(craftPlayer, net.minecraft.util.StringUtil.filterText(line.raw()), currentTextStyle), translateColors(craftPlayer, net.minecraft.util.StringUtil.filterText(line.filteredOrEmpty()), currentTextStyle) // Paper - filter sign text to chat only // Purpur - Signs allow color codes
);
}
}
@@ -308,6 +324,27 @@ public class SignBlockEntity extends BlockEntity {
return new CommandSourceStack(commandSource, Vec3.atCenterOf(pos), Vec2.ZERO, level, LevelBasedPermissionSet.GAMEMASTER, string, component, level.getServer(), player); // Paper - Fix commands from signs not firing command events
@@ -308,6 +_,27 @@
commandSource, Vec3.atCenterOf(pos), Vec2.ZERO, level, LevelBasedPermissionSet.GAMEMASTER, textName, displayName, level.getServer(), player // Paper - Fix commands from signs not firing command events
);
}
+
+ // Purpur start - Signs allow color codes
+ public ClientboundBlockEntityDataPacket getTranslatedUpdatePacket(boolean filtered, boolean front) {
+ try (net.minecraft.util.ProblemReporter.ScopedCollector scopedCollector = new net.minecraft.util.ProblemReporter.ScopedCollector(this.problemPath(), LOGGER)) {
@@ -67,7 +60,6 @@ index ce6108ea608463a28f9349010e912f23a7a1cb0c..e93f399c02aa3c47b08e33b8cf2f8b47
+ }
+ }
+ // Purpur end - Signs allow color codes
+
@Override
public ClientboundBlockEntityDataPacket getUpdatePacket() {
return ClientboundBlockEntityDataPacket.create(this);