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,114 +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/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
public joptsimple.OptionSet options;
public org.bukkit.command.ConsoleCommandSender console;
public static int currentTick; // Paper - improve tick loop
+ public static final long startTimeMillis = System.currentTimeMillis(); // Purpur - Add uptime command
public java.util.Queue<Runnable> processQueue = new java.util.concurrent.ConcurrentLinkedQueue<Runnable>();
public int autosavePeriod;
// Paper - don't store the vanilla dispatcher
@@ -306,6 +307,8 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
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
+ public boolean lagging = false; // Purpur - Lagging threshold
+ protected boolean upnp = false; // Purpur - UPnP Port Forwarding
// 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
public double[] computeTPS() {
final long interval = this.tickRateManager().nanosecondsPerTick();
return new double[] {
+ getTPS(this.tickTimes5s, interval), // Purpur - Add 5 second tps average in /tps
getTPS(this.tickTimes1m, interval),
getTPS(this.tickTimes5m, interval),
getTPS(this.tickTimes15m, interval)
@@ -1014,6 +1018,15 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
LOGGER.info("Stopping server");
Commands.COMMAND_SENDING_POOL.shutdownNow(); // Paper - Perf: Async command map building; Shutdown and don't bother finishing
+ // Purpur start - UPnP Port Forwarding
+ if (upnp) {
+ if (dev.omega24.upnp4j.UPnP4J.close(this.getPort(), dev.omega24.upnp4j.util.Protocol.TCP)) {
+ LOGGER.info("[UPnP] Port {} closed", this.getPort());
+ } else {
+ LOGGER.error("[UPnP] Failed to close port {}", this.getPort());
+ }
+ }
+ // Purpur end - UPnP Port Forwarding
// CraftBukkit start
if (this.server != null) {
this.server.spark.disable(); // Paper - spark
@@ -1107,6 +1120,8 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
this.safeShutdown(waitForShutdown, false);
}
public void safeShutdown(boolean waitForShutdown, 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
}
// Paper end - Add onboarding message for initial server start
// Paper start - Improve outdated version checking
- if (System.getProperty("paper.disableStartupVersionCheck") == null && io.papermc.paper.configuration.GlobalConfiguration.get().updateChecker.enabled) {
+ if (false && System.getProperty("paper.disableStartupVersionCheck") == null && io.papermc.paper.configuration.GlobalConfiguration.get().updateChecker.enabled) { // Purpur - disable paper startup check
CompletableFuture.runAsync(com.destroystokyo.paper.PaperVersionFetcher::getUpdateStatusStartupMessage, io.papermc.paper.util.MCUtil.ASYNC_EXECUTOR);
}
// Paper end - Improve outdated version checking
+ // Purpur start - config for startup commands
+ if (!Boolean.getBoolean("Purpur.IReallyDontWantStartupCommands") && !org.purpurmc.purpur.PurpurConfig.startupCommands.isEmpty()) {
+ LOGGER.info("Purpur: Running startup commands specified in purpur.yml.");
+ for (final String startupCommand : org.purpurmc.purpur.PurpurConfig.startupCommands) {
+ LOGGER.info("Purpur: Running the following command: \"{}\"", startupCommand);
+ ((net.minecraft.server.dedicated.DedicatedServer) this).handleConsoleInput(startupCommand, this.createCommandSourceStack());
+ }
+ }
+ // Purpur end - config for startup commands
+
while (this.running) {
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));
final long catchup = (long)Math.max(
1,
- 5 //ConfigHolder.getConfig().tickLoop.catchupTicks.getOrDefault(MoonriseConfig.TickLoop.DEFAULT_CATCHUP_TICKS).intValue()
+ org.purpurmc.purpur.PurpurConfig.tpsCatchup ? 5 : 1 //ConfigHolder.getConfig().tickLoop.catchupTicks.getOrDefault(MoonriseConfig.TickLoop.DEFAULT_CATCHUP_TICKS).intValue() // Purpur - Configurable TPS Catchup
);
+ lagging = getTPS()[0] < org.purpurmc.purpur.PurpurConfig.laggingThreshold; // Purpur - Lagging threshold
+
// 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;
}
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) {

View File

@@ -1,224 +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/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
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);
@@ -622,8 +624,25 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
// 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;
+ // Purpur start - Allow toggling special MobSpawners per world
+ if (purpurConfig.phantomSpawning) {
+ this.customSpawners.add(new net.minecraft.world.level.levelgen.PhantomSpawner());
+ }
+ if (purpurConfig.patrolSpawning) {
+ this.customSpawners.add(new net.minecraft.world.level.levelgen.PatrolSpawner());
+ }
+ if (purpurConfig.catSpawning) {
+ this.customSpawners.add(new net.minecraft.world.entity.npc.CatSpawner());
+ }
+ if (purpurConfig.villageSiegeSpawning) {
+ this.customSpawners.add(new net.minecraft.world.entity.ai.village.VillageSiege());
+ }
+ if (purpurConfig.villagerTraderSpawning) {
+ this.customSpawners.add(new net.minecraft.world.entity.npc.wanderingtrader.WanderingTraderSpawner(serverLevelData));
+ }
+ // Purpur end - Allow toggling special MobSpawners per world
ChunkGenerator chunkGenerator = 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
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
}
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);
+ // Purpur start - Special mobs naturally spawn
+ net.minecraft.world.entity.animal.equine.AbstractHorse skeletonHorse;
+ if (purpurConfig.zombieHorseSpawnChance > 0D && random.nextDouble() <= purpurConfig.zombieHorseSpawnChance) {
+ skeletonHorse = EntityType.ZOMBIE_HORSE.create(this, EntitySpawnReason.EVENT);
+ } else {
+ skeletonHorse = EntityType.SKELETON_HORSE.create(this, EntitySpawnReason.EVENT);
+ 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)) {
+ // Purpur start - Smooth snow accumulation
+ boolean canSnow = true;
+ // Ensure snow doesn't get more than N layers taller than its neighbors
+ // We only need to check blocks that are taller than the minimum step height
+ if (org.purpurmc.purpur.PurpurConfig.smoothSnowAccumulationStep > 0 && layersValue >= org.purpurmc.purpur.PurpurConfig.smoothSnowAccumulationStep) {
+ int layersValueMin = layersValue - org.purpurmc.purpur.PurpurConfig.smoothSnowAccumulationStep;
+ for (Direction direction : Direction.Plane.HORIZONTAL) {
+ BlockPos blockPosNeighbor = heightmapPos.relative(direction);
+ BlockState blockStateNeighbor = this.getBlockState(blockPosNeighbor);
+ if (blockStateNeighbor.is(Blocks.SNOW)) {
+ // Special check for snow layers, if neighbors are too short, don't accumulate
+ int layersValueNeighbor = blockStateNeighbor.getValue(SnowLayerBlock.LAYERS);
+ if (layersValueNeighbor <= layersValueMin) {
+ canSnow = false;
+ break;
+ }
+ } else if (!Block.isFaceFull(blockStateNeighbor.getCollisionShape(this, blockPosNeighbor), direction.getOpposite())) {
+ // Since our layer is tall enough already, if we have a non-full neighbor block, don't accumulate
+ canSnow = false;
+ break;
+ }
+ }
+ }
+ 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
+ } // 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,
- 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)) {
+ // Purpur start - Customizable sleeping actionbar messages
+ if (org.purpurmc.purpur.PurpurConfig.sleepSkippingNight.isBlank()) {
+ return;
+ }
+ if (!org.purpurmc.purpur.PurpurConfig.sleepSkippingNight.equalsIgnoreCase("default")) {
+ component = io.papermc.paper.adventure.PaperAdventure.asVanilla(net.kyori.adventure.text.minimessage.MiniMessage.miniMessage().deserialize(org.purpurmc.purpur.PurpurConfig.sleepSkippingNight));
+ } else
+ // Purpur end - Customizable sleeping actionbar messages
component = Component.translatable("sleep.skipping_night");
} else {
+ // Purpur start - Customizable sleeping actionbar messages
+ if (org.purpurmc.purpur.PurpurConfig.sleepingPlayersPercent.isBlank()) {
+ return;
+ }
+ if (!org.purpurmc.purpur.PurpurConfig.sleepingPlayersPercent.equalsIgnoreCase("default")) {
+ component = io.papermc.paper.adventure.PaperAdventure.asVanilla(net.kyori.adventure.text.minimessage.MiniMessage.miniMessage().deserialize(org.purpurmc.purpur.PurpurConfig.sleepingPlayersPercent,
+ net.kyori.adventure.text.minimessage.tag.resolver.Placeholder.parsed("count", Integer.toString(this.sleepStatus.amountSleeping())),
+ net.kyori.adventure.text.minimessage.tag.resolver.Placeholder.parsed("total", Integer.toString(this.sleepStatus.sleepersNeeded(i)))));
+ } else
+ // Purpur end - Customizable sleeping actionbar messages
component = Component.translatable("sleep.players_sleeping", this.sleepStatus.amountSleeping(), this.sleepStatus.sleepersNeeded(i));
}
@@ -1275,6 +1368,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
@VisibleForTesting
public void resetWeatherCycle() {
// CraftBukkit start
+ if (this.purpurConfig.rainStopsAfterSleep) // Purpur - Option for if rain and thunder should stop on sleep
this.serverLevelData.setRaining(false, org.bukkit.event.weather.WeatherChangeEvent.Cause.SLEEP); // Paper - Add cause to Weather/ThunderChangeEvents
// If we stop due to everyone sleeping we should reset the weather duration to some other random value.
// Not that everyone ever manages to get the whole server to sleep at the same time....
@@ -1282,6 +1376,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
this.serverLevelData.setRainTime(0);
}
// CraftBukkit end
+ if (this.purpurConfig.thunderStopsAfterSleep) // Purpur - Option for if rain and thunder should stop on sleep
this.serverLevelData.setThundering(false, org.bukkit.event.weather.ThunderChangeEvent.Cause.SLEEP); // Paper - Add cause to Weather/ThunderChangeEvents
// CraftBukkit start
// If we stop due to everyone sleeping we should reset the weather duration to some other random value.
@@ -1954,7 +2049,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
Explosion.BlockInteraction blockInteraction = switch (explosionInteraction) {
case NONE -> Explosion.BlockInteraction.KEEP;
case BLOCK -> this.getDestroyType(GameRules.BLOCK_EXPLOSION_DROP_DECAY);
- case MOB -> this.getGameRules().get(GameRules.MOB_GRIEFING)
+ case MOB -> ((source instanceof net.minecraft.world.entity.projectile.hurtingprojectile.LargeFireball) ? this.getGameRules().get(GameRules.MOB_GRIEFING, this.purpurConfig.fireballsMobGriefingOverride) : this.getGameRules().get(GameRules.MOB_GRIEFING)) // Purpur - Add mobGriefing override to everything affected
? 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
// Spigot start
if (entity.getBukkitEntity() instanceof org.bukkit.inventory.InventoryHolder && (!(entity instanceof ServerPlayer) || entity.getRemovalReason() != Entity.RemovalReason.KILLED)) { // SPIGOT-6876: closeInventory clears death message
// Paper start - Fix merchant inventory not closing on entity removal
- if (entity.getBukkitEntity() instanceof org.bukkit.inventory.Merchant merchant && merchant.getTrader() != null) {
+ if (!entity.level().purpurConfig.playerVoidTrading && entity.getBukkitEntity() instanceof org.bukkit.inventory.Merchant merchant && merchant.getTrader() != null) { // Purpur - Allow void trading
merchant.getTrader().closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason.UNLOADED);
}
// Paper end - Fix merchant inventory not closing on entity removal

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,81 +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/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 {
// Paper end - Fix MC-167279
this.lookControl = new Bee.BeeLookControl(this);
this.setPathfindingMalus(PathType.DANGER_FIRE, -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 {
if (this.stayOutOfHiveCountdown <= 0 && !this.beePollinateGoal.isPollinating() && !this.hasStung() && this.getTarget() == null) {
boolean flag = 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();
} else {
return false;
}
}
+ // Purpur start - Bee can work when raining or at night
+ public static boolean isNightOrRaining(Level level) {
+ return level.dimensionType().hasSkyLight() && (level.isDarkOutside() && !level.purpurConfig.beeCanWorkAtNight || level.isRaining() && !level.purpurConfig.beeCanWorkInRain); // Purpur - Bee can work when raining or at night
+ }
+ // Purpur end - Bee can work when raining or at night
+
public void setStayOutOfHiveCountdown(int stayOutOfHiveCountdown) {
this.stayOutOfHiveCountdown = stayOutOfHiveCountdown;
}
@@ -387,7 +393,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal {
@Override
protected void customServerAiStep(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 {
this.hurtServer(level, this.damageSources().drown(), 1.0F);
}
+ if (hasStung && !this.level().purpurConfig.beeDiesAfterSting) setHasStung(false); else // Purpur - Stop bees from dying after stinging
if (hasStung) {
this.timeSinceSting++;
if (this.timeSinceSting % 5 == 0 && this.random.nextInt(Mth.clamp(1200 - this.timeSinceSting, 1, 1200)) == 0) {
@@ -1130,6 +1137,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal {
Bee.this.savedFlowerPos = optional.get();
Bee.this.navigation
.moveTo(Bee.this.savedFlowerPos.getX() + 0.5, Bee.this.savedFlowerPos.getY() + 0.5, Bee.this.savedFlowerPos.getZ() + 0.5, 1.2F);
+ new org.purpurmc.purpur.event.entity.BeeFoundFlowerEvent((org.bukkit.entity.Bee) Bee.this.getBukkitEntity(), 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 {
this.pollinating = false;
Bee.this.navigation.stop();
Bee.this.remainingCooldownBeforeLocatingNewFlower = 200;
+ new org.purpurmc.purpur.event.entity.BeeStopPollinatingEvent((org.bukkit.entity.Bee) Bee.this.getBukkitEntity(), Bee.this.savedFlowerPos == null ? null : org.bukkit.craftbukkit.util.CraftLocation.toBukkit(Bee.this.savedFlowerPos, Bee.this.level()), Bee.this.hasNectar()).callEvent(); // Purpur - Bee API
}
@Override
@@ -1222,6 +1231,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal {
this.setWantedPos();
}
+ if (this.successfulPollinatingTicks == 0) new org.purpurmc.purpur.event.entity.BeeStartedPollinatingEvent((org.bukkit.entity.Bee) Bee.this.getBukkitEntity(), org.bukkit.craftbukkit.util.CraftLocation.toBukkit(Bee.this.savedFlowerPos, Bee.this.level())).callEvent(); // Purpur - Bee API
this.successfulPollinatingTicks++;
if (Bee.this.random.nextFloat() < 0.05F && this.successfulPollinatingTicks > this.lastSoundPlayedTick + 60) {
this.lastSoundPlayedTick = this.successfulPollinatingTicks;

View File

@@ -1,98 +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/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 {
this.goalSelector.addGoal(0, new FloatGoal(this));
this.goalSelector.addGoal(1, new PanicGoal(this, 2.0));
this.goalSelector.addGoal(2, new BreedGoal(this, 1.0));
- this.goalSelector.addGoal(3, new TemptGoal(this, 1.25, itemStack -> itemStack.is(ItemTags.COW_FOOD), false));
+ this.goalSelector.addGoal(3, new TemptGoal(this, 1.25, itemStack -> level().purpurConfig.cowFeedMushrooms > 0 && (itemStack.is(net.minecraft.world.level.block.Blocks.RED_MUSHROOM.asItem()) || itemStack.is(net.minecraft.world.level.block.Blocks.BROWN_MUSHROOM.asItem())) || itemStack.is(ItemTags.COW_FOOD), false)); // Purpur - Cows eat mushrooms
this.goalSelector.addGoal(4, new FollowParentGoal(this, 1.25));
this.goalSelector.addGoal(5, new WaterAvoidingRandomStrollGoal(this, 1.0));
this.goalSelector.addGoal(6, new LookAtPlayerGoal(this, Player.class, 6.0F));
@@ -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);
return InteractionResult.SUCCESS;
+ // Purpur start - Cows eat mushrooms - feed mushroom to change to mooshroom
+ } else if (level().purpurConfig.cowFeedMushrooms > 0 && this.getType() != EntityType.MOOSHROOM && isMushroom(itemInHand)) {
+ return this.feedMushroom(player, itemInHand);
+ // Purpur end - Cows eat mushrooms
} else {
return super.mobInteract(player, hand);
}
@@ -105,4 +109,67 @@ public abstract class AbstractCow extends Animal {
public EntityDimensions getDefaultDimensions(Pose pose) {
return this.isBaby() ? BABY_DIMENSIONS : super.getDefaultDimensions(pose);
}
+
+ // Purpur start - Cows eat mushrooms - feed mushroom to change to mooshroom
+ private int redMushroomsFed = 0;
+ private int brownMushroomsFed = 0;
+
+ private boolean isMushroom(ItemStack stack) {
+ return stack.getItem() == net.minecraft.world.level.block.Blocks.RED_MUSHROOM.asItem() || stack.getItem() == net.minecraft.world.level.block.Blocks.BROWN_MUSHROOM.asItem();
+ }
+
+ private int incrementFeedCount(ItemStack stack) {
+ if (stack.getItem() == net.minecraft.world.level.block.Blocks.RED_MUSHROOM.asItem()) {
+ return ++redMushroomsFed;
+ } else {
+ return ++brownMushroomsFed;
+ }
+ }
+
+ private InteractionResult feedMushroom(Player player, ItemStack stack) {
+ level().broadcastEntityEvent(this, (byte) 18); // hearts
+ playSound(SoundEvents.COW_MILK, 1.0F, 1.0F);
+ if (incrementFeedCount(stack) < level().purpurConfig.cowFeedMushrooms) {
+ if (!player.getAbilities().instabuild) {
+ stack.shrink(1);
+ }
+ return InteractionResult.CONSUME; // require 5 mushrooms to transform (prevents mushroom duping)
+ }
+ MushroomCow mooshroom = EntityType.MOOSHROOM.create(level(), net.minecraft.world.entity.EntitySpawnReason.CONVERSION);
+ if (mooshroom == null) {
+ return InteractionResult.PASS;
+ }
+ if (stack.getItem() == net.minecraft.world.level.block.Blocks.BROWN_MUSHROOM.asItem()) {
+ mooshroom.setVariant(MushroomCow.Variant.BROWN);
+ } else {
+ mooshroom.setVariant(MushroomCow.Variant.RED);
+ }
+ mooshroom.snapTo(this.getX(), this.getY(), this.getZ(), this.getYRot(), this.getXRot());
+ mooshroom.setHealth(this.getHealth());
+ mooshroom.setAge(getAge());
+ mooshroom.copyPosition(this);
+ mooshroom.setYBodyRot(this.yBodyRot);
+ mooshroom.setYHeadRot(this.getYHeadRot());
+ mooshroom.yRotO = this.yRotO;
+ mooshroom.xRotO = this.xRotO;
+ if (this.hasCustomName()) {
+ mooshroom.setCustomName(this.getCustomName());
+ }
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityTransformEvent(this, mooshroom, org.bukkit.event.entity.EntityTransformEvent.TransformReason.INFECTION).isCancelled()) {
+ return InteractionResult.PASS;
+ }
+ this.level().addFreshEntity(mooshroom);
+ this.remove(RemovalReason.DISCARDED, org.bukkit.event.entity.EntityRemoveEvent.Cause.DISCARD);
+ if (!player.getAbilities().instabuild) {
+ stack.shrink(1);
+ }
+ for (int i = 0; i < 15; ++i) {
+ ((net.minecraft.server.level.ServerLevel) level()).sendParticlesSource(((net.minecraft.server.level.ServerLevel) level()).players(), null, net.minecraft.core.particles.ParticleTypes.HAPPY_VILLAGER,
+ false, true,
+ getX() + random.nextFloat(), getY() + (random.nextFloat() * 2), getZ() + random.nextFloat(), 1,
+ random.nextGaussian() * 0.05D, random.nextGaussian() * 0.05D, random.nextGaussian() * 0.05D, 0);
+ }
+ return InteractionResult.SUCCESS;
+ }
+ // Purpur end - Cows eat mushrooms
}

View File

@@ -1,55 +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/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 {
public static final float BABY_SCALE = 0.65F;
private static final boolean DEFAULT_GOT_FISH = false;
@Nullable public BlockPos treasurePos;
+ private boolean isNaturallyAggressiveToPlayers; // Purpur - Dolphins naturally aggressive to players chance
public Dolphin(EntityType<? extends Dolphin> type, Level level) {
super(type, level);
@@ -90,6 +91,7 @@ public class Dolphin extends AgeableWaterCreature {
this.setAirSupply(this.getMaxAirSupply());
this.setXRot(0.0F);
SpawnGroupData spawnGroupData1 = Objects.requireNonNullElseGet(spawnGroupData, () -> new AgeableMob.AgeableMobGroupData(0.1F));
+ this.isNaturallyAggressiveToPlayers = level.getLevel().purpurConfig.dolphinNaturallyAggressiveToPlayersChance > 0.0D && random.nextDouble() <= level.getLevel().purpurConfig.dolphinNaturallyAggressiveToPlayersChance; // Purpur - Dolphins naturally aggressive to players chance
return super.finalizeSpawn(level, difficulty, spawnReason, spawnGroupData1);
}
@@ -155,17 +157,19 @@ public class Dolphin extends AgeableWaterCreature {
protected void registerGoals() {
this.goalSelector.addGoal(0, new BreathAirGoal(this));
this.goalSelector.addGoal(0, new TryFindWaterGoal(this));
+ this.goalSelector.addGoal(1, new MeleeAttackGoal(this, 1.2000000476837158D, true)); // Purpur - Dolphins naturally aggressive to players chance
this.goalSelector.addGoal(1, new Dolphin.DolphinSwimToTreasureGoal(this));
this.goalSelector.addGoal(2, new Dolphin.DolphinSwimWithPlayerGoal(this, 4.0));
this.goalSelector.addGoal(4, new RandomSwimmingGoal(this, 1.0, 10));
this.goalSelector.addGoal(4, new RandomLookAroundGoal(this));
this.goalSelector.addGoal(5, new LookAtPlayerGoal(this, Player.class, 6.0F));
this.goalSelector.addGoal(5, new DolphinJumpGoal(this, 10));
- this.goalSelector.addGoal(6, new MeleeAttackGoal(this, 1.2F, true));
+ //this.goalSelector.addGoal(6, new MeleeAttackGoal(this, 1.2F, true)); // Purpur - moved up - Dolphins naturally aggressive to players chance
this.goalSelector.addGoal(8, new Dolphin.PlayWithItemsGoal());
this.goalSelector.addGoal(8, new FollowBoatGoal(this));
this.goalSelector.addGoal(9, new AvoidEntityGoal<>(this, Guardian.class, 8.0F, 1.0, 1.0));
this.targetSelector.addGoal(1, new HurtByTargetGoal(this, Guardian.class).setAlertOthers());
+ this.targetSelector.addGoal(2, new net.minecraft.world.entity.ai.goal.target.NearestAttackableTargetGoal<>(this, Player.class, 10, true, false, (ignored, ignored2) -> isNaturallyAggressiveToPlayers)); // Purpur - Dolphins naturally aggressive to players chance
}
public static AttributeSupplier.Builder createAttributes() {
@@ -392,6 +396,7 @@ public class Dolphin extends AgeableWaterCreature {
@Override
public boolean canUse() {
+ if (this.dolphin.level().purpurConfig.dolphinDisableTreasureSearching) return false; // Purpur - Add option to disable dolphin treasure searching
return this.dolphin.gotFish() && this.dolphin.getAirSupply() >= 100;
}

View File

@@ -1,50 +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/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;
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) {
super(type, level);
@@ -105,6 +106,7 @@ public class Llama extends AbstractChestedHorse implements RangedAttackMob {
super.addAdditionalSaveData(output);
output.store("Variant", Llama.Variant.LEGACY_CODEC, this.getVariant());
output.putInt("Strength", this.getStrength());
+ output.putBoolean("Purpur.ShouldJoinCaravan", shouldJoinCaravan); // Purpur - Llama API
}
@Override
@@ -112,6 +114,7 @@ public class Llama extends AbstractChestedHorse implements RangedAttackMob {
this.setStrength(input.getIntOr("Strength", 0));
super.readAdditionalSaveData(input);
this.setVariant(input.read("Variant", Llama.Variant.LEGACY_CODEC).orElse(Llama.Variant.DEFAULT));
+ this.shouldJoinCaravan = input.getBooleanOr("Purpur.ShouldJoinCaravan", true); // Purpur - Llama API
}
@Override
@@ -388,6 +391,7 @@ public class Llama extends AbstractChestedHorse implements RangedAttackMob {
public void leaveCaravan() {
if (this.caravanHead != null) {
+ new org.purpurmc.purpur.event.entity.LlamaLeaveCaravanEvent((org.bukkit.entity.Llama) getBukkitEntity()).callEvent(); // Purpur - Llama API
this.caravanHead.caravanTail = null;
}
@@ -395,6 +399,7 @@ public class Llama extends AbstractChestedHorse implements RangedAttackMob {
}
public void joinCaravan(Llama caravanHead) {
+ 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.caravanTail = 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/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);
}
+ // Purpur start - Configurable default collar color
+ @Override
+ public void tame(Player player) {
+ setCollarColor(level().purpurConfig.catDefaultCollarColor);
+ super.tame(player);
+ }
+ // Purpur end - Configurable default collar color
+
@Override
public @Nullable SpawnGroupData finalizeSpawn(
ServerLevelAccessor level, DifficultyInstance difficulty, EntitySpawnReason spawnReason, @Nullable SpawnGroupData spawnGroupData
@@ -451,7 +459,7 @@ public class Cat extends TamableAnimal {
}
private void tryToTame(Player player) {
- if (this.random.nextInt(3) == 0 && !org.bukkit.craftbukkit.event.CraftEventFactory.callEntityTameEvent(this, player).isCancelled()) { // CraftBukkit
+ if (((this.level().purpurConfig.alwaysTameInCreative && player.hasInfiniteMaterials()) || this.random.nextInt(3) == 0) && !org.bukkit.craftbukkit.event.CraftEventFactory.callEntityTameEvent(this, player).isCancelled()) { // CraftBukkit // Purpur - Config to always tame in Creative
this.tame(player);
this.setOrderedToSit(true);
this.level().broadcastEntityEvent(this, EntityEvent.TAMING_SUCCEEDED);

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,31 +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/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 {
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 {
}
if (integer == 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)) {
container.stopOpen(copperGolem);
}

View File

@@ -1,60 +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/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 {
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) {
super(type, level);
}
+ // Purpur start - Summoner API
+ public java.util.@Nullable UUID getSummoner() {
+ return summoner;
+ }
+
+ public void setSummoner(java.util.@Nullable UUID summoner) {
+ this.summoner = summoner;
+ }
+ // Purpur end - Summoner API
+
@Override
protected void registerGoals() {
+ if (this.level().purpurConfig.ironGolemPoppyCalm) this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.ReceiveFlower(this)); // Purpur - Iron golem calm anger options
this.goalSelector.addGoal(1, new MeleeAttackGoal(this, 1.0, true));
this.goalSelector.addGoal(2, new MoveTowardsTargetGoal(this, 0.9, 32.0F));
this.goalSelector.addGoal(2, new MoveBackToVillageGoal(this, 0.6, false));
@@ -142,6 +154,7 @@ public class IronGolem extends AbstractGolem implements NeutralMob {
protected void addAdditionalSaveData(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) {
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);
+ if (this.level().purpurConfig.ironGolemHealCalm && isAngry() && getHealth() == getMaxHealth()) stopBeingAngry(); // Purpur - Iron golem calm anger options
return InteractionResult.SUCCESS;
}
}

View File

@@ -1,59 +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/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 {
protected void registerGoals() {
this.goalSelector.addGoal(0, new TamableAnimal.TamableAnimalPanicGoal(1.25));
this.goalSelector.addGoal(0, new FloatGoal(this));
+ if (this.level().purpurConfig.parrotBreedable) this.goalSelector.addGoal(1, new net.minecraft.world.entity.ai.goal.BreedGoal(this, 1.0D)); // Purpur - Breedable parrots
this.goalSelector.addGoal(1, new LookAtPlayerGoal(this, Player.class, 8.0F));
this.goalSelector.addGoal(2, new SitWhenOrderedToGoal(this));
this.goalSelector.addGoal(2, new FollowOwnerGoal(this, 1.0, 5.0F, 1.0F));
@@ -269,7 +270,7 @@ public class Parrot extends ShoulderRidingEntity implements FlyingAnimal {
}
if (!this.level().isClientSide()) {
- if (this.random.nextInt(10) == 0 && !org.bukkit.craftbukkit.event.CraftEventFactory.callEntityTameEvent(this, player).isCancelled()) { // CraftBukkit
+ if (((this.level().purpurConfig.alwaysTameInCreative && player.hasInfiniteMaterials()) || this.random.nextInt(10) == 0) && !org.bukkit.craftbukkit.event.CraftEventFactory.callEntityTameEvent(this, player).isCancelled()) { // CraftBukkit // Purpur - Config to always tame in Creative
this.tame(player);
this.level().broadcastEntityEvent(this, EntityEvent.TAMING_SUCCEEDED);
} else {
@@ -277,6 +278,7 @@ public class Parrot extends ShoulderRidingEntity implements FlyingAnimal {
}
}
+ if (this.level().purpurConfig.parrotBreedable) return super.mobInteract(player, hand); // Purpur - Breedable parrots
return InteractionResult.SUCCESS;
} else if (!itemInHand.is(ItemTags.PARROT_POISONOUS_FOOD)) {
if (!this.isFlying() && this.isTame() && this.isOwnedBy(player)) {
@@ -301,7 +303,7 @@ public class Parrot extends ShoulderRidingEntity implements FlyingAnimal {
@Override
public boolean isFood(ItemStack stack) {
- return false;
+ return this.level().purpurConfig.parrotBreedable && stack.is(ItemTags.PARROT_FOOD); // Purpur - Breedable parrots
}
public static boolean checkParrotSpawnRules(
@@ -316,12 +318,12 @@ public class Parrot extends ShoulderRidingEntity implements FlyingAnimal {
@Override
public boolean canMate(Animal otherAnimal) {
- return false;
+ return super.canMate(otherAnimal); // Purpur - Breedable parrots
}
@Override
public @Nullable AgeableMob getBreedOffspring(ServerLevel level, AgeableMob partner) {
- return null;
+ return level.purpurConfig.parrotBreedable ? EntityType.PARROT.create(level, EntitySpawnReason.BREEDING) : null; // Purpur - Breedable parrots
}
@Override

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,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/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 {
super(type, level);
}
+ // Purpur start - Breedable Polar Bears
+ public boolean canMate(Animal other) {
+ if (other == this) {
+ return false;
+ } else if (this.isStanding()) {
+ return false;
+ } else if (this.getTarget() != null) {
+ return false;
+ } else if (!(other instanceof PolarBear)) {
+ return false;
+ } else {
+ PolarBear bear = (PolarBear) other;
+ if (bear.isStanding()) {
+ return false;
+ }
+ if (bear.getTarget() != null) {
+ return false;
+ }
+ return this.isInLove() && bear.isInLove();
+ }
+ }
+ // Purpur end - Breedable Polar Bears
+
@Override
public @Nullable AgeableMob getBreedOffspring(ServerLevel level, AgeableMob partner) {
return EntityType.POLAR_BEAR.create(level, EntitySpawnReason.BREEDING);
@@ -73,7 +96,7 @@ public class PolarBear extends Animal implements NeutralMob {
@Override
public boolean isFood(ItemStack stack) {
- return false;
+ return level().purpurConfig.polarBearBreedableItem != null && stack.getItem() == level().purpurConfig.polarBearBreedableItem; // Purpur - Breedable Polar Bears
}
@Override
@@ -82,6 +105,12 @@ public class PolarBear extends Animal implements NeutralMob {
this.goalSelector.addGoal(0, new FloatGoal(this));
this.goalSelector.addGoal(1, new PolarBear.PolarBearMeleeAttackGoal());
this.goalSelector.addGoal(1, new PanicGoal(this, 2.0, mob -> mob.isBaby() ? DamageTypeTags.PANIC_CAUSES : DamageTypeTags.PANIC_ENVIRONMENTAL_CAUSES));
+ // Purpur start - Breedable Polar Bears
+ if (level().purpurConfig.polarBearBreedableItem != null) {
+ this.goalSelector.addGoal(2, new net.minecraft.world.entity.ai.goal.BreedGoal(this, 1.0D));
+ this.goalSelector.addGoal(3, new net.minecraft.world.entity.ai.goal.TemptGoal(this, 1.0D, net.minecraft.world.item.crafting.Ingredient.of(level().purpurConfig.polarBearBreedableItem), false));
+ }
+ // Purpur end - Breedable Polar Bears
this.goalSelector.addGoal(4, new FollowParentGoal(this, 1.25));
this.goalSelector.addGoal(5, new RandomStrollGoal(this, 1.0));
this.goalSelector.addGoal(6, new LookAtPlayerGoal(this, Player.class, 6.0F));

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,58 +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/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 {
public Squid(EntityType<? extends Squid> type, 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
this.tentacleSpeed = 1.0F / (this.random.nextFloat() + 1.0F) * 0.2F;
}
+ // Purpur start - Stop squids floating on top of water
+ @Override
+ public net.minecraft.world.phys.AABB getAxisForFluidCheck() {
+ // Stops squids from floating just over the water
+ return super.getAxisForFluidCheck().offsetY(level().purpurConfig.squidOffsetWaterCheck);
+ }
+ // Purpur end - Stop squids floating on top of water
+
+ // Purpur start - Flying squids! Oh my!
+ public boolean canFly() {
+ return this.level().purpurConfig.squidsCanFly;
+ }
+
+ @Override
+ public boolean isInWater() {
+ return this.wasTouchingWater || canFly();
+ }
+ // Purpur end - Flying squids! Oh my!
+
@Override
protected void registerGoals() {
this.goalSelector.addGoal(0, new Squid.SquidRandomMovementGoal(this));
@@ -128,6 +147,7 @@ public class Squid extends AgeableWaterCreature {
}
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 {
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);
}

View File

@@ -1,176 +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/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;
};
+ // Purpur start - Configurable chance for wolves to spawn rabid
+ private boolean isRabid = false;
+ private static final TargetingConditions.Selector RABID_PREDICATE = (entity, ignored) -> entity instanceof net.minecraft.server.level.ServerPlayer || entity instanceof net.minecraft.world.entity.Mob;
+ private final net.minecraft.world.entity.ai.goal.Goal PATHFINDER_VANILLA = new NonTameRandomTargetGoal<>(this, Animal.class, false, PREY_SELECTOR);
+ private final net.minecraft.world.entity.ai.goal.Goal PATHFINDER_RABID = new NonTameRandomTargetGoal<>(this, LivingEntity.class, false, RABID_PREDICATE);
+ private static final class AvoidRabidWolfGoal extends AvoidEntityGoal<Wolf> {
+ private final Wolf wolf;
+
+ public AvoidRabidWolfGoal(Wolf wolf, float distance, double minSpeed, double maxSpeed) {
+ super(wolf, Wolf.class, distance, minSpeed, maxSpeed);
+ this.wolf = wolf;
+ }
+
+ @Override
+ public boolean canUse() {
+ return super.canUse() && !this.wolf.isRabid() && this.toAvoid != null && this.toAvoid.isRabid(); // wolves which are not rabid run away from rabid wolves
+ }
+
+ @Override
+ public void start() {
+ this.wolf.setTarget(null);
+ super.start();
+ }
+
+ @Override
+ public void tick() {
+ this.wolf.setTarget(null);
+ super.tick();
+ }
+ }
+ // Purpur end - Configurable chance for wolves to spawn rabid
private static final float START_HEALTH = 8.0F;
private static final float TAME_HEALTH = 40.0F;
private static final float ARMOR_REPAIR_UNIT = 0.125F;
@@ -121,12 +152,47 @@ public class Wolf extends TamableAnimal implements NeutralMob {
this.setPathfindingMalus(PathType.DANGER_POWDER_SNOW, -1.0F);
}
+ // Purpur start - Configurable chance for wolves to spawn rabid
+ public boolean isRabid() {
+ return this.isRabid;
+ }
+
+ public void setRabid(boolean isRabid) {
+ this.isRabid = isRabid;
+ updatePathfinders(true);
+ }
+
+ public void updatePathfinders(boolean modifyEffects) {
+ this.targetSelector.removeGoal(PATHFINDER_VANILLA);
+ this.targetSelector.removeGoal(PATHFINDER_RABID);
+ if (this.isRabid) {
+ this.setOwnerReference(null);
+ setTame(false, true);
+ this.targetSelector.addGoal(5, PATHFINDER_RABID);
+ if (modifyEffects) this.addEffect(new net.minecraft.world.effect.MobEffectInstance(net.minecraft.world.effect.MobEffects.NAUSEA, 1200));
+ } else {
+ this.targetSelector.addGoal(5, PATHFINDER_VANILLA);
+ this.stopBeingAngry();
+ if (modifyEffects) this.removeEffect(net.minecraft.world.effect.MobEffects.NAUSEA);
+ }
+ }
+ // Purpur end - Configurable chance for wolves to spawn rabid
+
+ // Purpur start - Configurable default collar color
+ @Override
+ public void tame(Player player) {
+ setCollarColor(level().purpurConfig.wolfDefaultCollarColor);
+ super.tame(player);
+ }
+ // Purpur end - Configurable default collar color
+
@Override
protected void registerGoals() {
this.goalSelector.addGoal(1, new FloatGoal(this));
this.goalSelector.addGoal(1, new TamableAnimal.TamableAnimalPanicGoal(1.5, DamageTypeTags.PANIC_ENVIRONMENTAL_CAUSES));
this.goalSelector.addGoal(2, new SitWhenOrderedToGoal(this));
this.goalSelector.addGoal(3, new Wolf.WolfAvoidEntityGoal<>(this, Llama.class, 24.0F, 1.5, 1.5));
+ this.goalSelector.addGoal(3, new AvoidRabidWolfGoal(this, 24.0F, 1.5D, 1.5D)); // Purpur - Configurable chance for wolves to spawn rabid
this.goalSelector.addGoal(4, new LeapAtTargetGoal(this, 0.4F));
this.goalSelector.addGoal(5, new MeleeAttackGoal(this, 1.0, true));
this.goalSelector.addGoal(6, new FollowOwnerGoal(this, 1.0, 10.0F, 2.0F));
@@ -139,7 +205,7 @@ public class Wolf extends TamableAnimal implements NeutralMob {
this.targetSelector.addGoal(2, new OwnerHurtTargetGoal(this));
this.targetSelector.addGoal(3, new HurtByTargetGoal(this).setAlertOthers());
this.targetSelector.addGoal(4, new NearestAttackableTargetGoal<>(this, Player.class, 10, true, false, this::isAngryAt));
- this.targetSelector.addGoal(5, new NonTameRandomTargetGoal<>(this, Animal.class, false, PREY_SELECTOR));
+ //this.targetSelector.addGoal(5, new NonTameRandomTargetGoal<>(this, Animal.class, false, PREY_SELECTOR)); // Purpur - Configurable chance for wolves to spawn rabid - moved to updatePathfinders()
this.targetSelector.addGoal(6, new NonTameRandomTargetGoal<>(this, Turtle.class, false, Turtle.BABY_ON_LAND_SELECTOR));
this.targetSelector.addGoal(7, new NearestAttackableTargetGoal<>(this, AbstractSkeleton.class, false));
this.targetSelector.addGoal(8, new ResetUniversalAngerTargetGoal<>(this, true));
@@ -229,6 +295,7 @@ public class Wolf extends TamableAnimal implements NeutralMob {
protected void addAdditionalSaveData(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 {
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));
+ // Purpur start - Configurable chance for wolves to spawn rabid
+ this.isRabid = input.getBooleanOr("Purpur.IsRabid", false);
+ this.updatePathfinders(false);
+ // 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 {
}
this.setSoundVariant(WolfSoundVariants.pickRandomSoundVariant(this.registryAccess(), level.getRandom()));
+ // Purpur start - Configurable chance for wolves to spawn rabid
+ this.isRabid = level.getLevel().purpurConfig.wolfNaturalRabid > 0.0D && random.nextDouble() <= level.getLevel().purpurConfig.wolfNaturalRabid;
+ this.updatePathfinders(false);
+ // Purpur end - Configurable chance for wolves to spawn rabid
return super.finalizeSpawn(level, difficulty, spawnReason, spawnGroupData);
}
@@ -316,6 +391,11 @@ public class Wolf extends TamableAnimal implements NeutralMob {
public void tick() {
super.tick();
if (this.isAlive()) {
+ // Purpur start - Configurable chance for wolves to spawn rabid
+ if (this.age % 300 == 0 && this.isRabid()) {
+ this.addEffect(new net.minecraft.world.effect.MobEffectInstance(net.minecraft.world.effect.MobEffects.NAUSEA, 400));
+ }
+ // Purpur end - Configurable chance for wolves to spawn rabid
this.interestedAngleO = this.interestedAngle;
if (this.isInterested()) {
this.interestedAngle = this.interestedAngle + (1.0F - this.interestedAngle) * 0.4F;
@@ -517,13 +597,27 @@ public class Wolf extends TamableAnimal implements NeutralMob {
itemInHand.consume(1, player);
this.tryToTame(player);
return InteractionResult.SUCCESS_SERVER;
+ // Purpur start - Configurable chance for wolves to spawn rabid
+ } else if (this.level().purpurConfig.wolfMilkCuresRabies && itemInHand.getItem() == Items.MILK_BUCKET && this.isRabid()) {
+ if (!player.isCreative()) {
+ player.setItemInHand(hand, new ItemStack(Items.BUCKET));
+ }
+ this.setRabid(false);
+ for (int i = 0; i < 10; ++i) {
+ ((ServerLevel) level()).sendParticlesSource(((ServerLevel) level()).players(), null, ParticleTypes.HAPPY_VILLAGER,
+ false, true,
+ getX() + random.nextFloat(), getY() + (random.nextFloat() * 1.5), getZ() + random.nextFloat(), 1,
+ random.nextGaussian() * 0.05D, random.nextGaussian() * 0.05D, random.nextGaussian() * 0.05D, 0);
+ }
+ return InteractionResult.SUCCESS_SERVER;
+ // Purpur end - Configurable chance for wolves to spawn rabid
}
return super.mobInteract(player, hand);
}
private void tryToTame(Player player) {
- if (this.random.nextInt(3) == 0 && !org.bukkit.craftbukkit.event.CraftEventFactory.callEntityTameEvent(this, player).isCancelled()) { // CraftBukkit - added event call
+ 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);
this.navigation.stop();
this.setTarget(null);

View File

@@ -1,64 +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/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 {
this.setPos(x, y, z);
}
+ // Purpur start - End crystal explosion options
+ public boolean shouldExplode() {
+ return showsBottom() ? level().purpurConfig.basedEndCrystalExplode : level().purpurConfig.baselessEndCrystalExplode;
+ }
+
+ public float getExplosionPower() {
+ return (float) (showsBottom() ? level().purpurConfig.basedEndCrystalExplosionPower : level().purpurConfig.baselessEndCrystalExplosionPower);
+ }
+
+ public boolean hasExplosionFire() {
+ return showsBottom() ? level().purpurConfig.basedEndCrystalExplosionFire : level().purpurConfig.baselessEndCrystalExplosionFire;
+ }
+
+ public Level.ExplosionInteraction getExplosionEffect() {
+ return showsBottom() ? level().purpurConfig.basedEndCrystalExplosionEffect : level().purpurConfig.baselessEndCrystalExplosionEffect;
+ }
+ // Purpur end - End crystal explosion options
+
@Override
protected Entity.MovementEmission getMovementEmission() {
return Entity.MovementEmission.NONE;
@@ -75,6 +93,8 @@ public class EndCrystal extends Entity {
}
}
// Paper end - Fix invulnerable end crystals
+ if (this.level().purpurConfig.endCrystalCramming > 0 && this.level().getEntitiesOfClass(EndCrystal.class, getBoundingBox()).size() > this.level().purpurConfig.endCrystalCramming) this.hurt(this.damageSources().cramming(), 6.0F); // Purpur - End Crystal Cramming
+
}
@Override
@@ -115,15 +135,17 @@ public class EndCrystal extends Entity {
}
// CraftBukkit end
if (!damageSource.is(DamageTypeTags.IS_EXPLOSION)) {
+ if (shouldExplode()) {// Purpur - End crystal explosion options
DamageSource damageSource1 = damageSource.getEntity() != null ? this.damageSources().explosion(this, damageSource.getEntity()) : null;
// CraftBukkit start
- org.bukkit.event.entity.ExplosionPrimeEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callExplosionPrimeEvent(this, 6.0F, false);
+ org.bukkit.event.entity.ExplosionPrimeEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callExplosionPrimeEvent(this, getExplosionPower(), hasExplosionFire()); // Purpur - End crystal explosion options
if (event.isCancelled()) {
return false;
}
this.remove(Entity.RemovalReason.KILLED, org.bukkit.event.entity.EntityRemoveEvent.Cause.EXPLODE); // Paper - add Bukkit remove cause
- level.explode(this, 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
+ } else this.unsetRemoved(); // Purpur - End crystal explosion options
} else {
this.remove(Entity.RemovalReason.KILLED, org.bukkit.event.entity.EntityRemoveEvent.Cause.DEATH); // Paper - add Bukkit remove cause
// CraftBukkit end

View File

@@ -1,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,81 +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/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();
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) {
super(type, level);
@@ -88,6 +89,16 @@ public class WitherBoss extends Monster implements RangedAttackMob {
this.xpReward = 50;
}
+ // Purpur start - Summoner API
+ public java.util.@Nullable UUID getSummoner() {
+ return summoner;
+ }
+
+ public void setSummoner(java.util.@Nullable UUID summoner) {
+ this.summoner = summoner;
+ }
+ // Purpur end - Summoner API
+
@Override
protected PathNavigation createNavigation(Level level) {
FlyingPathNavigation flyingPathNavigation = new FlyingPathNavigation(this, level);
@@ -120,6 +131,7 @@ public class WitherBoss extends Monster implements RangedAttackMob {
protected void addAdditionalSaveData(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 {
if (this.hasCustomName()) {
this.bossEvent.setName(this.getDisplayName());
}
+ this.setSummoner(input.read("Purpur.Summoner", net.minecraft.core.UUIDUtil.CODEC).orElse(null)); // Purpur - Summoner API
}
@Override
@@ -272,7 +285,7 @@ public class WitherBoss extends Monster implements RangedAttackMob {
level.explode(this, this.getX(), this.getEyeY(), this.getZ(), event.getRadius(), event.getFire(), Level.ExplosionInteraction.MOB);
}
// CraftBukkit end
- if (!this.isSilent()) {
+ if (!this.isSilent() && level.purpurConfig.witherPlaySpawnSound) { // Purpur - Toggle for Wither's spawn sound
// 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 {
}
}
- if (this.tickCount % 20 == 0) {
- this.heal(1.0F, org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason.REGEN); // CraftBukkit
+ // Purpur start - Customizable wither health and healing - customizable heal rate and amount
+ if (this.tickCount % level().purpurConfig.witherHealthRegenDelay == 0) {
+ this.heal(level().purpurConfig.witherHealthRegenAmount, org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason.REGEN); // CraftBukkit
+ // Purpur end - Customizable wither health and healing
}
this.bossEvent.setProgress(this.getHealth() / this.getMaxHealth());
@@ -577,6 +592,7 @@ public class WitherBoss extends Monster implements RangedAttackMob {
@Override
protected boolean canRide(Entity entity) {
+ if (this.level().purpurConfig.witherCanRideVehicles) return this.boardingCooldown <= 0; // Purpur - Configs for if Wither/Ender Dragon can ride vehicles
return false;
}

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,73 +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/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 {
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) {
super(type, level);
@@ -159,6 +160,27 @@ public class Creeper extends Monster {
return false; // CraftBukkit
}
+ // Purpur start - Special mobs naturally spawn
+ @Override
+ public net.minecraft.world.entity.SpawnGroupData finalizeSpawn(net.minecraft.world.level.ServerLevelAccessor world, net.minecraft.world.DifficultyInstance difficulty, net.minecraft.world.entity.EntitySpawnReason spawnReason, net.minecraft.world.entity.@Nullable SpawnGroupData entityData) {
+ double chance = world.getLevel().purpurConfig.creeperChargedChance;
+ if (chance > 0D && random.nextDouble() <= chance) {
+ setPowered(true);
+ }
+ return super.finalizeSpawn(world, difficulty, spawnReason, entityData);
+ }
+ // Purpur end - Special mobs naturally spawn
+
+ // Purpur start - Config to make Creepers explode on death
+ @Override
+ protected org.bukkit.event.entity.EntityDeathEvent dropAllDeathLoot(ServerLevel world, DamageSource damageSource) {
+ if (!this.exploding && this.level().purpurConfig.creeperExplodeWhenKilled && damageSource.getEntity() instanceof net.minecraft.server.level.ServerPlayer) {
+ this.explodeCreeper();
+ }
+ return super.dropAllDeathLoot(world, damageSource);
+ }
+ // Purpur end - Config to make Creepers explode on death
+
@Override
public SoundEvent getHurtSound(DamageSource damageSource) {
return SoundEvents.CREEPER_HURT;
@@ -243,14 +265,16 @@ public class Creeper extends Monster {
}
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
// 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
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
this.spawnLingeringCloud();
this.triggerOnDeathMobEffects(serverLevel, 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 {
}
// CraftBukkit end
}
+ this.exploding = false; // Purpur - Config to make Creepers explode on death
}
private void spawnLingeringCloud() {

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,47 +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/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 {
}
public static boolean isDarkEnoughToSpawn(ServerLevelAccessor level, BlockPos pos, 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
if (level.getBrightness(LightLayer.SKY, pos) > random.nextInt(32)) {
return false;
} else {
@@ -109,6 +114,11 @@ public abstract class Monster extends PathfinderMob implements Enemy {
public static boolean checkAnyLightMonsterSpawnRules(
EntityType<? extends Monster> entityType, LevelAccessor level, EntitySpawnReason spawnReason, BlockPos pos, 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);
}
@@ -146,4 +156,12 @@ public abstract class Monster extends PathfinderMob implements Enemy {
return ItemStack.EMPTY;
}
}
+
+ // Purpur start - Config to disable hostile mob spawn on ice
+ public static boolean canSpawnInBlueAndPackedIce(LevelAccessor level, BlockPos pos) {
+ net.minecraft.world.level.block.state.BlockState spawnBlock = level.getBlockState(pos.below());
+
+ return (!level.getMinecraftWorld().purpurConfig.mobsSpawnOnPackedIce && spawnBlock.is(net.minecraft.world.level.block.Blocks.PACKED_ICE)) || (!level.getMinecraftWorld().purpurConfig.mobsSpawnOnBlueIce && spawnBlock.is(net.minecraft.world.level.block.Blocks.BLUE_ICE));
+ }
+ // Purpur end - Config to disable hostile mob spawn on ice
}

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,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/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 {
protected void registerGoals() {
super.registerGoals();
this.goalSelector.addGoal(0, new FloatGoal(this));
+ if (level().purpurConfig.ravagerAvoidRabbits) this.goalSelector.addGoal(3, new net.minecraft.world.entity.ai.goal.AvoidEntityGoal<>(this, net.minecraft.world.entity.animal.rabbit.Rabbit.class, 6.0F, 1.0D, 1.2D)); // Purpur - option to make ravagers afraid of rabbits
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 {
)) {
BlockState blockState = serverLevel.getBlockState(blockPos);
Block block = blockState.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
continue;

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,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/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 {
@Override
public InteractionResult mobInteract(Player player, InteractionHand hand) {
boolean isFood = this.isFood(player.getItemInHand(hand));
+ // Purpur start
+ if (level().purpurConfig.striderGiveSaddleBack && 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
if (!isFood && this.isSaddled() && !this.isVehicle() && !player.isSecondaryUseActive()) {
if (!this.level().isClientSide()) {
player.startRiding(this);

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/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 {
RandomSource random = level.getRandom();
this.populateDefaultEquipmentSlots(random, difficulty);
this.populateDefaultEquipmentEnchantments(level, random, difficulty);
+ // Purpur start - Special mobs naturally spawn
+ if (level().purpurConfig.vindicatorJohnnySpawnChance > 0D && random.nextDouble() <= level().purpurConfig.vindicatorJohnnySpawnChance) {
+ setCustomName(Component.translatable("Johnny"));
+ }
+ // Purpur end - Special mobs naturally spawn
return spawnGroupData1;
}

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,28 +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/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
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
- if (this.getItemBySlot(EquipmentSlot.HEAD).isEmpty() && SpecialDates.isHalloween() && random.nextFloat() < 0.25F) {
+ if (this.getItemBySlot(EquipmentSlot.HEAD).isEmpty() && (level.getLevel().purpurConfig.forceHalloweenSeason || SpecialDates.isHalloween()) && random.nextFloat() < this.level().purpurConfig.chanceHeadHalloweenOnEntity) { // Purpur - Halloween options and optimizations
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);
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
);
// Paper start - call EntityShootBowEvent

View File

@@ -1,35 +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/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 {
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)));
- 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
+ @Override
+ public boolean canUse() {
+ return (level().purpurConfig.zombieAggressiveTowardsVillagerWhenLagging || !level().getServer().server.isLagging()) && super.canUse();
+ }
+
+ @Override
+ public boolean canContinueToUse() {
+ return (level().purpurConfig.zombieAggressiveTowardsVillagerWhenLagging || !level().getServer().server.isLagging()) && super.canContinueToUse();
+ }
+ });
+ // Purpur end - Add option to disable zombie aggressiveness towards villagers
this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, IronGolem.class, true));
this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, Axolotl.class, true, false));
this.targetSelector.addGoal(5, new NearestAttackableTargetGoal<>(this, Turtle.class, 10, true, false, Turtle.BABY_ON_LAND_SELECTOR));

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/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)) {
- 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);
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
}
return InteractionResult.SUCCESS_SERVER;

View File

@@ -1,149 +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/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
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) {
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));
}
+ // Purpur start - Allow leashing villagers
+ @Override
+ public boolean canBeLeashed() {
+ return level().purpurConfig.villagerCanBeLeashed;
+ }
+ // Purpur end - Allow leashing villagers
+
+ // Purpur start - Lobotomize stuck villagers
+ private boolean checkLobotomized() {
+ int interval = this.level().purpurConfig.villagerLobotomizeCheckInterval;
+ boolean shouldCheckForTradeLocked = this.level().purpurConfig.villagerLobotomizeWaitUntilTradeLocked;
+ if (this.notLobotomizedCount > 3) {
+ // check half as often if not lobotomized for the last 3+ consecutive checks
+ interval *= 2;
+ }
+ if (this.level().getGameTime() % interval == 0) {
+ // offset Y for short blocks like dirt_path/farmland
+ this.isLobotomized = !(shouldCheckForTradeLocked && this.getVillagerXp() == 0) && !canTravelFrom(BlockPos.containing(this.position().x, this.getBoundingBox().minY + 0.0625D, this.position().z));
+
+ if (this.isLobotomized) {
+ this.notLobotomizedCount = 0;
+ } else {
+ this.notLobotomizedCount++;
+ }
+ }
+ return this.isLobotomized;
+ }
+
+ private boolean canTravelFrom(BlockPos pos) {
+ return canTravelTo(pos.east()) || canTravelTo(pos.west()) || canTravelTo(pos.north()) || canTravelTo(pos.south());
+ }
+
+ private boolean canTravelTo(BlockPos pos) {
+ net.minecraft.world.level.block.state.BlockState state = this.level().getBlockStateIfLoaded(pos);
+ if (state == null) {
+ // chunk not loaded
+ return false;
+ }
+ net.minecraft.world.level.block.Block bottom = state.getBlock();
+ if (bottom instanceof net.minecraft.world.level.block.FenceBlock ||
+ bottom instanceof net.minecraft.world.level.block.FenceGateBlock ||
+ bottom instanceof net.minecraft.world.level.block.WallBlock) {
+ // bottom block is too tall to get over
+ return false;
+ }
+ net.minecraft.world.level.block.Block top = level().getBlockState(pos.above()).getBlock();
+ // only if both blocks have no collision
+ return !bottom.hasCollision && !top.hasCollision;
+ }
+ // Purpur end - Lobotomize stuck villagers
+
@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
+ // Purpur start - Lobotomize stuck villagers
+ if (this.level().purpurConfig.villagerLobotomizeEnabled) {
+ // treat as inactive if lobotomized
+ inactive = inactive || checkLobotomized();
+ } else {
+ this.isLobotomized = false;
+ }
+ if (!inactive) {
+ this.getBrain().tick(level, this); // Paper - EAR 2
+ }
+ else if (this.isLobotomized && shouldRestock(level)) restock();
+ // Purpur end - Lobotomize stuck villagers
profilerFiller.pop();
if (this.assignProfessionWhenSpawned) {
this.assignProfessionWhenSpawned = false;
@@ -369,6 +433,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler
return InteractionResult.CONSUME;
}
+ if (this.level().purpurConfig.villagerAllowTrading) // Purpur - Add config for villager trading
this.startTrading(player);
}
@@ -500,7 +565,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler
public void updateDemand() {
for (MerchantOffer merchantOffer : this.getOffers()) {
- merchantOffer.updateDemand();
+ merchantOffer.updateDemand(this.level().purpurConfig.villagerMinimumDemand); // Purpur - Configurable minimum demand for trades
}
}
@@ -692,7 +757,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler
@Override
public boolean canBreed() {
- return this.foodLevel + this.countFoodPointsInInventory() >= 12 && !this.isSleeping() && this.getAge() == 0;
+ return this.level().purpurConfig.villagerCanBreed && this.foodLevel + this.countFoodPointsInInventory() >= 12 && !this.isSleeping() && this.getAge() == 0; // Purpur - Configurable villager breeding
}
private boolean hungry() {
@@ -915,6 +980,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler
}
public void spawnGolemIfNeeded(ServerLevel level, long gameTime, int minVillagerAmount) {
+ 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);

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,204 +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/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;
import org.jspecify.annotations.Nullable;
import org.slf4j.Logger;
+// Purpur start - Anvil API
+import net.minecraft.network.protocol.game.ClientboundContainerSetDataPacket;
+import net.minecraft.network.protocol.game.ClientboundContainerSetSlotPacket;
+import net.minecraft.server.level.ServerPlayer;
+// Purpur end - Anvil API
+
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 {
private org.bukkit.craftbukkit.inventory.view.CraftAnvilView bukkitEntity;
// CraftBukkit end
public boolean bypassEnchantmentLevelRestriction = false; // Paper - bypass anvil level restrictions
+ // Purpur start - Anvil API
+ public boolean bypassCost = false;
+ 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 {
@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
}
@Override
protected void onTake(Player player, ItemStack stack) {
+ // Purpur start - Anvil API
+ ItemStack itemstack = this.activeQuickItem != null ? this.activeQuickItem : stack;
+ 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()) {
+ if (this.bypassCost) ((ServerPlayer) player).lastSentExp = -1; else // Purpur - Anvil API
player.giveExperienceLevels(-this.cost.get());
}
@@ -134,13 +149,19 @@ public class AnvilMenu extends ItemCombinerMenu {
@Override
public void createResult() {
+ // Purpur start - Anvil API
+ this.bypassCost = false;
+ this.canDoUnsafeEnchants = false;
+ 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);
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);
+ // 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 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;
}
+ 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;
+ 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);
+ canEnchant1 = true;
+ }
+ // Purpur end - Config to allow unsafe enchants
i++;
}
}
+ mutable.removeIf(removedEnchantments::contains); // Purpur - Config to allow unsafe enchants
- if (!canEnchant) {
+ if (!canEnchant || !canEnchant1) { // Purpur - Config to allow unsafe enchants
flag1 = 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();
}
@@ -243,6 +275,54 @@ public class AnvilMenu extends ItemCombinerMenu {
if (!this.itemName.equals(item.getHoverName().getString())) {
i1 = 1;
i += i1;
+ // Purpur start - Allow anvil colors
+ if (this.player != null) {
+ org.bukkit.craftbukkit.entity.CraftHumanEntity player = this.player.getBukkitEntity();
+ String name = this.itemName;
+ boolean removeItalics = false;
+ if (player.hasPermission("purpur.anvil.remove_italics")) {
+ if (name.startsWith("&r")) {
+ name = name.substring(2);
+ removeItalics = true;
+ } else if (name.startsWith("<r>")) {
+ name = name.substring(3);
+ removeItalics = true;
+ } else if (name.startsWith("<reset>")) {
+ name = name.substring(7);
+ removeItalics = true;
+ }
+ }
+ if (this.player.level().purpurConfig.anvilAllowColors) {
+ if (player.hasPermission("purpur.anvil.color")) {
+ java.util.regex.Matcher matcher = java.util.regex.Pattern.compile("(?i)&([0-9a-fr])").matcher(name);
+ while (matcher.find()) {
+ String match = matcher.group(1);
+ name = name.replace("&" + match, "\u00a7" + match.toLowerCase(java.util.Locale.ROOT));
+ }
+ //name = name.replaceAll("(?i)&([0-9a-fr])", "\u00a7$1");
+ }
+ if (player.hasPermission("purpur.anvil.format")) {
+ java.util.regex.Matcher matcher = java.util.regex.Pattern.compile("(?i)&([k-or])").matcher(name);
+ while (matcher.find()) {
+ String match = matcher.group(1);
+ name = name.replace("&" + match, "\u00a7" + match.toLowerCase(java.util.Locale.ROOT));
+ }
+ //name = name.replaceAll("(?i)&([l-or])", "\u00a7$1");
+ }
+ }
+ net.kyori.adventure.text.Component component;
+ if (this.player.level().purpurConfig.anvilColorsUseMiniMessage && player.hasPermission("purpur.anvil.minimessage")) {
+ component = net.kyori.adventure.text.minimessage.MiniMessage.miniMessage().deserialize(org.bukkit.ChatColor.stripColor(name));
+ } else {
+ component = net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(name);
+ }
+ 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));
+ }
+ else
+ // Purpur end - Allow anvil colors
itemStack.set(DataComponents.CUSTOM_NAME, Component.literal(this.itemName));
}
} else if (item.has(DataComponents.CUSTOM_NAME)) {
@@ -267,6 +347,12 @@ public class AnvilMenu extends ItemCombinerMenu {
this.onlyRenaming = true;
}
+ // Purpur start - Anvil API
+ if (this.bypassCost && this.cost.get() >= this.maximumRepairCost) {
+ this.cost.set(this.maximumRepairCost - 1);
+ }
+ // Purpur end - Anvil API
+
if (this.cost.get() >= this.maximumRepairCost && !this.player.hasInfiniteMaterials()) { // CraftBukkit
itemStack = ItemStack.EMPTY;
}
@@ -287,6 +373,13 @@ public class AnvilMenu extends ItemCombinerMenu {
org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareAnvilEvent(this.getBukkitView(), itemStack); // CraftBukkit
this.broadcastChanges();
+
+ // Purpur start - Anvil API
+ if ((this.canDoUnsafeEnchants || org.purpurmc.purpur.PurpurConfig.allowInapplicableEnchants || org.purpurmc.purpur.PurpurConfig.allowIncompatibleEnchants) && itemStack != ItemStack.EMPTY) { // Purpur - Config to allow unsafe enchants
+ ((ServerPlayer) this.player).connection.send(new ClientboundContainerSetSlotPacket(this.containerId, this.incrementStateId(), 2, itemStack));
+ ((ServerPlayer) this.player).connection.send(new ClientboundContainerSetDataPacket(this.containerId, 0, this.cost.get()));
+ }
+ // Purpur end - Anvil API
} 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 {
}
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 boolean setItemName(String itemName) {

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,59 +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/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 {
return access.getLocation();
}
// CraftBukkit end
+
+ // Purpur start - Enchantment Table Persists Lapis
+ @Override
+ public void onClose(org.bukkit.craftbukkit.entity.CraftHumanEntity who) {
+ super.onClose(who);
+
+ if (who.getHandle().level().purpurConfig.enchantmentTableLapisPersists) {
+ access.execute((level, pos) -> {
+ net.minecraft.world.level.block.entity.BlockEntity blockEntity = level.getBlockEntity(pos);
+ if (blockEntity instanceof net.minecraft.world.level.block.entity.EnchantingTableBlockEntity enchantmentTable) {
+ enchantmentTable.setLapis(this.getItem(1).getCount());
+ }
+ });
+ }
+ }
+ // Purpur end - Enchantment Table Persists Lapis
};
// Paper end - Add missing InventoryHolders
this.access = access;
@@ -83,6 +99,16 @@ public class EnchantmentMenu extends AbstractContainerMenu {
return EnchantmentMenu.EMPTY_SLOT_LAPIS_LAZULI;
}
});
+ // Purpur start - Enchantment Table Persists Lapis
+ access.execute((level, pos) -> {
+ if (level.purpurConfig.enchantmentTableLapisPersists) {
+ net.minecraft.world.level.block.entity.BlockEntity blockEntity = level.getBlockEntity(pos);
+ if (blockEntity instanceof net.minecraft.world.level.block.entity.EnchantingTableBlockEntity enchantmentTable) {
+ this.getSlot(1).set(new ItemStack(Items.LAPIS_LAZULI, enchantmentTable.getLapis()));
+ }
+ }
+ });
+ // Purpur end - Enchantment Table Persists Lapis
this.addStandardInventorySlots(playerInventory, 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 {
@Override
public void removed(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
}
@Override

View File

@@ -1,146 +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/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 {
@Override
public void onTake(Player player, ItemStack stack) {
access.execute((level, blockPos) -> {
+ 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));
event.callEvent();
- ExperienceOrb.awardWithDirection((ServerLevel) level, Vec3.atCenterOf(blockPos), 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
// 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)) {
+ if (!org.purpurmc.purpur.PurpurConfig.grindstoneIgnoredEnchants.contains(holder.value())) { // Purpur - Config for grindstones
i += holder.value().getMinCost(intValue);
}
}
@@ -203,15 +205,75 @@ public class GrindstoneMenu extends AbstractContainerMenu {
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());
}
}
});
}
+ // Purpur start - Config for grindstones
+ private java.util.List<net.minecraft.core.component.DataComponentType<?>> GRINDSTONE_REMOVE_ATTRIBUTES_REMOVAL_LIST = java.util.List.of(
+ // DataComponents.MAX_STACK_SIZE,
+ // DataComponents.DAMAGE,
+ // DataComponents.BLOCK_STATE,
+ DataComponents.CUSTOM_DATA,
+ // DataComponents.MAX_DAMAGE,
+ // DataComponents.UNBREAKABLE,
+ // DataComponents.CUSTOM_NAME,
+ // DataComponents.ITEM_NAME,
+ // DataComponents.LORE,
+ // DataComponents.RARITY,
+ // DataComponents.ENCHANTMENTS,
+ // DataComponents.CAN_PLACE_ON,
+ // DataComponents.CAN_BREAK,
+ DataComponents.ATTRIBUTE_MODIFIERS,
+ DataComponents.CUSTOM_MODEL_DATA,
+ // DataComponents.HIDE_ADDITIONAL_TOOLTIP,
+ // DataComponents.HIDE_TOOLTIP,
+ // DataComponents.REPAIR_COST,
+ // DataComponents.CREATIVE_SLOT_LOCK,
+ // DataComponents.ENCHANTMENT_GLINT_OVERRIDE,
+ // DataComponents.INTANGIBLE_PROJECTILE,
+ // DataComponents.FOOD,
+ // DataComponents.FIRE_RESISTANT,
+ // DataComponents.TOOL,
+ // DataComponents.STORED_ENCHANTMENTS,
+ DataComponents.DYED_COLOR,
+ // DataComponents.MAP_COLOR,
+ // DataComponents.MAP_ID,
+ // DataComponents.MAP_DECORATIONS,
+ // DataComponents.MAP_POST_PROCESSING,
+ // DataComponents.CHARGED_PROJECTILES,
+ // DataComponents.BUNDLE_CONTENTS,
+ // DataComponents.POTION_CONTENTS,
+ DataComponents.SUSPICIOUS_STEW_EFFECTS
+ // DataComponents.WRITABLE_BOOK_CONTENT,
+ // DataComponents.WRITTEN_BOOK_CONTENT,
+ // DataComponents.TRIM,
+ // DataComponents.DEBUG_STICK_STATE,
+ // DataComponents.ENTITY_DATA,
+ // DataComponents.BUCKET_ENTITY_DATA,
+ // DataComponents.BLOCK_ENTITY_DATA,
+ // DataComponents.INSTRUMENT,
+ // DataComponents.OMINOUS_BOTTLE_AMPLIFIER,
+ // DataComponents.RECIPES,
+ // DataComponents.LODESTONE_TRACKER,
+ // DataComponents.FIREWORK_EXPLOSION,
+ // DataComponents.FIREWORKS,
+ // DataComponents.PROFILE,
+ // DataComponents.NOTE_BLOCK_SOUND,
+ // DataComponents.BANNER_PATTERNS,
+ // DataComponents.BASE_COLOR,
+ // DataComponents.POT_DECORATIONS,
+ // DataComponents.CONTAINER,
+ // DataComponents.BEES,
+ // DataComponents.LOCK,
+ // DataComponents.CONTAINER_LOOT,
+ );
+ // 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()) {
item = item.transmuteCopy(Items.BOOK);
}
@@ -223,6 +285,23 @@ public class GrindstoneMenu extends AbstractContainerMenu {
}
item.set(DataComponents.REPAIR_COST, i);
+
+ // Purpur start - Config for grindstones
+ net.minecraft.core.component.DataComponentPatch.Builder builder = net.minecraft.core.component.DataComponentPatch.builder();
+ if (org.purpurmc.purpur.PurpurConfig.grindstoneRemoveAttributes) {
+ item.getComponents().forEach(typedDataComponent -> {
+ if (GRINDSTONE_REMOVE_ATTRIBUTES_REMOVAL_LIST.contains(typedDataComponent.type())) {
+ builder.remove(typedDataComponent.type());
+ }
+ });
+ }
+ if (org.purpurmc.purpur.PurpurConfig.grindstoneRemoveDisplay) {
+ builder.remove(DataComponents.CUSTOM_NAME);
+ builder.remove(DataComponents.LORE);
+ }
+ item.applyComponents(builder.build());
+ // Purpur end - Config for grindstones
+
return item;
}
@@ -279,7 +358,9 @@ public class GrindstoneMenu extends AbstractContainerMenu {
return ItemStack.EMPTY;
}
+ this.activeQuickItem = itemStack; // Purpur - Grindstone API
slot.onTake(player, item);
+ this.activeQuickItem = null; // Purpur - Grindstone API
}
return itemStack;

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,57 +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/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) {
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
&& 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 {
return;
}
+ if (level.purpurConfig.farmlandTramplingDisabled) return; // Purpur - Farmland trampling changes
+ if (level.purpurConfig.farmlandTramplingOnlyPlayers && !(entity instanceof Player)) return; // Purpur - Farmland trampling changes
+
+ // Purpur start - Ability to re-add farmland mechanics from Alpha
+ if (level.purpurConfig.farmlandAlpha) {
+ Block block = level.getBlockState(pos.below()).getBlock();
+ if (block instanceof FenceBlock || block instanceof WallBlock) {
+ return;
+ }
+ }
+ // Purpur end - Ability to re-add farmland mechanics from Alpha
+
+ // Purpur start - Farmland trampling changes
+ if (level.purpurConfig.farmlandTramplingFeatherFalling) {
+ net.minecraft.world.item.ItemStack bootsItem = ((net.minecraft.world.entity.LivingEntity) entity).getItemBySlot(net.minecraft.world.entity.EquipmentSlot.FEET);
+
+ if (bootsItem != net.minecraft.world.item.ItemStack.EMPTY && net.minecraft.world.item.enchantment.EnchantmentHelper.getItemEnchantmentLevel(net.minecraft.world.item.enchantment.Enchantments.FEATHER_FALLING, bootsItem) >= (int) entity.fallDistance) {
+ return;
+ }
+ }
+ // Purpur end - Farmland trampling changes
+
if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(entity, pos, Blocks.DIRT.defaultBlockState())) {
return;
}
@@ -177,7 +199,7 @@ public class FarmBlock extends Block {
}
}
- return false;
+ return ((ServerLevel) level).purpurConfig.farmlandGetsMoistFromBelow && level.getFluidState(pos.relative(Direction.DOWN)).is(FluidTags.WATER); // Purpur - Allow soil to moisten from water directly under it
// Paper end - Perf: remove abstract block iteration
}

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,64 +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/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 {
"leash",
"UUID"
);
- public static final int MAX_OCCUPANTS = 3;
+ public static final int MAX_OCCUPANTS = org.purpurmc.purpur.PurpurConfig.beeInsideBeeHive; // Purpur - Config to change max number of bees
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;
}
+ // Purpur start - Stored Bee API
+ public List<Entity> releaseBee(BlockState iblockdata, BeehiveBlockEntity.BeeData data, BeehiveBlockEntity.BeeReleaseStatus tileentitybeehive_releasestatus, boolean force) {
+ List<Entity> list = Lists.newArrayList();
+
+ BeehiveBlockEntity.releaseOccupant(this.level, this.worldPosition, iblockdata, data.occupant, list, tileentitybeehive_releasestatus, this.savedFlowerPos, force);
+
+ if (!list.isEmpty()) {
+ stored.remove(data);
+
+ super.setChanged();
+ }
+
+ return list;
+ }
+ // Purpur end - Stored Bee API
+
@VisibleForDebug
public int getOccupantCount() {
return this.stored.size();
}
+ // Purpur start - Stored Bee API
+ public List<BeeData> getStored() {
+ return stored;
+ }
+ // Purpur end - Stored Bee API
+
// Paper start - Add EntityBlockStorage clearEntities
public void clearBees() {
this.stored.clear();
@@ -398,8 +420,8 @@ public class BeehiveBlockEntity extends BlockEntity {
registrar.register(DebugSubscriptions.BEE_HIVES, () -> DebugHiveInfo.pack(this));
}
- static class BeeData {
- private final BeehiveBlockEntity.Occupant occupant;
+ public static class BeeData { // Purpur - make public - Stored Bee API
+ public final BeehiveBlockEntity.Occupant occupant; // Purpur - make public - Stored Bee API
private int exitTickCounter; // Paper - Fix bees aging inside hives; separate counter for checking if bee should exit to reduce exit attempts
private int ticksInHive;

View File

@@ -1,50 +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/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 {
input.read("PublicBukkitValues", CompoundTag.CODEC)
.ifPresent(this.persistentDataContainer::putAll);
// Paper end - read persistent data container
+
+
+ this.persistentLore = input.read("Purpur.persistentLore", net.minecraft.world.item.component.ItemLore.CODEC).orElse(null); // Purpur - Persistent BlockEntity Lore and DisplayName
+
}
public final void loadWithComponents(ValueInput input) {
@@ -117,6 +121,11 @@ public abstract class BlockEntity implements DebugValueSource {
}
protected void saveAdditional(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);
+ }
+ // Purpur end - Persistent BlockEntity Lore and DisplayName
}
public final CompoundTag saveWithFullMetadata(HolderLookup.Provider registries) {
@@ -402,4 +411,16 @@ public abstract class BlockEntity implements DebugValueSource {
return this.blockEntity.getNameForReporting() + "@" + this.blockEntity.getBlockPos();
}
}
+
+ // Purpur start - Persistent BlockEntity Lore and DisplayName
+ private net.minecraft.world.item.component.@Nullable ItemLore persistentLore = null;
+
+ public void setPersistentLore(net.minecraft.world.item.component.ItemLore lore) {
+ this.persistentLore = lore;
+ }
+
+ public @org.jetbrains.annotations.Nullable net.minecraft.world.item.component.ItemLore getPersistentLore() {
+ return this.persistentLore;
+ }
+ // Purpur end - Persistent BlockEntity Lore and DisplayName
}

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,73 +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/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);
}
+ // Purpur start - Signs allow color codes
+ private Component translateColors(org.bukkit.entity.Player player, String line, Style style) {
+ if (level.purpurConfig.signAllowColors) {
+ if (player.hasPermission("purpur.sign.color")) line = line.replaceAll("(?i)&([0-9a-fr])", "\u00a7$1");
+ if (player.hasPermission("purpur.sign.style")) line = line.replaceAll("(?i)&([l-or])", "\u00a7$1");
+ if (player.hasPermission("purpur.sign.magic")) line = line.replaceAll("(?i)&([kr])", "\u00a7$1");
+
+ return io.papermc.paper.adventure.PaperAdventure.asVanilla(net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(line));
+ } else {
+ return Component.literal(line).setStyle(style);
+ }
+ }
+ // Purpur end - Signs allow color codes
+
private SignText setMessages(Player player, List<FilteredText> filteredText, SignText text, 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();
+
+ 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
} 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
);
}
}
@@ -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
}
+ // 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)) {
+ net.minecraft.world.level.storage.TagValueOutput tagValueOutput = net.minecraft.world.level.storage.TagValueOutput.createWithContext(scopedCollector, this.getLevel().registryAccess());
+ this.saveAdditional(tagValueOutput);
+
+ final Component[] lines = front ? frontText.getMessages(filtered) : backText.getMessages(filtered);
+ final String side = front ? "front_text" : "back_text";
+ net.minecraft.world.level.storage.ValueOutput sideNbt = tagValueOutput.child(side);
+ net.minecraft.world.level.storage.ValueOutput.TypedOutputList<String> messagesNbt = sideNbt.list("messages", com.mojang.serialization.Codec.STRING);
+ for (int i = 0; i < 4; i++) {
+ final net.kyori.adventure.text.Component component = io.papermc.paper.adventure.PaperAdventure.asAdventure(lines[i]);
+ final String line = net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacyAmpersand().serialize(component);
+ messagesNbt.add(line);
+ }
+ tagValueOutput.putString("PurpurEditor", "true");
+ return ClientboundBlockEntityDataPacket.create(this, (blockEntity, registryAccess) -> tagValueOutput.buildResult());
+ }
+ }
+ // Purpur end - Signs allow color codes
+
@Override
public ClientboundBlockEntityDataPacket getUpdatePacket() {
return ClientboundBlockEntityDataPacket.create(this);