all patches apply \o/

This commit is contained in:
granny
2024-06-14 16:29:04 -07:00
parent 699969ff1c
commit cfc96e0c93
44 changed files with 234 additions and 235 deletions

View File

@@ -0,0 +1,46 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Encode42 <me@encode42.dev>
Date: Mon, 4 Jul 2022 13:57:06 -0400
Subject: [PATCH] Config to not let coral die
diff --git a/src/main/java/net/minecraft/world/level/block/BaseCoralPlantTypeBlock.java b/src/main/java/net/minecraft/world/level/block/BaseCoralPlantTypeBlock.java
index ce9f189bdafec26360bfadd0f36a8bc2726e132b..d5465b48531fd4b4094874c135274abf985ee71a 100644
--- a/src/main/java/net/minecraft/world/level/block/BaseCoralPlantTypeBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/BaseCoralPlantTypeBlock.java
@@ -38,6 +38,7 @@ public abstract class BaseCoralPlantTypeBlock extends Block implements SimpleWat
}
protected static boolean scanForWater(BlockState state, BlockGetter world, BlockPos pos) {
+ if (!((net.minecraft.world.level.LevelAccessor) world).getMinecraftWorld().purpurConfig.coralDieOutsideWater) return true; // Purpur
if (state.getValue(WATERLOGGED)) {
return true;
} else {
diff --git a/src/main/java/net/minecraft/world/level/block/CoralBlock.java b/src/main/java/net/minecraft/world/level/block/CoralBlock.java
index 81fe0dea8e6e23c4a78f07fc2f9c0d68cd683f11..bff97b7d3909f2ec9e58a341b901b3741927543f 100644
--- a/src/main/java/net/minecraft/world/level/block/CoralBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/CoralBlock.java
@@ -59,6 +59,7 @@ public class CoralBlock extends Block {
}
protected boolean scanForWater(BlockGetter world, BlockPos pos) {
+ if (!((net.minecraft.world.level.LevelAccessor) world).getMinecraftWorld().purpurConfig.coralDieOutsideWater) return true; // Purpur
Direction[] aenumdirection = Direction.values();
int i = aenumdirection.length;
diff --git a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
index 6441a55bda07bacd23918a7cb74cacbfe45688ae..55d6232d50dd48080aec705512c791c86dae8c93 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
@@ -894,6 +894,11 @@ public class PurpurWorldConfig {
composterBulkProcess = getBoolean("blocks.composter.sneak-to-bulk-process", composterBulkProcess);
}
+ public boolean coralDieOutsideWater = true;
+ private void coralSettings() {
+ coralDieOutsideWater = getBoolean("blocks.coral.die-outside-water", coralDieOutsideWater);
+ }
+
public boolean dispenserApplyCursedArmor = true;
public boolean dispenserPlaceAnvils = false;
private void dispenserSettings() {

View File

@@ -0,0 +1,23 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: BillyGalbreath <blake.galbreath@gmail.com>
Date: Sat, 9 Jul 2022 00:57:32 -0500
Subject: [PATCH] Add local difficulty api
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
index fc38d65914143aaf93aa85badf3adcdfe4dda1b5..adb914317183148ecab6c8ab7c4ce65d3400434e 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
@@ -2373,6 +2373,12 @@ public class CraftWorld extends CraftRegionAccessor implements World {
return (this.getHandle().getDragonFight() == null) ? null : new CraftDragonBattle(this.getHandle().getDragonFight());
}
+ // Purpur start
+ public float getLocalDifficultyAt(Location location) {
+ return getHandle().getCurrentDifficultyAt(io.papermc.paper.util.MCUtil.toBlockPosition(location)).getEffectiveDifficulty();
+ }
+ // Purpur end
+
@Override
public Collection<GeneratedStructure> getStructures(int x, int z) {
return this.getStructures(x, z, struct -> true);

View File

@@ -0,0 +1,50 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Encode42 <me@encode42.dev>
Date: Tue, 12 Jul 2022 14:16:10 -0400
Subject: [PATCH] Add toggle for RNG manipulation
Paper patches RNG maniplulation by using a shared (and locked) random source.
This comes with a performance gain, but technical players may prefer the ability to manipulate RNG.
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
index 3ba86e5b66ff4d3d4c8675f9b084b91ab034eeb4..7e94f52f4086331401e35b6814709054e26d85b6 100644
--- a/src/main/java/net/minecraft/world/entity/Entity.java
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
@@ -485,7 +485,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
this.bb = Entity.INITIAL_AABB;
this.stuckSpeedMultiplier = Vec3.ZERO;
this.nextStep = 1.0F;
- this.random = SHARED_RANDOM; // Paper - Share random for entities to make them more random
+ this.random = world == null || world.purpurConfig.entitySharedRandom ? SHARED_RANDOM : RandomSource.create(); // Paper - Share random for entities to make them more random // Purpur
this.remainingFireTicks = -this.getFireImmuneTicks();
this.fluidHeight = new Object2DoubleArrayMap(2);
this.fluidOnEyes = new HashSet();
diff --git a/src/main/java/net/minecraft/world/entity/animal/Squid.java b/src/main/java/net/minecraft/world/entity/animal/Squid.java
index b9c8fe36c6a6256097ea69383bef678bbfb6c45b..8ec27ee82cd6f31bee722852c5fc6e7ca64a3a77 100644
--- a/src/main/java/net/minecraft/world/entity/animal/Squid.java
+++ b/src/main/java/net/minecraft/world/entity/animal/Squid.java
@@ -41,7 +41,7 @@ public class Squid extends WaterAnimal {
public Squid(EntityType<? extends Squid> type, Level world) {
super(type, world);
- //this.random.setSeed((long)this.getId()); // Paper - Share random for entities to make them more random
+ if (!world.purpurConfig.entitySharedRandom) this.random.setSeed((long)this.getId()); // Paper - Share random for entities to make them more random // Purpur
this.tentacleSpeed = 1.0F / (this.random.nextFloat() + 1.0F) * 0.2F;
}
diff --git a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
index 55d6232d50dd48080aec705512c791c86dae8c93..bd48c162844d3aaa194476eb6b6c2647ec2a7316 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
@@ -208,9 +208,11 @@ public class PurpurWorldConfig {
public int entityLifeSpan = 0;
public float entityLeftHandedChance = 0.05f;
+ public boolean entitySharedRandom = true;
private void entitySettings() {
entityLifeSpan = getInt("gameplay-mechanics.entity-lifespan", entityLifeSpan);
entityLeftHandedChance = (float) getDouble("gameplay-mechanics.entity-left-handed-chance", entityLeftHandedChance);
+ entitySharedRandom = getBoolean("settings.entity.shared-random", entitySharedRandom);
}
public List<Item> itemImmuneToCactus = new ArrayList<>();

View File

@@ -0,0 +1,35 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: BillyGalbreath <blake.galbreath@gmail.com>
Date: Wed, 27 Jul 2022 00:42:39 -0500
Subject: [PATCH] Add more logger output for invalid movement kicks
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
index c1f345fed7c5f95a87e3cc74e8ec200fcc49e777..44baee03b15c710f06f0d255e3102393d4c172f5 100644
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -721,6 +721,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel());
if (packet.getId() == this.awaitingTeleport) {
if (this.awaitingPositionFromClient == null) {
+ ServerGamePacketListenerImpl.LOGGER.warn("Disconnected on accept teleport packet. Was not expecting position data from client at this time"); // Purpur
this.disconnect((Component) Component.translatable("multiplayer.disconnect.invalid_player_movement"), org.bukkit.event.player.PlayerKickEvent.Cause.INVALID_PLAYER_MOVEMENT); // Paper - kick event cause
return;
}
@@ -1327,7 +1328,15 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
@Override
public void handleMovePlayer(ServerboundMovePlayerPacket packet) {
PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel());
- if (ServerGamePacketListenerImpl.containsInvalidValues(packet.getX(0.0D), packet.getY(0.0D), packet.getZ(0.0D), packet.getYRot(0.0F), packet.getXRot(0.0F))) {
+ // Purpur start
+ boolean invalidX = Double.isNaN(packet.getX(0.0D));
+ boolean invalidY = Double.isNaN(packet.getY(0.0D));
+ boolean invalidZ = Double.isNaN(packet.getZ(0.0D));
+ boolean invalidYaw = !Floats.isFinite(packet.getYRot(0.0F));
+ boolean invalidPitch = !Floats.isFinite(packet.getXRot(0.0F));
+ if (invalidX || invalidY || invalidZ || invalidYaw || invalidPitch) {
+ ServerGamePacketListenerImpl.LOGGER.warn(String.format("Disconnected on move player packet. Invalid data: x=%b, y=%b, z=%b, yaw=%b, pitch=%b", invalidX, invalidY, invalidZ, invalidYaw, invalidPitch)); // Purpur
+ // Purpur end
this.disconnect((Component) Component.translatable("multiplayer.disconnect.invalid_player_movement"), org.bukkit.event.player.PlayerKickEvent.Cause.INVALID_PLAYER_MOVEMENT); // Paper - kick event cause
} else {
ServerLevel worldserver = this.player.serverLevel();

View File

@@ -0,0 +1,34 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: SageSphinx63920 <sage@sagesphinx63920.dev>
Date: Mon, 25 Jul 2022 19:33:49 +0200
Subject: [PATCH] Add Bee API
diff --git a/src/main/java/net/minecraft/world/entity/animal/Bee.java b/src/main/java/net/minecraft/world/entity/animal/Bee.java
index 0dfdecff129a6b34833eb3fb7d7d967b131531ff..0422c4184c4823b8572afd398ef96fc6054e8485 100644
--- a/src/main/java/net/minecraft/world/entity/animal/Bee.java
+++ b/src/main/java/net/minecraft/world/entity/animal/Bee.java
@@ -808,6 +808,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal {
if (optional.isPresent()) {
Bee.this.savedFlowerPos = (BlockPos) optional.get();
Bee.this.navigation.moveTo((double) Bee.this.savedFlowerPos.getX() + 0.5D, (double) Bee.this.savedFlowerPos.getY() + 0.5D, (double) Bee.this.savedFlowerPos.getZ() + 0.5D, 1.2000000476837158D);
+ new org.purpurmc.purpur.event.entity.BeeFoundFlowerEvent((org.bukkit.entity.Bee) Bee.this.getBukkitEntity(), io.papermc.paper.util.MCUtil.toLocation(Bee.this.level(), Bee.this.savedFlowerPos)).callEvent(); // Purpur
return true;
} else {
Bee.this.remainingCooldownBeforeLocatingNewFlower = Mth.nextInt(Bee.this.random, 20, 60);
@@ -864,6 +865,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 : io.papermc.paper.util.MCUtil.toLocation(Bee.this.level(), Bee.this.savedFlowerPos), Bee.this.hasNectar()).callEvent(); // Purpur
}
@Override
@@ -910,6 +912,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(), io.papermc.paper.util.MCUtil.toLocation(Bee.this.level(), Bee.this.savedFlowerPos)).callEvent(); // Purpur
++this.successfulPollinatingTicks;
if (Bee.this.random.nextFloat() < 0.05F && this.successfulPollinatingTicks > this.lastSoundPlayedTick + 60) {
this.lastSoundPlayedTick = this.successfulPollinatingTicks;

View File

@@ -0,0 +1,148 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: YouHaveTrouble <youhavetrouble@youhavetrouble.me>
Date: Sat, 23 Jul 2022 14:40:38 +0200
Subject: [PATCH] Debug Marker API
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
index 8632ef169eab32caca3a6d89011c37e81345b7d0..dedf510a5942aaa65a606d108d4082e87add5523 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
@@ -1609,6 +1609,42 @@ public final class CraftServer implements Server {
public void removeFuel(org.bukkit.Material material) {
net.minecraft.world.level.block.entity.AbstractFurnaceBlockEntity.removeFuel(net.minecraft.world.item.ItemStack.fromBukkitCopy(new ItemStack(material)));
}
+
+ @Override
+ public void sendBlockHighlight(Location location, int duration) {
+ sendBlockHighlight(location, duration, "", 0x6400FF00);
+ }
+
+ @Override
+ public void sendBlockHighlight(Location location, int duration, int argb) {
+ sendBlockHighlight(location, duration, "", argb);
+ }
+
+ @Override
+ public void sendBlockHighlight(Location location, int duration, String text) {
+ sendBlockHighlight(location, duration, text, 0x6400FF00);
+ }
+
+ @Override
+ public void sendBlockHighlight(Location location, int duration, String text, int argb) {
+ this.worlds.forEach((name, world) -> world.sendBlockHighlight(location, duration, text, argb));
+ }
+
+ @Override
+ public void sendBlockHighlight(Location location, int duration, org.bukkit.Color color, int transparency) {
+ sendBlockHighlight(location, duration, "", color, transparency);
+ }
+
+ @Override
+ public void sendBlockHighlight(Location location, int duration, String text, org.bukkit.Color color, int transparency) {
+ if (transparency < 0 || transparency > 255) throw new IllegalArgumentException("transparency is outside of 0-255 range");
+ sendBlockHighlight(location, duration, text, transparency << 24 | color.asRGB());
+ }
+
+ @Override
+ public void clearBlockHighlights() {
+ this.worlds.forEach((name, world) -> clearBlockHighlights());
+ }
// Purpur End
@Override
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
index adb914317183148ecab6c8ab7c4ce65d3400434e..415c87f2ead5cfa5f8d63d125596aa60581c561a 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
@@ -2377,6 +2377,42 @@ public class CraftWorld extends CraftRegionAccessor implements World {
public float getLocalDifficultyAt(Location location) {
return getHandle().getCurrentDifficultyAt(io.papermc.paper.util.MCUtil.toBlockPosition(location)).getEffectiveDifficulty();
}
+
+ @Override
+ public void sendBlockHighlight(Location location, int duration) {
+ sendBlockHighlight(location, duration, "", 0x6400FF00);
+ }
+
+ @Override
+ public void sendBlockHighlight(Location location, int duration, int argb) {
+ sendBlockHighlight(location, duration, "", argb);
+ }
+
+ @Override
+ public void sendBlockHighlight(Location location, int duration, String text) {
+ sendBlockHighlight(location, duration, text, 0x6400FF00);
+ }
+
+ @Override
+ public void sendBlockHighlight(Location location, int duration, String text, int argb) {
+ net.minecraft.network.protocol.game.DebugPackets.sendGameTestAddMarker(getHandle(), io.papermc.paper.util.MCUtil.toBlockPosition(location), text, argb, duration);
+ }
+
+ @Override
+ public void sendBlockHighlight(Location location, int duration, org.bukkit.Color color, int transparency) {
+ sendBlockHighlight(location, duration, "", color, transparency);
+ }
+
+ @Override
+ public void sendBlockHighlight(Location location, int duration, String text, org.bukkit.Color color, int transparency) {
+ if (transparency < 0 || transparency > 255) throw new IllegalArgumentException("transparency is outside of 0-255 range");
+ sendBlockHighlight(location, duration, text, transparency << 24 | color.asRGB());
+ }
+
+ @Override
+ public void clearBlockHighlights() {
+ net.minecraft.network.protocol.game.DebugPackets.sendGameTestClearPacket(getHandle());
+ }
// Purpur end
@Override
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
index f4c1b3184afa8803a6dcdc63fa79f8d724ccefab..a51cfed20f938364d0b087ddbabcfc83719a9de1 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
@@ -3582,5 +3582,43 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
public void resetIdleTimer() {
getHandle().resetLastActionTime();
}
+
+ @Override
+ public void sendBlockHighlight(Location location, int duration) {
+ sendBlockHighlight(location, duration, "", 0x6400FF00);
+ }
+
+ @Override
+ public void sendBlockHighlight(Location location, int duration, int argb) {
+ sendBlockHighlight(location, duration, "", argb);
+ }
+
+ @Override
+ public void sendBlockHighlight(Location location, int duration, String text) {
+ sendBlockHighlight(location, duration, text, 0x6400FF00);
+ }
+
+ @Override
+ public void sendBlockHighlight(Location location, int duration, String text, int argb) {
+ if (this.getHandle().connection == null) return;
+ this.getHandle().connection.send(new net.minecraft.network.protocol.common.ClientboundCustomPayloadPacket(new net.minecraft.network.protocol.common.custom.GameTestAddMarkerDebugPayload(io.papermc.paper.util.MCUtil.toBlockPosition(location), argb, text, duration)));
+ }
+
+ @Override
+ public void sendBlockHighlight(Location location, int duration, org.bukkit.Color color, int transparency) {
+ sendBlockHighlight(location, duration, "", color, transparency);
+ }
+
+ @Override
+ public void sendBlockHighlight(Location location, int duration, String text, org.bukkit.Color color, int transparency) {
+ if (transparency < 0 || transparency > 255) throw new IllegalArgumentException("transparency is outside of 0-255 range");
+ sendBlockHighlight(location, duration, text, transparency << 24 | color.asRGB());
+ }
+
+ @Override
+ public void clearBlockHighlights() {
+ if (this.getHandle().connection == null) return;
+ this.getHandle().connection.send(new net.minecraft.network.protocol.common.ClientboundCustomPayloadPacket(new net.minecraft.network.protocol.common.custom.GameTestClearMarkersDebugPayload()));
+ }
// Purpur end
}

View File

@@ -0,0 +1,39 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: granny <granny@purpurmc.org>
Date: Fri, 26 Aug 2022 22:44:41 -0700
Subject: [PATCH] mob spawning option to ignore creative players
diff --git a/src/main/java/net/minecraft/world/level/NaturalSpawner.java b/src/main/java/net/minecraft/world/level/NaturalSpawner.java
index ea6533c1ac218aa075da3401807a06fcb7892321..3fffaf0876bde3487e990510debeb31913d390b4 100644
--- a/src/main/java/net/minecraft/world/level/NaturalSpawner.java
+++ b/src/main/java/net/minecraft/world/level/NaturalSpawner.java
@@ -208,7 +208,7 @@ public final class NaturalSpawner {
blockposition_mutableblockposition.set(l, i, i1);
double d0 = (double) l + 0.5D;
double d1 = (double) i1 + 0.5D;
- Player entityhuman = world.getNearestPlayer(d0, (double) i, d1, -1.0D, false);
+ Player entityhuman = world.getNearestPlayer(d0, (double) i, d1, -1.0D, world.purpurConfig.mobSpawningIgnoreCreativePlayers); // Purpur
if (entityhuman != null) {
double d2 = entityhuman.distanceToSqr(d0, (double) i, d1);
diff --git a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
index bd48c162844d3aaa194476eb6b6c2647ec2a7316..3ee77eafb36b744035e4eb0cc916ad165f100b13 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
@@ -370,6 +370,7 @@ public class PurpurWorldConfig {
public boolean phantomSpawning;
public boolean villagerTraderSpawning;
public boolean villageSiegeSpawning;
+ public boolean mobSpawningIgnoreCreativePlayers = false;
private void mobSpawnerSettings() {
// values of "default" or null will default to true only if the world environment is normal (aka overworld)
Predicate<Boolean> predicate = (bool) -> (bool != null && bool) || (bool == null && environment == World.Environment.NORMAL);
@@ -378,6 +379,7 @@ public class PurpurWorldConfig {
phantomSpawning = getBoolean("gameplay-mechanics.mob-spawning.phantoms", predicate);
villagerTraderSpawning = getBoolean("gameplay-mechanics.mob-spawning.wandering-traders", predicate);
villageSiegeSpawning = getBoolean("gameplay-mechanics.mob-spawning.village-sieges", predicate);
+ mobSpawningIgnoreCreativePlayers = getBoolean("gameplay-mechanics.mob-spawning.ignore-creative-players", mobSpawningIgnoreCreativePlayers);
}
public boolean disableObserverClocks = false;

View File

@@ -0,0 +1,51 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: BillyGalbreath <blake.galbreath@gmail.com>
Date: Fri, 2 Sep 2022 13:04:53 -0500
Subject: [PATCH] Add skeleton bow accuracy option
diff --git a/src/main/java/net/minecraft/world/entity/monster/AbstractSkeleton.java b/src/main/java/net/minecraft/world/entity/monster/AbstractSkeleton.java
index 63cbec52bc4637a0b787cbc22041188691527def..45b09f79a0ae8b7ebdd015d6edfa1fe0fd092763 100644
--- a/src/main/java/net/minecraft/world/entity/monster/AbstractSkeleton.java
+++ b/src/main/java/net/minecraft/world/entity/monster/AbstractSkeleton.java
@@ -185,7 +185,7 @@ public abstract class AbstractSkeleton extends Monster implements RangedAttackMo
double d2 = target.getZ() - this.getZ();
double d3 = Math.sqrt(d0 * d0 + d2 * d2);
- entityarrow.shoot(d0, d1 + d3 * 0.20000000298023224D, d2, 1.6F, (float) (14 - this.level().getDifficulty().getId() * 4));
+ entityarrow.shoot(d0, d1 + d3 * 0.20000000298023224D, d2, 1.6F, this.level().purpurConfig.skeletonBowAccuracyMap.getOrDefault(this.level().getDifficulty().getId(), (float) (14 - this.level().getDifficulty().getId() * 4))); // Purpur
// CraftBukkit start
org.bukkit.event.entity.EntityShootBowEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityShootBowEvent(this, this.getMainHandItem(), entityarrow.getPickupItem(), entityarrow, net.minecraft.world.InteractionHand.MAIN_HAND, 0.8F, true); // Paper
if (event.isCancelled()) {
diff --git a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
index 3ee77eafb36b744035e4eb0cc916ad165f100b13..81d3a0af4da0387fc072c015e04d51b7564f603a 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
@@ -2516,6 +2516,8 @@ public class PurpurWorldConfig {
public boolean skeletonAlwaysDropExp = false;
public double skeletonHeadVisibilityPercent = 0.5D;
public int skeletonFeedWitherRoses = 0;
+ public String skeletonBowAccuracy = "14 - difficulty * 4";
+ public Map<Integer, Float> skeletonBowAccuracyMap = new HashMap<>();
private void skeletonSettings() {
skeletonRidable = getBoolean("mobs.skeleton.ridable", skeletonRidable);
skeletonRidableInWater = getBoolean("mobs.skeleton.ridable-in-water", skeletonRidableInWater);
@@ -2530,6 +2532,18 @@ public class PurpurWorldConfig {
skeletonAlwaysDropExp = getBoolean("mobs.skeleton.always-drop-exp", skeletonAlwaysDropExp);
skeletonHeadVisibilityPercent = getDouble("mobs.skeleton.head-visibility-percent", skeletonHeadVisibilityPercent);
skeletonFeedWitherRoses = getInt("mobs.skeleton.feed-wither-roses", skeletonFeedWitherRoses);
+ final String defaultSkeletonBowAccuracy = skeletonBowAccuracy;
+ skeletonBowAccuracy = getString("mobs.skeleton.bow-accuracy", skeletonBowAccuracy);
+ for (int i = 1; i < 4; i++) {
+ final float divergence;
+ try {
+ divergence = ((Number) Entity.scriptEngine.eval("let difficulty = " + i + "; " + skeletonBowAccuracy)).floatValue();
+ } catch (javax.script.ScriptException e) {
+ e.printStackTrace();
+ break;
+ }
+ skeletonBowAccuracyMap.put(i, divergence);
+ }
}
public boolean skeletonHorseRidable = false;

View File

@@ -0,0 +1,22 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: MelnCat <melncatuwu@gmail.com>
Date: Fri, 23 Sep 2022 18:41:05 -0700
Subject: [PATCH] Add death screen API
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
index a51cfed20f938364d0b087ddbabcfc83719a9de1..f36c0c33438698d7bf6e0fd6c3101b2b8e8f8fe5 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
@@ -3620,5 +3620,11 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
if (this.getHandle().connection == null) return;
this.getHandle().connection.send(new net.minecraft.network.protocol.common.ClientboundCustomPayloadPacket(new net.minecraft.network.protocol.common.custom.GameTestClearMarkersDebugPayload()));
}
+
+ @Override
+ public void sendDeathScreen(net.kyori.adventure.text.Component message) {
+ if (this.getHandle().connection == null) return;
+ this.getHandle().connection.send(new net.minecraft.network.protocol.game.ClientboundPlayerCombatKillPacket(getEntityId(), io.papermc.paper.adventure.PaperAdventure.asVanilla(message)));
+ }
// Purpur end
}

View File

@@ -0,0 +1,360 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: BillyGalbreath <blake.galbreath@gmail.com>
Date: Mon, 26 Sep 2022 07:43:30 -0500
Subject: [PATCH] Implement ram and rambar commands
diff --git a/src/main/java/net/minecraft/commands/Commands.java b/src/main/java/net/minecraft/commands/Commands.java
index 89cfef3a5c466a8f508cce1aa37ec6b01432eb35..7bcc0f87337547f8783dd9cc8adff61187cd41d7 100644
--- a/src/main/java/net/minecraft/commands/Commands.java
+++ b/src/main/java/net/minecraft/commands/Commands.java
@@ -256,6 +256,8 @@ public class Commands {
org.purpurmc.purpur.command.UptimeCommand.register(this.dispatcher); // Purpur
org.purpurmc.purpur.command.TPSBarCommand.register(this.dispatcher); // Purpur
org.purpurmc.purpur.command.CompassCommand.register(this.dispatcher); // Purpur
+ org.purpurmc.purpur.command.RamBarCommand.register(this.dispatcher); // Purpur
+ org.purpurmc.purpur.command.RamCommand.register(this.dispatcher); // Purpur
}
if (environment.includeIntegrated) {
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
index 30e642f51bbaae3a96c714a99dda43ca60cc374c..3f414fe2ead0f3ba44f48bf5d6555c65a629c447 100644
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
@@ -299,6 +299,7 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player {
public boolean purpurClient = false; // Purpur
private boolean tpsBar = false; // Purpur
private boolean compassBar = false; // Purpur
+ private boolean ramBar = false; // Purpur
public ServerPlayer(MinecraftServer server, ServerLevel world, GameProfile profile, ClientInformation clientOptions) {
super(world, world.getSharedSpawnPos(), world.getSharedSpawnAngle(), profile);
@@ -570,6 +571,7 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player {
if (nbt.contains("Purpur.TPSBar")) { this.tpsBar = nbt.getBoolean("Purpur.TPSBar"); } // Purpur
if (nbt.contains("Purpur.CompassBar")) { this.compassBar = nbt.getBoolean("Purpur.CompassBar"); } // Purpur
+ if (nbt.contains("Purpur.RamBar")) { this.ramBar = nbt.getBoolean("Purpur.RamBar"); } // Purpur
}
@Override
@@ -646,6 +648,7 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player {
});
}
+ nbt.putBoolean("Purpur.RamBar", this.ramBar); // Purpur
nbt.putBoolean("Purpur.TPSBar", this.tpsBar); // Purpur
nbt.putBoolean("Purpur.CompassBar", this.compassBar); // Purpur
}
@@ -3058,5 +3061,13 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player {
public void compassBar(boolean compassBar) {
this.compassBar = compassBar;
}
+
+ public boolean ramBar() {
+ return this.ramBar;
+ }
+
+ public void ramBar(boolean ramBar) {
+ this.ramBar = ramBar;
+ }
// Purpur end
}
diff --git a/src/main/java/org/purpurmc/purpur/PurpurConfig.java b/src/main/java/org/purpurmc/purpur/PurpurConfig.java
index bbb7afbfb84b0d8e45f6e0de61f4f3e8c9315431..0278beb0746db9a8b25eefeacbb4f8f4e5e6d38b 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurConfig.java
@@ -182,6 +182,8 @@ public class PurpurConfig {
public static String creditsCommandOutput = "<green>%s has been shown the end credits";
public static String demoCommandOutput = "<green>%s has been shown the demo screen";
public static String pingCommandOutput = "<green>%s's ping is %sms";
+ public static String ramCommandOutput = "<green>Ram Usage: <used>/<xmx> (<percent>)";
+ public static String rambarCommandOutput = "<green>Rambar toggled <onoff> for <target>";
public static String tpsbarCommandOutput = "<green>Tpsbar toggled <onoff> for <target>";
public static String dontRunWithScissors = "<red><italic>Don't run with scissors!";
public static String uptimeCommandOutput = "<green>Server uptime is <uptime>";
@@ -199,6 +201,8 @@ public class PurpurConfig {
creditsCommandOutput = getString("settings.messages.credits-command-output", creditsCommandOutput);
demoCommandOutput = getString("settings.messages.demo-command-output", demoCommandOutput);
pingCommandOutput = getString("settings.messages.ping-command-output", pingCommandOutput);
+ ramCommandOutput = getString("settings.messages.ram-command-output", ramCommandOutput);
+ rambarCommandOutput = getString("settings.messages.rambar-command-output", rambarCommandOutput);
tpsbarCommandOutput = getString("settings.messages.tpsbar-command-output", tpsbarCommandOutput);
dontRunWithScissors = getString("settings.messages.dont-run-with-scissors", dontRunWithScissors);
uptimeCommandOutput = getString("settings.messages.uptime-command-output", uptimeCommandOutput);
@@ -247,6 +251,15 @@ public class PurpurConfig {
disableGiveCommandDrops = getBoolean("settings.disable-give-dropping", disableGiveCommandDrops);
}
+ public static String commandRamBarTitle = "<gray>Ram<yellow>:</yellow> <used>/<xmx> (<percent>)";
+ public static BossBar.Overlay commandRamBarProgressOverlay = BossBar.Overlay.NOTCHED_20;
+ public static BossBar.Color commandRamBarProgressColorGood = BossBar.Color.GREEN;
+ public static BossBar.Color commandRamBarProgressColorMedium = BossBar.Color.YELLOW;
+ public static BossBar.Color commandRamBarProgressColorLow = BossBar.Color.RED;
+ public static String commandRamBarTextColorGood = "<gradient:#55ff55:#00aa00><text></gradient>";
+ public static String commandRamBarTextColorMedium = "<gradient:#ffff55:#ffaa00><text></gradient>";
+ public static String commandRamBarTextColorLow = "<gradient:#ff5555:#aa0000><text></gradient>";
+ public static int commandRamBarTickInterval = 20;
public static String commandTPSBarTitle = "<gray>TPS<yellow>:</yellow> <tps> MSPT<yellow>:</yellow> <mspt> Ping<yellow>:</yellow> <ping>ms";
public static BossBar.Overlay commandTPSBarProgressOverlay = BossBar.Overlay.NOTCHED_20;
public static TPSBarTask.FillMode commandTPSBarProgressFillMode = TPSBarTask.FillMode.MSPT;
@@ -274,6 +287,16 @@ public class PurpurConfig {
public static String uptimeSecond = "%02d second";
public static String uptimeSeconds = "%02d seconds";
private static void commandSettings() {
+ commandRamBarTitle = getString("settings.command.rambar.title", commandRamBarTitle);
+ commandRamBarProgressOverlay = BossBar.Overlay.valueOf(getString("settings.command.rambar.overlay", commandRamBarProgressOverlay.name()));
+ commandRamBarProgressColorGood = BossBar.Color.valueOf(getString("settings.command.rambar.progress-color.good", commandRamBarProgressColorGood.name()));
+ commandRamBarProgressColorMedium = BossBar.Color.valueOf(getString("settings.command.rambar.progress-color.medium", commandRamBarProgressColorMedium.name()));
+ commandRamBarProgressColorLow = BossBar.Color.valueOf(getString("settings.command.rambar.progress-color.low", commandRamBarProgressColorLow.name()));
+ commandRamBarTextColorGood = getString("settings.command.rambar.text-color.good", commandRamBarTextColorGood);
+ commandRamBarTextColorMedium = getString("settings.command.rambar.text-color.medium", commandRamBarTextColorMedium);
+ commandRamBarTextColorLow = getString("settings.command.rambar.text-color.low", commandRamBarTextColorLow);
+ commandRamBarTickInterval = getInt("settings.command.rambar.tick-interval", commandRamBarTickInterval);
+
commandTPSBarTitle = getString("settings.command.tpsbar.title", commandTPSBarTitle);
commandTPSBarProgressOverlay = BossBar.Overlay.valueOf(getString("settings.command.tpsbar.overlay", commandTPSBarProgressOverlay.name()));
commandTPSBarProgressFillMode = TPSBarTask.FillMode.valueOf(getString("settings.command.tpsbar.fill-mode", commandTPSBarProgressFillMode.name()));
diff --git a/src/main/java/org/purpurmc/purpur/command/RamBarCommand.java b/src/main/java/org/purpurmc/purpur/command/RamBarCommand.java
new file mode 100644
index 0000000000000000000000000000000000000000..2852c07adb080c34905f5d1b19efed8ea47eecc6
--- /dev/null
+++ b/src/main/java/org/purpurmc/purpur/command/RamBarCommand.java
@@ -0,0 +1,44 @@
+package org.purpurmc.purpur.command;
+
+import com.mojang.brigadier.CommandDispatcher;
+import net.kyori.adventure.text.Component;
+import net.kyori.adventure.text.format.NamedTextColor;
+import net.kyori.adventure.text.minimessage.MiniMessage;
+import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder;
+import net.minecraft.commands.CommandSourceStack;
+import net.minecraft.commands.Commands;
+import net.minecraft.commands.arguments.EntityArgument;
+import net.minecraft.server.level.ServerPlayer;
+import org.purpurmc.purpur.PurpurConfig;
+import org.purpurmc.purpur.task.RamBarTask;
+
+import java.util.Collection;
+import java.util.Collections;
+
+public class RamBarCommand {
+ public static void register(CommandDispatcher<CommandSourceStack> dispatcher) {
+ dispatcher.register(Commands.literal("rambar")
+ .requires(listener -> listener.hasPermission(2, "bukkit.command.rambar"))
+ .executes(context -> execute(context.getSource(), Collections.singleton(context.getSource().getPlayerOrException())))
+ .then(Commands.argument("targets", EntityArgument.players())
+ .requires(listener -> listener.hasPermission(2, "bukkit.command.rambar.other"))
+ .executes((context) -> execute(context.getSource(), EntityArgument.getPlayers(context, "targets")))
+ )
+ );
+ }
+
+ private static int execute(CommandSourceStack sender, Collection<ServerPlayer> targets) {
+ for (ServerPlayer player : targets) {
+ boolean result = RamBarTask.instance().togglePlayer(player.getBukkitEntity());
+ player.ramBar(result);
+
+ Component output = MiniMessage.miniMessage().deserialize(PurpurConfig.rambarCommandOutput,
+ Placeholder.component("onoff", Component.translatable(result ? "options.on" : "options.off")
+ .color(result ? NamedTextColor.GREEN : NamedTextColor.RED)),
+ Placeholder.parsed("target", player.getGameProfile().getName()));
+
+ sender.sendSuccess(output, false);
+ }
+ return targets.size();
+ }
+}
diff --git a/src/main/java/org/purpurmc/purpur/command/RamCommand.java b/src/main/java/org/purpurmc/purpur/command/RamCommand.java
new file mode 100644
index 0000000000000000000000000000000000000000..992f8dfc628c7485e335191e1308cdfd4eedfbe8
--- /dev/null
+++ b/src/main/java/org/purpurmc/purpur/command/RamCommand.java
@@ -0,0 +1,30 @@
+package org.purpurmc.purpur.command;
+
+import com.mojang.brigadier.CommandDispatcher;
+import io.papermc.paper.adventure.PaperAdventure;
+import net.kyori.adventure.text.minimessage.MiniMessage;
+import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder;
+import net.minecraft.commands.CommandSourceStack;
+import net.minecraft.commands.Commands;
+import org.purpurmc.purpur.PurpurConfig;
+import org.purpurmc.purpur.task.RamBarTask;
+
+public class RamCommand {
+ public static void register(CommandDispatcher<CommandSourceStack> dispatcher) {
+ dispatcher.register(Commands.literal("ram")
+ .requires(listener -> listener.hasPermission(2, "bukkit.command.ram"))
+ .executes(context -> {
+ CommandSourceStack sender = context.getSource();
+ RamBarTask ramBar = RamBarTask.instance();
+ sender.sendSuccess(() -> PaperAdventure.asVanilla(MiniMessage.miniMessage().deserialize(PurpurConfig.ramCommandOutput,
+ Placeholder.component("allocated", ramBar.format(ramBar.getAllocated())),
+ Placeholder.component("used", ramBar.format(ramBar.getUsed())),
+ Placeholder.component("xmx", ramBar.format(ramBar.getXmx())),
+ Placeholder.component("xms", ramBar.format(ramBar.getXms())),
+ Placeholder.unparsed("percent", ((int) (ramBar.getPercent() * 100)) + "%")
+ )), false);
+ return 1;
+ })
+ );
+ }
+}
diff --git a/src/main/java/org/purpurmc/purpur/task/BossBarTask.java b/src/main/java/org/purpurmc/purpur/task/BossBarTask.java
index d333334f323049ca97e756324cff0b23eddacd2a..114f273dd7f8b8a3c02f0651f6944859b33a65d4 100644
--- a/src/main/java/org/purpurmc/purpur/task/BossBarTask.java
+++ b/src/main/java/org/purpurmc/purpur/task/BossBarTask.java
@@ -89,17 +89,22 @@ public abstract class BossBarTask extends BukkitRunnable {
}
public static void startAll() {
+ RamBarTask.instance().start();
TPSBarTask.instance().start();
CompassTask.instance().start();
}
public static void stopAll() {
+ RamBarTask.instance().stop();
TPSBarTask.instance().stop();
CompassTask.instance().stop();
}
public static void addToAll(ServerPlayer player) {
Player bukkit = player.getBukkitEntity();
+ if (player.ramBar()) {
+ RamBarTask.instance().addPlayer(bukkit);
+ }
if (player.tpsBar()) {
TPSBarTask.instance().addPlayer(bukkit);
}
@@ -109,6 +114,7 @@ public abstract class BossBarTask extends BukkitRunnable {
}
public static void removeFromAll(Player player) {
+ RamBarTask.instance().removePlayer(player);
TPSBarTask.instance().removePlayer(player);
CompassTask.instance().removePlayer(player);
}
diff --git a/src/main/java/org/purpurmc/purpur/task/RamBarTask.java b/src/main/java/org/purpurmc/purpur/task/RamBarTask.java
new file mode 100644
index 0000000000000000000000000000000000000000..8e98c0ae73e2c40002a72b5d0d246ffa0c3ab38f
--- /dev/null
+++ b/src/main/java/org/purpurmc/purpur/task/RamBarTask.java
@@ -0,0 +1,117 @@
+package org.purpurmc.purpur.task;
+
+import net.kyori.adventure.bossbar.BossBar;
+import net.kyori.adventure.text.Component;
+import net.kyori.adventure.text.minimessage.MiniMessage;
+import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder;
+import org.bukkit.entity.Player;
+import org.purpurmc.purpur.PurpurConfig;
+
+import java.lang.management.ManagementFactory;
+import java.lang.management.MemoryUsage;
+
+public class RamBarTask extends BossBarTask {
+ private static RamBarTask instance;
+ private long allocated = 0L;
+ private long used = 0L;
+ private long xmx = 0L;
+ private long xms = 0L;
+ private float percent = 0F;
+ private int tick = 0;
+
+ public static RamBarTask instance() {
+ if (instance == null) {
+ instance = new RamBarTask();
+ }
+ return instance;
+ }
+
+ @Override
+ BossBar createBossBar() {
+ return BossBar.bossBar(Component.text(""), 0.0F, instance().getBossBarColor(), PurpurConfig.commandRamBarProgressOverlay);
+ }
+
+ @Override
+ void updateBossBar(BossBar bossbar, Player player) {
+ bossbar.progress(getBossBarProgress());
+ bossbar.color(getBossBarColor());
+ bossbar.name(MiniMessage.miniMessage().deserialize(PurpurConfig.commandRamBarTitle,
+ Placeholder.component("allocated", format(this.allocated)),
+ Placeholder.component("used", format(this.used)),
+ Placeholder.component("xmx", format(this.xmx)),
+ Placeholder.component("xms", format(this.xms)),
+ Placeholder.unparsed("percent", ((int) (this.percent * 100)) + "%")
+ ));
+ }
+
+ @Override
+ public void run() {
+ if (++this.tick < PurpurConfig.commandRamBarTickInterval) {
+ return;
+ }
+ this.tick = 0;
+
+ MemoryUsage heap = ManagementFactory.getMemoryMXBean().getHeapMemoryUsage();
+
+ this.allocated = heap.getCommitted();
+ this.used = heap.getUsed();
+ this.xmx = heap.getMax();
+ this.xms = heap.getInit();
+ this.percent = Math.max(Math.min((float) this.used / this.xmx, 1.0F), 0.0F);
+
+ super.run();
+ }
+
+ private float getBossBarProgress() {
+ return this.percent;
+ }
+
+ private BossBar.Color getBossBarColor() {
+ if (this.percent < 0.5F) {
+ return PurpurConfig.commandRamBarProgressColorGood;
+ } else if (this.percent < 0.75F) {
+ return PurpurConfig.commandRamBarProgressColorMedium;
+ } else {
+ return PurpurConfig.commandRamBarProgressColorLow;
+ }
+ }
+
+ public Component format(long v) {
+ String color;
+ if (this.percent < 0.60F) {
+ color = PurpurConfig.commandRamBarTextColorGood;
+ } else if (this.percent < 0.85F) {
+ color = PurpurConfig.commandRamBarTextColorMedium;
+ } else {
+ color = PurpurConfig.commandRamBarTextColorLow;
+ }
+ String value;
+ if (v < 1024) {
+ value = v + "B";
+ } else {
+ int z = (63 - Long.numberOfLeadingZeros(v)) / 10;
+ value = String.format("%.1f%s", (double) v / (1L << (z * 10)), "BKMGTPE".charAt(z));
+ }
+ return MiniMessage.miniMessage().deserialize(color, Placeholder.unparsed("text", value));
+ }
+
+ public long getAllocated() {
+ return this.allocated;
+ }
+
+ public long getUsed() {
+ return this.used;
+ }
+
+ public long getXmx() {
+ return this.xmx;
+ }
+
+ public long getXms() {
+ return this.xms;
+ }
+
+ public float getPercent() {
+ return this.percent;
+ }
+}

View File

@@ -0,0 +1,43 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: MelnCat <melncatuwu@gmail.com>
Date: Sat, 1 Oct 2022 13:29:17 -0700
Subject: [PATCH] Configurable block blast resistance
diff --git a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java b/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java
index 52bd9fa49649ede9d29e1c0d348cb13abf2ef1b1..ff76338659201424dcc88dfd08b6b8c2f2af593b 100644
--- a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java
+++ b/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java
@@ -85,7 +85,7 @@ public abstract class BlockBehaviour implements FeatureElement {
protected static final Direction[] UPDATE_SHAPE_ORDER = new Direction[]{Direction.WEST, Direction.EAST, Direction.NORTH, Direction.SOUTH, Direction.DOWN, Direction.UP};
public final boolean hasCollision;
- protected final float explosionResistance;
+ public float explosionResistance; // Purpur - protected final -> public
protected final boolean isRandomlyTicking;
protected final SoundType soundType;
protected final float friction;
diff --git a/src/main/java/org/purpurmc/purpur/PurpurConfig.java b/src/main/java/org/purpurmc/purpur/PurpurConfig.java
index 0278beb0746db9a8b25eefeacbb4f8f4e5e6d38b..7d33bdb2592f7977aff21804c837c9eff5827f5f 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurConfig.java
@@ -488,4 +488,19 @@ public class PurpurConfig {
String setPattern = getString("settings.username-valid-characters", defaultPattern);
usernameValidCharactersPattern = java.util.regex.Pattern.compile(setPattern == null || setPattern.isBlank() ? defaultPattern : setPattern);
}
+
+ private static void blastResistanceSettings() {
+ getMap("settings.blast-resistance-overrides", Collections.emptyMap()).forEach((blockId, value) -> {
+ Block block = BuiltInRegistries.BLOCK.get(ResourceLocation.withDefaultNamespace(blockId));
+ if (block == Blocks.AIR) {
+ log(Level.SEVERE, "Invalid block for `settings.blast-resistance-overrides`: " + blockId);
+ return;
+ }
+ if (!(value instanceof Number blastResistance)) {
+ log(Level.SEVERE, "Invalid blast resistance for `settings.blast-resistance-overrides." + blockId + "`: " + value);
+ return;
+ }
+ block.explosionResistance = blastResistance.floatValue();
+ });
+ }
}

View File

@@ -0,0 +1,110 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: MelnCat <melncatuwu@gmail.com>
Date: Sat, 1 Oct 2022 18:06:52 -0700
Subject: [PATCH] Configurable block fall damage modifiers
diff --git a/src/main/java/net/minecraft/world/level/block/BedBlock.java b/src/main/java/net/minecraft/world/level/block/BedBlock.java
index b59dd6b512021c335f3c21999958e2ea081daf69..17c994a39a1b99cc7727e328ce7493d534247a21 100644
--- a/src/main/java/net/minecraft/world/level/block/BedBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/BedBlock.java
@@ -181,7 +181,7 @@ public class BedBlock extends HorizontalDirectionalBlock implements EntityBlock
@Override
public void fallOn(Level world, BlockState state, BlockPos pos, Entity entity, float fallDistance) {
- super.fallOn(world, state, pos, entity, fallDistance * 0.5F);
+ super.fallOn(world, state, pos, entity, fallDistance); // Purpur
}
@Override
diff --git a/src/main/java/net/minecraft/world/level/block/Block.java b/src/main/java/net/minecraft/world/level/block/Block.java
index 73f2103b77795740690032084ecddc9c2a5b119e..6d012ca724f1373bcf9e8d86d22194143f56d52b 100644
--- a/src/main/java/net/minecraft/world/level/block/Block.java
+++ b/src/main/java/net/minecraft/world/level/block/Block.java
@@ -88,6 +88,10 @@ public class Block extends BlockBehaviour implements ItemLike {
public static final int UPDATE_LIMIT = 512;
protected final StateDefinition<Block, BlockState> stateDefinition;
private BlockState defaultBlockState;
+ // Purpur start
+ public float fallDamageMultiplier = 1.0F;
+ public float fallDistanceMultiplier = 1.0F;
+ // Purpur end
// Paper start
public final boolean isDestroyable() {
return io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.allowPermanentBlockBreakExploits ||
@@ -485,7 +489,7 @@ public class Block extends BlockBehaviour implements ItemLike {
}
public void fallOn(Level world, BlockState state, BlockPos pos, Entity entity, float fallDistance) {
- entity.causeFallDamage(fallDistance, 1.0F, entity.damageSources().fall());
+ entity.causeFallDamage(fallDistance * fallDistanceMultiplier, fallDamageMultiplier, entity.damageSources().fall()); // Purpur
}
public void updateEntityAfterFallOn(BlockGetter world, Entity entity) {
diff --git a/src/main/java/net/minecraft/world/level/block/HayBlock.java b/src/main/java/net/minecraft/world/level/block/HayBlock.java
index ef364aa171a48482a45bc18cfe730ec20c3f7be6..74971d90506aa253d5ee821b5390fb2551a3a393 100644
--- a/src/main/java/net/minecraft/world/level/block/HayBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/HayBlock.java
@@ -23,6 +23,6 @@ public class HayBlock extends RotatedPillarBlock {
@Override
public void fallOn(Level world, BlockState state, BlockPos pos, Entity entity, float fallDistance) {
- entity.causeFallDamage(fallDistance, 0.2F, world.damageSources().fall());
+ super.fallOn(world, state, pos, entity, fallDistance); // Purpur
}
}
diff --git a/src/main/java/org/purpurmc/purpur/PurpurConfig.java b/src/main/java/org/purpurmc/purpur/PurpurConfig.java
index 7d33bdb2592f7977aff21804c837c9eff5827f5f..3f4584ede9fc039ecdb770a0d6fcb824abc03388 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurConfig.java
@@ -503,4 +503,50 @@ public class PurpurConfig {
block.explosionResistance = blastResistance.floatValue();
});
}
+ private static void blockFallMultiplierSettings() {
+ getMap("settings.block-fall-multipliers", Map.ofEntries(
+ Map.entry("minecraft:hay_block", Map.of("damage", 0.2F)),
+ Map.entry("minecraft:white_bed", Map.of("distance", 0.5F)),
+ Map.entry("minecraft:light_gray_bed", Map.of("distance", 0.5F)),
+ Map.entry("minecraft:gray_bed", Map.of("distance", 0.5F)),
+ Map.entry("minecraft:black_bed", Map.of("distance", 0.5F)),
+ Map.entry("minecraft:brown_bed", Map.of("distance", 0.5F)),
+ Map.entry("minecraft:pink_bed", Map.of("distance", 0.5F)),
+ Map.entry("minecraft:red_bed", Map.of("distance", 0.5F)),
+ Map.entry("minecraft:orange_bed", Map.of("distance", 0.5F)),
+ Map.entry("minecraft:yellow_bed", Map.of("distance", 0.5F)),
+ Map.entry("minecraft:green_bed", Map.of("distance", 0.5F)),
+ Map.entry("minecraft:lime_bed", Map.of("distance", 0.5F)),
+ Map.entry("minecraft:cyan_bed", Map.of("distance", 0.5F)),
+ Map.entry("minecraft:light_blue_bed", Map.of("distance", 0.5F)),
+ Map.entry("minecraft:blue_bed", Map.of("distance", 0.5F)),
+ Map.entry("minecraft:purple_bed", Map.of("distance", 0.5F)),
+ Map.entry("minecraft:magenta_bed", Map.of("distance", 0.5F))
+ )).forEach((blockId, value) -> {
+ Block block = BuiltInRegistries.BLOCK.get(new ResourceLocation(blockId));
+ if (block == Blocks.AIR) {
+ log(Level.SEVERE, "Invalid block for `settings.block-fall-multipliers`: " + blockId);
+ return;
+ }
+ if (!(value instanceof Map<?, ?> map)) {
+ log(Level.SEVERE, "Invalid fall multiplier for `settings.block-fall-multipliers." + blockId + "`: " + value
+ + ", expected a map with keys `damage` and `distance` to floats.");
+ return;
+ }
+ Object rawFallDamageMultiplier = map.get("damage");
+ if (rawFallDamageMultiplier == null) rawFallDamageMultiplier = 1F;
+ if (!(rawFallDamageMultiplier instanceof Number fallDamageMultiplier)) {
+ log(Level.SEVERE, "Invalid multiplier for `settings.block-fall-multipliers." + blockId + ".damage`: " + map.get("damage"));
+ return;
+ }
+ Object rawFallDistanceMultiplier = map.get("distance");
+ if (rawFallDistanceMultiplier == null) rawFallDistanceMultiplier = 1F;
+ if (!(rawFallDistanceMultiplier instanceof Number fallDistanceMultiplier)) {
+ log(Level.SEVERE, "Invalid multiplier for `settings.block-fall-multipliers." + blockId + ".distance`: " + map.get("distance"));
+ return;
+ }
+ block.fallDamageMultiplier = fallDamageMultiplier.floatValue();
+ block.fallDistanceMultiplier = fallDistanceMultiplier.floatValue();
+ });
+ }
}

View File

@@ -0,0 +1,31 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: MelnCat <melncatuwu@gmail.com>
Date: Sat, 1 Oct 2022 17:08:43 -0700
Subject: [PATCH] Language API
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
index dedf510a5942aaa65a606d108d4082e87add5523..12e4202f198ea7fe3a69d265444b8ad88bbc0ee6 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
@@ -410,6 +410,20 @@ public final class CraftServer implements Server {
this.paperPluginManager = new io.papermc.paper.plugin.manager.PaperPluginManagerImpl(this, this.commandMap, pluginManager);
this.pluginManager.paperPluginManager = this.paperPluginManager;
// Paper end
+ // Purpur start
+ org.purpurmc.purpur.language.Language.setLanguage(new org.purpurmc.purpur.language.Language() {
+ private net.minecraft.locale.Language language = net.minecraft.locale.Language.getInstance();
+ @Override
+ public boolean has(@org.jetbrains.annotations.NotNull String key) {
+ return language.has(key);
+ }
+
+ @Override
+ public @org.jetbrains.annotations.NotNull String getOrDefault(@org.jetbrains.annotations.NotNull String key) {
+ return language.getOrDefault(key);
+ }
+ });
+ // Purpur end
CraftRegistry.setMinecraftRegistry(console.registryAccess());

View File

@@ -0,0 +1,51 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Rhythmic <mc.ADHDMC@gmail.com>
Date: Thu, 6 Oct 2022 10:41:01 -0700
Subject: [PATCH] Milk Keeps Beneficial Effects
diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java
index b3320e206e07a7b895fe28bcc4cc501c104bedd5..7d8b12bdbb2e86e49d92124ba8376df3ff5edc17 100644
--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java
+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java
@@ -1129,6 +1129,7 @@ public abstract class LivingEntity extends Entity implements Attackable {
for (flag = false; iterator.hasNext(); flag = true) {
// CraftBukkit start
MobEffectInstance effect = (MobEffectInstance) iterator.next();
+ if (cause == EntityPotionEffectEvent.Cause.MILK && !this.level().purpurConfig.milkClearsBeneficialEffects && effect.getEffect().value().isBeneficial()) continue; // Purpur
EntityPotionEffectEvent event = CraftEventFactory.callEntityPotionEffectChangeEvent(this, effect, null, cause, EntityPotionEffectEvent.Action.CLEARED);
if (event.isCancelled()) {
continue;
diff --git a/src/main/java/net/minecraft/world/entity/npc/WanderingTrader.java b/src/main/java/net/minecraft/world/entity/npc/WanderingTrader.java
index 1313844a719befa96d4d8ab23505e89e8c4df2fd..0da4dbd11d2b5368e10291ca0389f08714e0c2af 100644
--- a/src/main/java/net/minecraft/world/entity/npc/WanderingTrader.java
+++ b/src/main/java/net/minecraft/world/entity/npc/WanderingTrader.java
@@ -110,7 +110,7 @@ public class WanderingTrader extends net.minecraft.world.entity.npc.AbstractVill
return this.canDrinkPotion && this.level().isNight() && !entityvillagertrader.isInvisible(); // Paper - Add more WanderingTrader API
}));
this.goalSelector.addGoal(0, new UseItemGoal<>(this, new ItemStack(Items.MILK_BUCKET), SoundEvents.WANDERING_TRADER_REAPPEARED, (entityvillagertrader) -> {
- return this.canDrinkMilk && this.level().isDay() && entityvillagertrader.isInvisible(); // Paper - Add more WanderingTrader API
+ return level().purpurConfig.milkClearsBeneficialEffects && this.canDrinkMilk && this.level().isDay() && entityvillagertrader.isInvisible(); // Paper - Add more WanderingTrader API // Purpur
}));
this.goalSelector.addGoal(1, new TradeWithPlayerGoal(this));
this.goalSelector.addGoal(1, new AvoidEntityGoal<>(this, Zombie.class, 8.0F, 0.5D, 0.5D));
diff --git a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
index 81d3a0af4da0387fc072c015e04d51b7564f603a..eaf99a0fc84372f12e2c54c9d175072abf1239b4 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
@@ -126,6 +126,7 @@ public class PurpurWorldConfig {
public boolean entitiesPickUpLootBypassMobGriefing = false;
public boolean fireballsBypassMobGriefing = false;
public boolean milkCuresBadOmen = true;
+ public boolean milkClearsBeneficialEffects = true;
public boolean noteBlockIgnoreAbove = false;
public boolean persistentDroppableEntityDisplayNames = true;
public boolean persistentTileEntityLore = false;
@@ -151,6 +152,7 @@ public class PurpurWorldConfig {
entitiesPickUpLootBypassMobGriefing = getBoolean("gameplay-mechanics.entities-pick-up-loot-bypass-mob-griefing", entitiesPickUpLootBypassMobGriefing);
fireballsBypassMobGriefing = getBoolean("gameplay-mechanics.fireballs-bypass-mob-griefing", fireballsBypassMobGriefing);
milkCuresBadOmen = getBoolean("gameplay-mechanics.milk-cures-bad-omen", milkCuresBadOmen);
+ milkClearsBeneficialEffects = getBoolean("gameplay-mechanics.milk-clears-beneficial-effects", milkClearsBeneficialEffects);
noteBlockIgnoreAbove = getBoolean("gameplay-mechanics.note-block-ignore-above", noteBlockIgnoreAbove);
if (PurpurConfig.version < 35) {
boolean oldVal = getBoolean("gameplay-mechanics.persistent-tileentity-display-names-and-lore", persistentTileEntityLore);

View File

@@ -0,0 +1,22 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Krakenied <Krakenied1@gmail.com>
Date: Sun, 9 Oct 2022 01:50:39 +0200
Subject: [PATCH] MC-121706 - Fix mobs not looking up and down when strafing
diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/RangedBowAttackGoal.java b/src/main/java/net/minecraft/world/entity/ai/goal/RangedBowAttackGoal.java
index 515c1f671cb2c3a7cc23053aedf404bbbe77af3e..42a1e5b9c08a9245dd0ce6d4025e3bb5d60feb62 100644
--- a/src/main/java/net/minecraft/world/entity/ai/goal/RangedBowAttackGoal.java
+++ b/src/main/java/net/minecraft/world/entity/ai/goal/RangedBowAttackGoal.java
@@ -116,9 +116,9 @@ public class RangedBowAttackGoal<T extends Monster & RangedAttackMob> extends Go
}
this.mob.lookAt(livingEntity, 30.0F, 30.0F);
- } else {
+ } //else { // Purpur - fix MC-121706
this.mob.getLookControl().setLookAt(livingEntity, 30.0F, 30.0F);
- }
+ //} // Purpur
if (this.mob.isUsingItem()) {
if (!bl && this.seeTime < -60) {

View File

@@ -0,0 +1,25 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Krakenied <Krakenied1@gmail.com>
Date: Fri, 14 Oct 2022 23:11:16 +0200
Subject: [PATCH] Add log suppression for LibraryLoader
diff --git a/src/main/java/org/purpurmc/purpur/PurpurConfig.java b/src/main/java/org/purpurmc/purpur/PurpurConfig.java
index 3f4584ede9fc039ecdb770a0d6fcb824abc03388..c6757db82626e98a76ad430dcca1f20c2a9c9684 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurConfig.java
@@ -461,11 +461,14 @@ public class PurpurConfig {
public static boolean loggerSuppressIgnoredAdvancementWarnings = false;
public static boolean loggerSuppressUnrecognizedRecipeErrors = false;
public static boolean loggerSuppressSetBlockFarChunk = false;
+ public static boolean loggerSuppressLibraryLoader = false;
private static void loggerSettings() {
loggerSuppressInitLegacyMaterialError = getBoolean("settings.logger.suppress-init-legacy-material-errors", loggerSuppressInitLegacyMaterialError);
loggerSuppressIgnoredAdvancementWarnings = getBoolean("settings.logger.suppress-ignored-advancement-warnings", loggerSuppressIgnoredAdvancementWarnings);
loggerSuppressUnrecognizedRecipeErrors = getBoolean("settings.logger.suppress-unrecognized-recipe-errors", loggerSuppressUnrecognizedRecipeErrors);
loggerSuppressSetBlockFarChunk = getBoolean("settings.logger.suppress-setblock-in-far-chunk-errors", loggerSuppressSetBlockFarChunk);
+ loggerSuppressLibraryLoader = getBoolean("settings.logger.suppress-library-loader", loggerSuppressLibraryLoader);
+ org.bukkit.plugin.java.JavaPluginLoader.SuppressLibraryLoaderLogger = loggerSuppressLibraryLoader;
}
public static boolean tpsCatchup = true;

View File

@@ -0,0 +1,45 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jared Seville <Peashooter101@yahoo.com>
Date: Sat, 15 Oct 2022 16:01:03 -0700
Subject: [PATCH] Add option to allow creeper to encircle target when fusing.
diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/SwellGoal.java b/src/main/java/net/minecraft/world/entity/ai/goal/SwellGoal.java
index 137ec75ee803789deb7b1ca93dd9369c9af362b9..ca95d25af3e9a0536868b0c7fd8e7d2ff1154ee3 100644
--- a/src/main/java/net/minecraft/world/entity/ai/goal/SwellGoal.java
+++ b/src/main/java/net/minecraft/world/entity/ai/goal/SwellGoal.java
@@ -54,6 +54,14 @@ public class SwellGoal extends Goal {
this.creeper.setSwellDir(-1);
} else {
this.creeper.setSwellDir(1);
+ // Purpur start
+ 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
}
}
}
diff --git a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
index eaf99a0fc84372f12e2c54c9d175072abf1239b4..1c6d34c1d186c561666ac0f3b7e358652e21f1bb 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
@@ -1423,6 +1423,7 @@ public class PurpurWorldConfig {
public boolean creeperHealthRadius = false;
public boolean creeperAlwaysDropExp = false;
public double creeperHeadVisibilityPercent = 0.5D;
+ public boolean creeperEncircleTarget = false;
private void creeperSettings() {
creeperRidable = getBoolean("mobs.creeper.ridable", creeperRidable);
creeperRidableInWater = getBoolean("mobs.creeper.ridable-in-water", creeperRidableInWater);
@@ -1441,6 +1442,7 @@ public class PurpurWorldConfig {
creeperHealthRadius = getBoolean("mobs.creeper.health-impacts-explosion", creeperHealthRadius);
creeperAlwaysDropExp = getBoolean("mobs.creeper.always-drop-exp", creeperAlwaysDropExp);
creeperHeadVisibilityPercent = getDouble("mobs.creeper.head-visibility-percent", creeperHeadVisibilityPercent);
+ creeperEncircleTarget = getBoolean("mobs.creeper.encircle-target", creeperEncircleTarget);
}
public boolean dolphinRidable = false;

View File

@@ -0,0 +1,92 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Racci <90304606+DaRacci@users.noreply.github.com>
Date: Fri, 4 Feb 2022 16:10:21 +1100
Subject: [PATCH] Fire Immunity API
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
index 7e94f52f4086331401e35b6814709054e26d85b6..2ff961220e161d06a11bfb497a83ced150048402 100644
--- a/src/main/java/net/minecraft/world/entity/Entity.java
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
@@ -428,6 +428,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
private UUID originWorld;
public boolean freezeLocked = false; // Paper - Freeze Tick Lock API
public boolean fixedPose = false; // Paper - Expand Pose API
+ public @Nullable Boolean immuneToFire = null; // Purpur - Fire immune API
public void setOrigin(@javax.annotation.Nonnull Location location) {
this.origin = location.toVector();
@@ -1651,7 +1652,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
}
public boolean fireImmune() {
- return this.getType().fireImmune();
+ return this.immuneToFire != null ? immuneToFire : this.getType().fireImmune(); // Purpur - add fire immune API
}
public boolean causeFallDamage(float fallDistance, float damageMultiplier, DamageSource damageSource) {
@@ -2361,6 +2362,11 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
nbttagcompound.putBoolean("Paper.FreezeLock", true);
}
// Paper end
+ // Purpur start
+ if (immuneToFire != null) {
+ nbttagcompound.putBoolean("Purpur.FireImmune", immuneToFire);
+ }
+ // Purpur end
return nbttagcompound;
} catch (Throwable throwable) {
CrashReport crashreport = CrashReport.forThrowable(throwable, "Saving entity NBT");
@@ -2508,6 +2514,11 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
freezeLocked = nbt.getBoolean("Paper.FreezeLock");
}
// Paper end
+ // Purpur start
+ if (nbt.contains("Purpur.FireImmune")) {
+ immuneToFire = nbt.getBoolean("Purpur.FireImmune");
+ }
+ // Purpur end
} catch (Throwable throwable) {
CrashReport crashreport = CrashReport.forThrowable(throwable, "Loading entity NBT");
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
index 4c1303c5b9f631efd9497cf893a6ca0348157f2c..31a696de166e1f4d8e5a67cd92427cbda2b8eeb2 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
@@ -86,6 +86,16 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity {
this.entityType = CraftEntityType.minecraftToBukkit(entity.getType());
}
+ @Override
+ public boolean isImmuneToFire() {
+ return getHandle().fireImmune();
+ }
+
+ @Override
+ public void setImmuneToFire(Boolean fireImmune) {
+ getHandle().immuneToFire = fireImmune;
+ }
+
@Override
public boolean isInDaylight() {
return getHandle().isSunBurnTick();
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java
index 01e4395f1669d21c30465aa1366bd2f1ae17678f..5c1cda88080850314dac196dbe71ff12e48a8aca 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java
@@ -173,9 +173,14 @@ public class CraftItem extends CraftEntity implements Item {
return this.getHandle().immuneToExplosion;
}
+ @Override
+ public void setImmuneToFire(@org.jetbrains.annotations.Nullable Boolean immuneToFire) {
+ this.getHandle().immuneToFire = (immuneToFire != null && immuneToFire);
+ }
+
@Override
public void setImmuneToFire(boolean immuneToFire) {
- item.immuneToFire = immuneToFire;
+ this.setImmuneToFire((Boolean) immuneToFire);
}
@Override

View File

@@ -0,0 +1,38 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: BillyGalbreath <blake.galbreath@gmail.com>
Date: Sun, 13 Nov 2022 05:05:34 -0600
Subject: [PATCH] Add option to teleport to spawn on nether ceiling damage
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
index 2ff961220e161d06a11bfb497a83ced150048402..4c30eb5b4557226f49968ababb1fe66065ecc486 100644
--- a/src/main/java/net/minecraft/world/entity/Entity.java
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
@@ -833,6 +833,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
&& this.level.paperConfig().environment.netherCeilingVoidDamageHeight.test(v -> this.getY() >= v)
&& (!(this instanceof Player player) || !player.getAbilities().invulnerable))) {
// Paper end - Configurable nether ceiling damage
+ if (this.level().purpurConfig.teleportOnNetherCeilingDamage && this.level.getWorld().getEnvironment() == org.bukkit.World.Environment.NETHER && this instanceof ServerPlayer player) player.teleport(io.papermc.paper.util.MCUtil.toLocation(this.level, this.level.getSharedSpawnPos())); else // Purpur
this.onBelowWorld();
}
diff --git a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
index 1c6d34c1d186c561666ac0f3b7e358652e21f1bb..780a70df21bef34942c2f1cdf0d1613d4bab94fc 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
@@ -410,6 +410,7 @@ public class PurpurWorldConfig {
public String playerDeathExpDropEquation = "expLevel * 7";
public int playerDeathExpDropMax = 100;
public boolean teleportIfOutsideBorder = false;
+ public boolean teleportOnNetherCeilingDamage = false;
public boolean totemOfUndyingWorksInInventory = false;
public boolean creativeOnePunch = false;
public boolean playerSleepNearMonsters = false;
@@ -435,6 +436,7 @@ public class PurpurWorldConfig {
playerDeathExpDropEquation = getString("gameplay-mechanics.player.exp-dropped-on-death.equation", playerDeathExpDropEquation);
playerDeathExpDropMax = getInt("gameplay-mechanics.player.exp-dropped-on-death.maximum", playerDeathExpDropMax);
teleportIfOutsideBorder = getBoolean("gameplay-mechanics.player.teleport-if-outside-border", teleportIfOutsideBorder);
+ teleportOnNetherCeilingDamage = getBoolean("gameplay-mechanics.player.teleport-on-nether-ceiling-damage", teleportOnNetherCeilingDamage);
totemOfUndyingWorksInInventory = getBoolean("gameplay-mechanics.player.totem-of-undying-works-in-inventory", totemOfUndyingWorksInInventory);
creativeOnePunch = getBoolean("gameplay-mechanics.player.one-punch-in-creative", creativeOnePunch);
playerSleepNearMonsters = getBoolean("gameplay-mechanics.player.sleep-ignore-nearby-mobs", playerSleepNearMonsters);

View File

@@ -0,0 +1,18 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: SageSphinx63920 <sage@sagesphinx63920.dev>
Date: Sat, 29 Oct 2022 00:06:41 +0200
Subject: [PATCH] Added got ram event
diff --git a/src/main/java/net/minecraft/world/entity/animal/goat/Goat.java b/src/main/java/net/minecraft/world/entity/animal/goat/Goat.java
index fab01a3e779e39962ef04305540e2fe3043072a2..e3a018f05c7c0019a076283a5217cca3acb0161b 100644
--- a/src/main/java/net/minecraft/world/entity/animal/goat/Goat.java
+++ b/src/main/java/net/minecraft/world/entity/animal/goat/Goat.java
@@ -428,6 +428,7 @@ public class Goat extends Animal {
// Paper start - Goat ram API
public void ram(net.minecraft.world.entity.LivingEntity entity) {
+ if(!new org.purpurmc.purpur.event.entity.GoatRamEntityEvent((org.bukkit.entity.Goat) getBukkitEntity(), (org.bukkit.entity.LivingEntity) entity.getBukkitLivingEntity()).callEvent()) return; // Purpur
Brain<Goat> brain = this.getBrain();
brain.setMemory(MemoryModuleType.RAM_TARGET, entity.position());
brain.eraseMemory(MemoryModuleType.RAM_COOLDOWN_TICKS);

View File

@@ -0,0 +1,23 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: BillyGalbreath <blake.galbreath@gmail.com>
Date: Thu, 24 Nov 2022 11:00:37 -0600
Subject: [PATCH] Log skipped entity's position
diff --git a/src/main/java/net/minecraft/world/entity/EntityType.java b/src/main/java/net/minecraft/world/entity/EntityType.java
index 831da897fd422df8e57487017871e841cbc95d00..d2e98ad9db7c0fc8c516f64febe9be0425b0e774 100644
--- a/src/main/java/net/minecraft/world/entity/EntityType.java
+++ b/src/main/java/net/minecraft/world/entity/EntityType.java
@@ -625,6 +625,12 @@ public class EntityType<T extends Entity> implements FeatureElement, EntityTypeT
entity.load(nbt);
}, () -> {
EntityType.LOGGER.warn("Skipping Entity with id {}", nbt.getString("id"));
+ // Purpur start - log skipped entity's position
+ try {
+ ListTag pos = nbt.getList("Pos", 6);
+ EntityType.LOGGER.warn("Location: {} {},{},{}", world.getWorld().getName(), pos.getDouble(0), pos.getDouble(1), pos.getDouble(2));
+ } catch (Throwable ignore) {}
+ // Purpur end
});
}

View File

@@ -0,0 +1,38 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: BillyGalbreath <blake.galbreath@gmail.com>
Date: Thu, 15 Dec 2022 11:42:15 -0600
Subject: [PATCH] End Crystal Cramming
diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EndCrystal.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EndCrystal.java
index 02f1d0418395b100cabfad7294466aaad34ac7c6..c0275197cc9aab2a49d88476e072a94f8e17e9ee 100644
--- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EndCrystal.java
+++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EndCrystal.java
@@ -102,6 +102,7 @@ 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
}
// Purpur start
diff --git a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
index 780a70df21bef34942c2f1cdf0d1613d4bab94fc..495bf6d8c5898410a955a8a0a9298c4919a7d65b 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
@@ -937,6 +937,7 @@ public class PurpurWorldConfig {
public double basedEndCrystalExplosionPower = 6.0D;
public boolean basedEndCrystalExplosionFire = false;
public net.minecraft.world.level.Level.ExplosionInteraction basedEndCrystalExplosionEffect = net.minecraft.world.level.Level.ExplosionInteraction.BLOCK;
+ public int endCrystalCramming = 0;
private void endCrystalSettings() {
if (PurpurConfig.version < 31) {
if ("DESTROY".equals(getString("blocks.end-crystal.baseless.explosion-effect", baselessEndCrystalExplosionEffect.name()))) {
@@ -964,6 +965,7 @@ public class PurpurWorldConfig {
log(Level.SEVERE, "Unknown value for `blocks.end-crystal.base.explosion-effect`! Using default of `BLOCK`");
basedEndCrystalExplosionEffect = net.minecraft.world.level.Level.ExplosionInteraction.BLOCK;
}
+ endCrystalCramming = getInt("blocks.end-crystal.cramming-amount", endCrystalCramming);
}
public boolean farmlandBypassMobGriefing = false;

View File

@@ -0,0 +1,55 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: 12emin34 <macanovic.emin@gmail.com>
Date: Mon, 26 Dec 2022 19:10:43 +0100
Subject: [PATCH] Option to allow beacon effects when covered by tinted glass
diff --git a/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java
index d1fb77d83d48183a9a37dbeec7bb0fda623d7e9b..df02a78855f1d0c32d1f744c20803fc97a8085c0 100644
--- a/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java
+++ b/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java
@@ -178,6 +178,7 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider, Name
int j = pos.getY();
int k = pos.getZ();
BlockPos blockposition1;
+ boolean isTintedGlass = false;
if (blockEntity.lastCheckY < j) {
blockposition1 = pos;
@@ -211,6 +212,9 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider, Name
}
}
} else {
+ if (world.purpurConfig.beaconAllowEffectsWithTintedGlass && block.equals(Blocks.TINTED_GLASS)) {
+ isTintedGlass = true;
+ }
if (tileentitybeacon_beaconcolortracker == null || iblockdata1.getLightBlock(world, blockposition1) >= 15 && !iblockdata1.is(Blocks.BEDROCK)) {
blockEntity.checkingBeamSections.clear();
blockEntity.lastCheckY = l;
@@ -230,7 +234,7 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider, Name
blockEntity.levels = BeaconBlockEntity.updateBase(world, i, j, k);
}
- if (blockEntity.levels > 0 && !blockEntity.beamSections.isEmpty()) {
+ if (blockEntity.levels > 0 && (!blockEntity.beamSections.isEmpty() || (world.purpurConfig.beaconAllowEffectsWithTintedGlass && isTintedGlass))) {
BeaconBlockEntity.applyEffects(world, pos, blockEntity.levels, blockEntity.primaryPower, blockEntity.secondaryPower, blockEntity); // Paper - Custom beacon ranges
BeaconBlockEntity.playSound(world, pos, SoundEvents.BEACON_AMBIENT);
}
diff --git a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
index 495bf6d8c5898410a955a8a0a9298c4919a7d65b..88a1843a19967683ce0470c7f6c17f02179ac556 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
@@ -836,11 +836,13 @@ public class PurpurWorldConfig {
public int beaconLevelTwo = 30;
public int beaconLevelThree = 40;
public int beaconLevelFour = 50;
+ public boolean beaconAllowEffectsWithTintedGlass = false;
private void beaconSettings() {
beaconLevelOne = getInt("blocks.beacon.effect-range.level-1", beaconLevelOne);
beaconLevelTwo = getInt("blocks.beacon.effect-range.level-2", beaconLevelTwo);
beaconLevelThree = getInt("blocks.beacon.effect-range.level-3", beaconLevelThree);
beaconLevelFour = getInt("blocks.beacon.effect-range.level-4", beaconLevelFour);
+ beaconAllowEffectsWithTintedGlass = getBoolean("blocks.beacon.allow-effects-with-tinted-glass", beaconAllowEffectsWithTintedGlass);
}
public boolean bedExplode = true;

View File

@@ -0,0 +1,61 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com>
Date: Thu, 27 Oct 2022 23:12:45 -0400
Subject: [PATCH] Add attribute clamping and armor limit config
diff --git a/src/main/java/net/minecraft/world/damagesource/CombatRules.java b/src/main/java/net/minecraft/world/damagesource/CombatRules.java
index 064c1e33f3feee77837bb57887877ae1ca39548d..ffd009bca3fdbfd0b14df78072ef8d472a57cd65 100644
--- a/src/main/java/net/minecraft/world/damagesource/CombatRules.java
+++ b/src/main/java/net/minecraft/world/damagesource/CombatRules.java
@@ -15,7 +15,7 @@ public class CombatRules {
public static float getDamageAfterAbsorb(LivingEntity armorWearer, float damageAmount, DamageSource damageSource, float armor, float armorToughness) {
float f = 2.0F + armorToughness / 4.0F;
- float g = Mth.clamp(armor - damageAmount / f, armor * 0.2F, 20.0F);
+ float g = Mth.clamp(armor - damageAmount / f, armor * 0.2F, org.purpurmc.purpur.PurpurConfig.limitArmor ? 20F : Float.MAX_VALUE); // Purpur
float h = g / 25.0F;
ItemStack itemStack = damageSource.getWeaponItem();
float i;
@@ -30,7 +30,7 @@ public class CombatRules {
}
public static float getDamageAfterMagicAbsorb(float damageDealt, float protection) {
- float f = Mth.clamp(protection, 0.0F, 20.0F);
+ float f = Mth.clamp(protection, 0.0F, org.purpurmc.purpur.PurpurConfig.limitArmor ? 20F : Float.MAX_VALUE); // Purpur
return damageDealt * (1.0F - f / 25.0F);
}
}
diff --git a/src/main/java/net/minecraft/world/entity/ai/attributes/RangedAttribute.java b/src/main/java/net/minecraft/world/entity/ai/attributes/RangedAttribute.java
index f0703302e7dbbda88de8c648d20d87c55ed9b1e0..a913ebabaa5f443afa987b972355a8f8d1723c78 100644
--- a/src/main/java/net/minecraft/world/entity/ai/attributes/RangedAttribute.java
+++ b/src/main/java/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
return Double.isNaN(value) ? this.minValue : Mth.clamp(value, this.minValue, this.maxValue);
}
}
diff --git a/src/main/java/org/purpurmc/purpur/PurpurConfig.java b/src/main/java/org/purpurmc/purpur/PurpurConfig.java
index c6757db82626e98a76ad430dcca1f20c2a9c9684..920dc26d4485f3c12d237c2b55e3d70671246ddc 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurConfig.java
@@ -492,6 +492,16 @@ public class PurpurConfig {
usernameValidCharactersPattern = java.util.regex.Pattern.compile(setPattern == null || setPattern.isBlank() ? defaultPattern : setPattern);
}
+ public static boolean clampAttributes = true;
+ private static void clampAttributes() {
+ clampAttributes = getBoolean("settings.clamp-attributes", clampAttributes);
+ }
+
+ public static boolean limitArmor = true;
+ private static void limitArmor() {
+ limitArmor = getBoolean("settings.limit-armor", limitArmor);
+ }
+
private static void blastResistanceSettings() {
getMap("settings.blast-resistance-overrides", Collections.emptyMap()).forEach((blockId, value) -> {
Block block = BuiltInRegistries.BLOCK.get(ResourceLocation.withDefaultNamespace(blockId));

View File

@@ -0,0 +1,44 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Nico314159 <nicolino.will@gmail.com>
Date: Mon, 9 Jan 2023 19:45:55 -0500
Subject: [PATCH] Config to remove explosion radius clamp
diff --git a/src/main/java/net/minecraft/world/level/Explosion.java b/src/main/java/net/minecraft/world/level/Explosion.java
index bff83fe413c7baef4ba56a3270ea4463a58c792f..c3bd4bcf79ef1ad28bb5651271144668e11f780b 100644
--- a/src/main/java/net/minecraft/world/level/Explosion.java
+++ b/src/main/java/net/minecraft/world/level/Explosion.java
@@ -99,7 +99,7 @@ public class Explosion {
this.hitPlayers = Maps.newHashMap();
this.level = world;
this.source = entity;
- this.radius = (float) Math.max(power, 0.0); // CraftBukkit - clamp bad values
+ this.radius = (float) (world == null || world.purpurConfig.explosionClampRadius ? Math.max(power, 0.0) : power); // CraftBukkit - clamp bad values // Purpur
this.x = x;
this.y = y;
this.z = z;
@@ -162,7 +162,7 @@ public class Explosion {
public void explode() {
// CraftBukkit start
- if (this.radius < 0.1F) {
+ if ((this.level == null || this.level.purpurConfig.explosionClampRadius) && this.radius < 0.1F) { // Purpur
return;
}
// CraftBukkit end
diff --git a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
index 88a1843a19967683ce0470c7f6c17f02179ac556..06ef23a5be69952876e539cd2ff785dae0d19caf 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
@@ -217,6 +217,11 @@ public class PurpurWorldConfig {
entitySharedRandom = getBoolean("settings.entity.shared-random", entitySharedRandom);
}
+ public boolean explosionClampRadius = true;
+ private void explosionSettings() {
+ explosionClampRadius = getBoolean("gameplay-mechanics.clamp-explosion-radius", explosionClampRadius);
+ }
+
public List<Item> itemImmuneToCactus = new ArrayList<>();
public List<Item> itemImmuneToExplosion = new ArrayList<>();
public List<Item> itemImmuneToFire = new ArrayList<>();

View File

@@ -0,0 +1,163 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: granny <granny@purpurmc.org>
Date: Thu, 9 Feb 2023 00:28:03 -0800
Subject: [PATCH] bonemealable sugarcane, cactus, and netherwart
diff --git a/src/main/java/net/minecraft/world/level/block/CactusBlock.java b/src/main/java/net/minecraft/world/level/block/CactusBlock.java
index 9200d75b05ce535f7b7f5c1572cd8f6261c6955b..066181ed274a492762baebf05bf51ac7848878cc 100644
--- a/src/main/java/net/minecraft/world/level/block/CactusBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/CactusBlock.java
@@ -23,7 +23,7 @@ import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.VoxelShape;
import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit
-public class CactusBlock extends Block {
+public class CactusBlock extends Block implements BonemealableBlock { // Purpur
public static final MapCodec<CactusBlock> CODEC = simpleCodec(CactusBlock::new);
public static final IntegerProperty AGE = BlockStateProperties.AGE_15;
@@ -134,4 +134,34 @@ public class CactusBlock extends Block {
protected boolean isPathfindable(BlockState state, PathComputationType type) {
return false;
}
+
+ // Purpur start
+ @Override
+ public boolean isValidBonemealTarget(final LevelReader world, final BlockPos pos, final BlockState state) {
+ if (!((Level) world).purpurConfig.cactusAffectedByBonemeal || !world.isEmptyBlock(pos.above())) return false;
+
+ int cactusHeight = 0;
+ while (world.getBlockState(pos.below(cactusHeight)).is(this)) {
+ cactusHeight++;
+ }
+
+ return cactusHeight < ((Level) world).paperConfig().maxGrowthHeight.cactus;
+ }
+
+ @Override
+ public boolean isBonemealSuccess(Level world, RandomSource random, BlockPos pos, BlockState state) {
+ return true;
+ }
+
+ @Override
+ public void performBonemeal(ServerLevel world, RandomSource random, BlockPos pos, BlockState state) {
+ int cactusHeight = 0;
+ while (world.getBlockState(pos.below(cactusHeight)).is(this)) {
+ cactusHeight++;
+ }
+ for (int i = 0; i <= world.paperConfig().maxGrowthHeight.cactus - cactusHeight; i++) {
+ world.setBlockAndUpdate(pos.above(i), state.setValue(CactusBlock.AGE, 0));
+ }
+ }
+ // Purpur end
}
diff --git a/src/main/java/net/minecraft/world/level/block/NetherWartBlock.java b/src/main/java/net/minecraft/world/level/block/NetherWartBlock.java
index da1c7999ca64199387054de46489d3ff4a299289..b8355ea1de26c4b6905f477fb4e110f1762447b4 100644
--- a/src/main/java/net/minecraft/world/level/block/NetherWartBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/NetherWartBlock.java
@@ -16,7 +16,7 @@ import net.minecraft.world.level.block.state.properties.IntegerProperty;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.VoxelShape;
-public class NetherWartBlock extends BushBlock {
+public class NetherWartBlock extends BushBlock implements BonemealableBlock { // Purpur
public static final MapCodec<NetherWartBlock> CODEC = simpleCodec(NetherWartBlock::new);
public static final int MAX_AGE = 3;
@@ -78,5 +78,22 @@ public class NetherWartBlock extends BushBlock {
super.playerDestroy(world, player, pos, state, blockEntity, itemInHand, includeDrops, dropExp);
}
}
+
+ @Override
+ public boolean isValidBonemealTarget(final net.minecraft.world.level.LevelReader world, final BlockPos pos, final BlockState state) {
+ return ((net.minecraft.world.level.Level) world).purpurConfig.netherWartAffectedByBonemeal && state.getValue(NetherWartBlock.AGE) < 3;
+ }
+
+ @Override
+ public boolean isBonemealSuccess(net.minecraft.world.level.Level world, RandomSource random, BlockPos pos, BlockState state) {
+ return true;
+ }
+
+ @Override
+ public void performBonemeal(ServerLevel world, RandomSource random, BlockPos pos, BlockState state) {
+ int i = Math.min(3, state.getValue(NetherWartBlock.AGE) + 1);
+ state = state.setValue(NetherWartBlock.AGE, i);
+ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockGrowEvent(world, pos, state, 2); // CraftBukkit
+ }
// Purpur end
}
diff --git a/src/main/java/net/minecraft/world/level/block/SugarCaneBlock.java b/src/main/java/net/minecraft/world/level/block/SugarCaneBlock.java
index c48c622e92cedeaa46b929c7adfedec98dd5a3fb..6449b5c424443b5f0ee7e3fce803449418fbed2a 100644
--- a/src/main/java/net/minecraft/world/level/block/SugarCaneBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/SugarCaneBlock.java
@@ -20,7 +20,7 @@ import net.minecraft.world.level.material.FluidState;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.VoxelShape;
-public class SugarCaneBlock extends Block {
+public class SugarCaneBlock extends Block implements BonemealableBlock { // Purpur
public static final MapCodec<SugarCaneBlock> CODEC = simpleCodec(SugarCaneBlock::new);
public static final IntegerProperty AGE = BlockStateProperties.AGE_15;
@@ -113,4 +113,34 @@ public class SugarCaneBlock extends Block {
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
builder.add(SugarCaneBlock.AGE);
}
+
+ // Purpur start
+ @Override
+ public boolean isValidBonemealTarget(final LevelReader world, final BlockPos pos, final BlockState state) {
+ if (!((net.minecraft.world.level.Level) world).purpurConfig.sugarCanAffectedByBonemeal || !world.isEmptyBlock(pos.above())) return false;
+
+ int reedHeight = 0;
+ while (world.getBlockState(pos.below(reedHeight)).is(this)) {
+ reedHeight++;
+ }
+
+ return reedHeight < ((net.minecraft.world.level.Level) world).paperConfig().maxGrowthHeight.reeds;
+ }
+
+ @Override
+ public boolean isBonemealSuccess(net.minecraft.world.level.Level world, RandomSource random, BlockPos pos, BlockState state) {
+ return true;
+ }
+
+ @Override
+ public void performBonemeal(ServerLevel world, RandomSource random, BlockPos pos, BlockState state) {
+ int reedHeight = 0;
+ while (world.getBlockState(pos.below(reedHeight)).is(this)) {
+ reedHeight++;
+ }
+ for (int i = 0; i <= world.paperConfig().maxGrowthHeight.reeds - reedHeight; i++) {
+ world.setBlockAndUpdate(pos.above(i), state.setValue(SugarCaneBlock.AGE, 0));
+ }
+ }
+ // Purpur end
}
diff --git a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
index 06ef23a5be69952876e539cd2ff785dae0d19caf..62328bd56578789dd898b203396d37a76e75f1e4 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
@@ -890,8 +890,20 @@ public class PurpurWorldConfig {
}
public boolean cactusBreaksFromSolidNeighbors = true;
+ public boolean cactusAffectedByBonemeal = false;
private void cactusSettings() {
cactusBreaksFromSolidNeighbors = getBoolean("blocks.cactus.breaks-from-solid-neighbors", cactusBreaksFromSolidNeighbors);
+ cactusAffectedByBonemeal = getBoolean("blocks.cactus.affected-by-bonemeal", cactusAffectedByBonemeal);
+ }
+
+ public boolean sugarCanAffectedByBonemeal = false;
+ private void sugarCaneSettings() {
+ sugarCanAffectedByBonemeal = getBoolean("blocks.sugar_cane.affected-by-bonemeal", sugarCanAffectedByBonemeal);
+ }
+
+ public boolean netherWartAffectedByBonemeal = false;
+ private void netherWartSettings() {
+ netherWartAffectedByBonemeal = getBoolean("blocks.nether_wart.affected-by-bonemeal", netherWartAffectedByBonemeal);
}
public boolean campFireLitWhenPlaced = true;

View File

@@ -0,0 +1,36 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: SageSphinx63920 <sage@sagesphinx63920.dev>
Date: Mon, 26 Dec 2022 23:42:37 +0100
Subject: [PATCH] Add PreExplodeEvents
diff --git a/src/main/java/net/minecraft/world/level/Explosion.java b/src/main/java/net/minecraft/world/level/Explosion.java
index c3bd4bcf79ef1ad28bb5651271144668e11f780b..2429f6525623e5a052a92479486328f49c3f1ba3 100644
--- a/src/main/java/net/minecraft/world/level/Explosion.java
+++ b/src/main/java/net/minecraft/world/level/Explosion.java
@@ -166,6 +166,25 @@ public class Explosion {
return;
}
// CraftBukkit end
+
+ // Purpur start - add PreExplodeEvents
+ if(this.source != null){
+ Location location = new Location(this.level.getWorld(), this.x, this.y, this.z);
+ if(!new org.purpurmc.purpur.event.entity.PreEntityExplodeEvent(this.source.getBukkitEntity(), location, this.blockInteraction == Explosion.BlockInteraction.DESTROY_WITH_DECAY ? 1.0F / this.radius : 1.0F).callEvent()) {
+ this.wasCanceled = true;
+ return;
+ }
+ }else {
+ Location location = new Location(this.level.getWorld(), this.x, this.y, this.z);
+ org.bukkit.block.Block block = location.getBlock();
+ org.bukkit.block.BlockState blockState = (this.damageSource.getDirectBlockState() != null) ? this.damageSource.getDirectBlockState() : block.getState();
+ if(!new org.purpurmc.purpur.event.PreBlockExplodeEvent(location.getBlock(), this.blockInteraction == Explosion.BlockInteraction.DESTROY_WITH_DECAY ? 1.0F / this.radius : 1.0F, blockState).callEvent()) {
+ this.wasCanceled = true;
+ return;
+ }
+ }
+ //Purpur end
+
this.level.gameEvent(this.source, (Holder) GameEvent.EXPLODE, new Vec3(this.x, this.y, this.z));
Set<BlockPos> set = Sets.newHashSet();
boolean flag = true;

View File

@@ -0,0 +1,131 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Parker Hawke <hawkeboyz2@hotmail.com>
Date: Sat, 27 Jun 2020 18:43:37 -0400
Subject: [PATCH] Improve output of plugins command
Co-authored-by: Oharass <oharass@bk.ru>
Co-authored-by: granny <granny@purpurmc.org>
diff --git a/src/main/java/io/papermc/paper/command/PaperPluginsCommand.java b/src/main/java/io/papermc/paper/command/PaperPluginsCommand.java
index f0fce4113fb07c64adbec029d177c236cbdcbae8..e94224ed280247ee69dfdff8dc960f2b8729be33 100644
--- a/src/main/java/io/papermc/paper/command/PaperPluginsCommand.java
+++ b/src/main/java/io/papermc/paper/command/PaperPluginsCommand.java
@@ -78,10 +78,10 @@ public class PaperPluginsCommand extends BukkitCommand {
this.setAliases(Arrays.asList("pl"));
}
- private static <T> List<Component> formatProviders(TreeMap<String, PluginProvider<T>> plugins) {
+ private static <T> List<Component> formatProviders(TreeMap<String, PluginProvider<T>> plugins, @NotNull CommandSender sender) { // Purpur
List<Component> components = new ArrayList<>(plugins.size());
for (PluginProvider<T> entry : plugins.values()) {
- components.add(formatProvider(entry));
+ components.add(formatProvider(entry, sender)); // Purpur
}
boolean isFirst = true;
@@ -109,7 +109,7 @@ public class PaperPluginsCommand extends BukkitCommand {
return formattedSublists;
}
- private static Component formatProvider(PluginProvider<?> provider) {
+ private static Component formatProvider(PluginProvider<?> provider, @NotNull CommandSender sender) { // Purpur
TextComponent.Builder builder = Component.text();
if (provider instanceof SpigotPluginProvider spigotPluginProvider && CraftMagicNumbers.isLegacy(spigotPluginProvider.getMeta())) {
builder.append(LEGACY_PLUGIN_STAR);
@@ -117,12 +117,64 @@ public class PaperPluginsCommand extends BukkitCommand {
String name = provider.getMeta().getName();
Component pluginName = Component.text(name, fromStatus(provider))
- .clickEvent(ClickEvent.runCommand("/version " + name));
+ // Purpur start
+ .clickEvent(ClickEvent.suggestCommand("/version " + name));
+
+ if (sender instanceof org.bukkit.entity.Player && sender.hasPermission("bukkit.command.version")) {
+ // Event components
+ String description = provider.getMeta().getDescription();
+ TextComponent.Builder hover = Component.text();
+ hover.append(Component.text("Version: ", NamedTextColor.WHITE)).append(Component.text(provider.getMeta().getVersion(), NamedTextColor.GREEN));
+
+ if (description != null) {
+ hover.append(Component.newline())
+ .append(Component.text("Description: ", NamedTextColor.WHITE))
+ .append(Component.text(description, NamedTextColor.GREEN));
+ }
+
+ if (provider.getMeta().getWebsite() != null) {
+ hover.append(Component.newline())
+ .append(Component.text("Website: ", NamedTextColor.WHITE))
+ .append(Component.text(provider.getMeta().getWebsite(), NamedTextColor.GREEN));
+ }
+
+ if (!provider.getMeta().getAuthors().isEmpty()) {
+ hover.append(Component.newline());
+ if (provider.getMeta().getAuthors().size() == 1) {
+ hover.append(Component.text("Author: "));
+ } else {
+ hover.append(Component.text("Authors: "));
+ }
+
+ hover.append(getAuthors(provider.getMeta()));
+ }
+
+ pluginName.hoverEvent(hover.build());
+ }
builder.append(pluginName);
+ // Purpur end
+
+ return builder.build();
+ }
+
+ // Purpur start
+ @NotNull
+ private static TextComponent getAuthors(@NotNull final PluginMeta pluginMeta) {
+ TextComponent.Builder builder = Component.text();
+ List<String> authors = pluginMeta.getAuthors();
+
+ for (int i = 0; i < authors.size(); i++) {
+ if (i > 0) {
+ builder.append(Component.text(i < authors.size() - 1 ? ", " : " and ", NamedTextColor.WHITE));
+ }
+
+ builder.append(Component.text(authors.get(i), NamedTextColor.GREEN));
+ }
return builder.build();
}
+ // Purpur end
private static Component asPlainComponents(String strings) {
net.kyori.adventure.text.TextComponent.Builder builder = Component.text();
@@ -182,24 +234,24 @@ public class PaperPluginsCommand extends BukkitCommand {
}
}
- Component infoMessage = Component.text("Server Plugins (%s):".formatted(paperPlugins.size() + spigotPlugins.size()), NamedTextColor.WHITE);
+ //Component infoMessage = Component.text("Server Plugins (%s):".formatted(paperPlugins.size() + spigotPlugins.size()), NamedTextColor.WHITE);
//.append(INFO_ICON_START.hoverEvent(SERVER_PLUGIN_INFO)); TODO: Add docs
- sender.sendMessage(infoMessage);
+ //sender.sendMessage(infoMessage); // Purpur
if (!paperPlugins.isEmpty()) {
- sender.sendMessage(PAPER_HEADER);
+ sender.sendMessage(PAPER_HEADER.append(Component.text(" (%s):".formatted(paperPlugins.size())))); // Purpur
}
- for (Component component : formatProviders(paperPlugins)) {
+ for (Component component : formatProviders(paperPlugins, sender)) { // Purpur
sender.sendMessage(component);
}
if (!spigotPlugins.isEmpty()) {
- sender.sendMessage(BUKKIT_HEADER);
+ sender.sendMessage(BUKKIT_HEADER.append(Component.text(" (%s):".formatted(spigotPlugins.size())))); // Purpur
}
- for (Component component : formatProviders(spigotPlugins)) {
+ for (Component component : formatProviders(spigotPlugins, sender)) { // Purpur
sender.sendMessage(component);
}

View File

@@ -0,0 +1,421 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: William Blake Galbreath <blake.galbreath@gmail.com>
Date: Thu, 16 Jan 2020 14:59:16 -0600
Subject: [PATCH] Make GUI Great Again
diff --git a/src/log4jPlugins/java/org/purpurmc/purpur/gui/HighlightErrorConverter.java b/src/log4jPlugins/java/org/purpurmc/purpur/gui/HighlightErrorConverter.java
new file mode 100644
index 0000000000000000000000000000000000000000..15a226e3854d731f7724025ea3459c8ace07630c
--- /dev/null
+++ b/src/log4jPlugins/java/org/purpurmc/purpur/gui/HighlightErrorConverter.java
@@ -0,0 +1,85 @@
+package org.purpurmc.purpur.gui.util;
+
+import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.core.LogEvent;
+import org.apache.logging.log4j.core.config.Configuration;
+import org.apache.logging.log4j.core.config.plugins.Plugin;
+import org.apache.logging.log4j.core.layout.PatternLayout;
+import org.apache.logging.log4j.core.pattern.ConverterKeys;
+import org.apache.logging.log4j.core.pattern.LogEventPatternConverter;
+import org.apache.logging.log4j.core.pattern.PatternConverter;
+import org.apache.logging.log4j.core.pattern.PatternFormatter;
+import org.apache.logging.log4j.core.pattern.PatternParser;
+import org.apache.logging.log4j.util.PerformanceSensitive;
+
+import java.util.List;
+
+@Plugin(name = "highlightGUIError", category = PatternConverter.CATEGORY)
+@ConverterKeys({"highlightGUIError"})
+@PerformanceSensitive("allocation")
+public final class HighlightErrorConverter extends LogEventPatternConverter {
+ private static final String ERROR = "\u00A74\u00A7l"; // Bold Red
+ private static final String WARN = "\u00A7e\u00A7l"; // Bold Yellow
+
+ private final List<PatternFormatter> formatters;
+
+ private HighlightErrorConverter(List<PatternFormatter> formatters) {
+ super("highlightGUIError", null);
+ this.formatters = formatters;
+ }
+
+ @Override
+ public void format(LogEvent event, StringBuilder toAppendTo) {
+ Level level = event.getLevel();
+ if (level.isMoreSpecificThan(Level.ERROR)) {
+ format(ERROR, event, toAppendTo);
+ return;
+ } else if (level.isMoreSpecificThan(Level.WARN)) {
+ format(WARN, event, toAppendTo);
+ return;
+ }
+ for (PatternFormatter formatter : formatters) {
+ formatter.format(event, toAppendTo);
+ }
+ }
+
+ private void format(String style, LogEvent event, StringBuilder toAppendTo) {
+ int start = toAppendTo.length();
+ toAppendTo.append(style);
+ int end = toAppendTo.length();
+
+ for (PatternFormatter formatter : formatters) {
+ formatter.format(event, toAppendTo);
+ }
+
+ if (toAppendTo.length() == end) {
+ toAppendTo.setLength(start);
+ }
+ }
+
+ @Override
+ public boolean handlesThrowable() {
+ for (final PatternFormatter formatter : formatters) {
+ if (formatter.handlesThrowable()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public static HighlightErrorConverter newInstance(Configuration config, String[] options) {
+ if (options.length != 1) {
+ LOGGER.error("Incorrect number of options on highlightGUIError. Expected 1 received " + options.length);
+ return null;
+ }
+
+ if (options[0] == null) {
+ LOGGER.error("No pattern supplied on highlightGUIError");
+ return null;
+ }
+
+ PatternParser parser = PatternLayout.createPatternParser(config);
+ List<PatternFormatter> formatters = parser.parse(options[0]);
+ return new HighlightErrorConverter(formatters);
+ }
+}
diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
index 7a579cdb6bb9dced485f86d1bfe8ab432db51ab1..931da957b34dc2d84f52de3d9e790c811a2a075a 100644
--- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
+++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
@@ -114,6 +114,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface
return;
}
// Paper start - Use TerminalConsoleAppender
+ if (DedicatedServer.this.gui == null || System.console() != null) // Purpur - has no GUI or has console (did not double-click)
new com.destroystokyo.paper.console.PaperConsole(DedicatedServer.this).start();
/*
jline.console.ConsoleReader bufferedreader = DedicatedServer.this.reader;
diff --git a/src/main/java/net/minecraft/server/gui/MinecraftServerGui.java b/src/main/java/net/minecraft/server/gui/MinecraftServerGui.java
index 759062d219ff490a3cb19e710c4d18e3e08288e0..8f74c2ec5252b6265549589310d742337c91cb2c 100644
--- a/src/main/java/net/minecraft/server/gui/MinecraftServerGui.java
+++ b/src/main/java/net/minecraft/server/gui/MinecraftServerGui.java
@@ -43,6 +43,11 @@ public class MinecraftServerGui extends JComponent {
private Thread logAppenderThread;
private final Collection<Runnable> finalizers = Lists.newArrayList();
final AtomicBoolean isClosing = new AtomicBoolean();
+ // Purpur start
+ private final CommandHistory history = new CommandHistory();
+ private String currentCommand = "";
+ private int historyIndex = 0;
+ // Purpur end
public static MinecraftServerGui showFrameFor(final DedicatedServer server) {
try {
@@ -51,7 +56,7 @@ public class MinecraftServerGui extends JComponent {
;
}
- final JFrame jframe = new JFrame("Minecraft server");
+ final JFrame jframe = new JFrame("Purpur Minecraft server"); // Purpur
final MinecraftServerGui servergui = new MinecraftServerGui(server);
jframe.setDefaultCloseOperation(2);
@@ -59,7 +64,7 @@ public class MinecraftServerGui extends JComponent {
jframe.pack();
jframe.setLocationRelativeTo((Component) null);
jframe.setVisible(true);
- jframe.setName("Minecraft server"); // Paper - Improve ServerGUI
+ jframe.setName("Purpur Minecraft server"); // Paper - Improve ServerGUI // Purpur
// Paper start - Improve ServerGUI
try {
@@ -71,7 +76,7 @@ public class MinecraftServerGui extends JComponent {
jframe.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent windowevent) {
if (!servergui.isClosing.getAndSet(true)) {
- jframe.setTitle("Minecraft server - shutting down!");
+ jframe.setTitle("Purpur Minecraft server - shutting down!"); // Purpur
server.halt(true);
servergui.runFinalizers();
}
@@ -159,7 +164,7 @@ public class MinecraftServerGui extends JComponent {
private JComponent buildChatPanel() {
JPanel jpanel = new JPanel(new BorderLayout());
- JTextArea jtextarea = new JTextArea();
+ org.purpurmc.purpur.gui.JColorTextPane jtextarea = new org.purpurmc.purpur.gui.JColorTextPane(); // Purpur
JScrollPane jscrollpane = new JScrollPane(jtextarea, 22, 30);
jtextarea.setEditable(false);
@@ -171,10 +176,43 @@ public class MinecraftServerGui extends JComponent {
if (!s.isEmpty()) {
this.server.handleConsoleInput(s, this.server.createCommandSourceStack());
+ // Purpur start
+ history.add(s);
+ historyIndex = -1;
+ // Purpur end
}
jtextfield.setText("");
});
+ // Purpur start
+ jtextfield.getInputMap().put(javax.swing.KeyStroke.getKeyStroke("UP"), "up");
+ jtextfield.getInputMap().put(javax.swing.KeyStroke.getKeyStroke("DOWN"), "down");
+ jtextfield.getActionMap().put("up", new javax.swing.AbstractAction() {
+ @Override
+ public void actionPerformed(java.awt.event.ActionEvent actionEvent) {
+ if (historyIndex < 0) {
+ currentCommand = jtextfield.getText();
+ }
+ if (historyIndex < history.size() - 1) {
+ jtextfield.setText(history.get(++historyIndex));
+ }
+ }
+ });
+ jtextfield.getActionMap().put("down", new javax.swing.AbstractAction() {
+ @Override
+ public void actionPerformed(java.awt.event.ActionEvent actionEvent) {
+ if (historyIndex >= 0) {
+ if (historyIndex == 0) {
+ --historyIndex;
+ jtextfield.setText(currentCommand);
+ } else {
+ --historyIndex;
+ jtextfield.setText(history.get(historyIndex));
+ }
+ }
+ }
+ });
+ // Purpur end
jtextarea.addFocusListener(new FocusAdapter() { // CraftBukkit - decompile error
public void focusGained(FocusEvent focusevent) {}
});
@@ -210,7 +248,7 @@ public class MinecraftServerGui extends JComponent {
}
private static final java.util.regex.Pattern ANSI = java.util.regex.Pattern.compile("\\e\\[[\\d;]*[^\\d;]"); // CraftBukkit // Paper
- public void print(JTextArea textArea, JScrollPane scrollPane, String message) {
+ public void print(org.purpurmc.purpur.gui.JColorTextPane textArea, JScrollPane scrollPane, String message) { // Purpur
if (!SwingUtilities.isEventDispatchThread()) {
SwingUtilities.invokeLater(() -> {
this.print(textArea, scrollPane, message);
@@ -224,11 +262,14 @@ public class MinecraftServerGui extends JComponent {
flag = (double) jscrollbar.getValue() + jscrollbar.getSize().getHeight() + (double) (MinecraftServerGui.MONOSPACED.getSize() * 4) > (double) jscrollbar.getMaximum();
}
+ /* // Purpur
try {
document.insertString(document.getLength(), MinecraftServerGui.ANSI.matcher(message).replaceAll(""), (AttributeSet) null); // CraftBukkit
} catch (BadLocationException badlocationexception) {
;
}
+ */ // Purpur
+ textArea.append(message); // Purpur
if (flag) {
jscrollbar.setValue(Integer.MAX_VALUE);
@@ -236,4 +277,16 @@ public class MinecraftServerGui extends JComponent {
}
}
+
+ // Purpur start
+ public static class CommandHistory extends java.util.LinkedList<String> {
+ @Override
+ public boolean add(String command) {
+ if (size() > 1000) {
+ remove();
+ }
+ return super.offerFirst(command);
+ }
+ }
+ // Purpur end
}
diff --git a/src/main/java/org/purpurmc/purpur/gui/GUIColor.java b/src/main/java/org/purpurmc/purpur/gui/GUIColor.java
new file mode 100644
index 0000000000000000000000000000000000000000..550222758bf0e7deff26a6e813a860b7be365e87
--- /dev/null
+++ b/src/main/java/org/purpurmc/purpur/gui/GUIColor.java
@@ -0,0 +1,58 @@
+package org.purpurmc.purpur.gui;
+
+import net.md_5.bungee.api.ChatColor;
+
+import java.awt.Color;
+import java.util.HashMap;
+import java.util.Map;
+
+public enum GUIColor {
+ BLACK(ChatColor.BLACK, new Color(0x000000)),
+ DARK_BLUE(ChatColor.DARK_BLUE, new Color(0x0000AA)),
+ DARK_GREEN(ChatColor.DARK_GREEN, new Color(0x00AA00)),
+ DARK_AQUA(ChatColor.DARK_AQUA, new Color(0x009999)),
+ DARK_RED(ChatColor.DARK_RED, new Color(0xAA0000)),
+ DARK_PURPLE(ChatColor.DARK_PURPLE, new Color(0xAA00AA)),
+ GOLD(ChatColor.GOLD, new Color(0xBB8800)),
+ GRAY(ChatColor.GRAY, new Color(0x888888)),
+ DARK_GRAY(ChatColor.DARK_GRAY, new Color(0x444444)),
+ BLUE(ChatColor.BLUE, new Color(0x5555FF)),
+ GREEN(ChatColor.GREEN, new Color(0x55FF55)),
+ AQUA(ChatColor.AQUA, new Color(0x55DDDD)),
+ RED(ChatColor.RED, new Color(0xFF5555)),
+ LIGHT_PURPLE(ChatColor.LIGHT_PURPLE, new Color(0xFF55FF)),
+ YELLOW(ChatColor.YELLOW, new Color(0xFFBB00)),
+ WHITE(ChatColor.WHITE, new Color(0xBBBBBB));
+
+ private final ChatColor chat;
+ private final Color color;
+
+ private static final Map<ChatColor, GUIColor> BY_CHAT = new HashMap<>();
+
+ GUIColor(ChatColor chat, Color color) {
+ this.chat = chat;
+ this.color = color;
+ }
+
+ public Color getColor() {
+ return color;
+ }
+
+ public ChatColor getChatColor() {
+ return chat;
+ }
+
+ public String getCode() {
+ return chat.toString();
+ }
+
+ public static GUIColor getColor(ChatColor chat) {
+ return BY_CHAT.get(chat);
+ }
+
+ static {
+ for (GUIColor color : values()) {
+ BY_CHAT.put(color.chat, color);
+ }
+ }
+}
diff --git a/src/main/java/org/purpurmc/purpur/gui/JColorTextPane.java b/src/main/java/org/purpurmc/purpur/gui/JColorTextPane.java
new file mode 100644
index 0000000000000000000000000000000000000000..d75fb5e77eff27d86135ed7d605dbc250b660f7d
--- /dev/null
+++ b/src/main/java/org/purpurmc/purpur/gui/JColorTextPane.java
@@ -0,0 +1,83 @@
+package org.purpurmc.purpur.gui;
+
+import com.google.common.collect.Sets;
+import javax.swing.UIManager;
+import net.md_5.bungee.api.chat.BaseComponent;
+import net.md_5.bungee.api.chat.TextComponent;
+
+import javax.swing.JTextPane;
+import javax.swing.Timer;
+import javax.swing.text.AttributeSet;
+import javax.swing.text.BadLocationException;
+import javax.swing.text.SimpleAttributeSet;
+import javax.swing.text.StyleConstants;
+import javax.swing.text.StyleContext;
+import java.util.Set;
+
+public class JColorTextPane extends JTextPane {
+ private static final GUIColor DEFAULT_COLOR;
+ static {
+ DEFAULT_COLOR = UIManager.getSystemLookAndFeelClassName().equals("com.sun.java.swing.plaf.gtk.GTKLookAndFeel")
+ ? GUIColor.WHITE : GUIColor.BLACK;
+ }
+
+
+ public void append(String msg) {
+ // TODO: update to use adventure instead
+ BaseComponent[] components = TextComponent.fromLegacyText(DEFAULT_COLOR.getCode() + msg, DEFAULT_COLOR.getChatColor());
+ for (BaseComponent component : components) {
+ String text = component.toPlainText();
+ if (text == null || text.isEmpty()) {
+ continue;
+ }
+
+ GUIColor guiColor = GUIColor.getColor(component.getColor());
+
+ StyleContext context = StyleContext.getDefaultStyleContext();
+ AttributeSet attr = context.addAttribute(SimpleAttributeSet.EMPTY, StyleConstants.Foreground, guiColor.getColor());
+ attr = context.addAttribute(attr, StyleConstants.CharacterConstants.Bold, component.isBold() || guiColor != DEFAULT_COLOR);
+ attr = context.addAttribute(attr, StyleConstants.CharacterConstants.Italic, component.isItalic());
+ attr = context.addAttribute(attr, StyleConstants.CharacterConstants.Underline, component.isUnderlined());
+ attr = context.addAttribute(attr, StyleConstants.CharacterConstants.StrikeThrough, component.isStrikethrough());
+ //attr = context.addAttribute(attr, StyleConstants.CharacterConstants.Blink, component.isObfuscated()); // no such thing as Blink, sadly
+
+ try {
+ int pos = getDocument().getLength();
+ getDocument().insertString(pos, text, attr);
+
+ if (component.isObfuscated()) {
+ // dirty hack to blink some text
+ Blink blink = new Blink(pos, text.length(), attr, context.addAttribute(attr, StyleConstants.Foreground, getBackground()));
+ BLINKS.add(blink);
+ }
+ } catch (BadLocationException ignore) {
+ }
+ }
+ }
+
+ private static final Set<Blink> BLINKS = Sets.newHashSet();
+ private static boolean SYNC_BLINK;
+
+ static {
+ new Timer(500, e -> {
+ SYNC_BLINK = !SYNC_BLINK;
+ BLINKS.forEach(Blink::blink);
+ }).start();
+ }
+
+ public class Blink {
+ private final int start, length;
+ private final AttributeSet attr1, attr2;
+
+ private Blink(int start, int length, AttributeSet attr1, AttributeSet attr2) {
+ this.start = start;
+ this.length = length;
+ this.attr1 = attr1;
+ this.attr2 = attr2;
+ }
+
+ private void blink() {
+ getStyledDocument().setCharacterAttributes(start, length, SYNC_BLINK ? attr1 : attr2, true);
+ }
+ }
+}
diff --git a/src/main/resources/log4j2.xml b/src/main/resources/log4j2.xml
index 637d64da9938e51a97338b9253b43889585c67bb..f9313059b4e3b2d100e66ed8a70d4811dc394031 100644
--- a/src/main/resources/log4j2.xml
+++ b/src/main/resources/log4j2.xml
@@ -2,7 +2,16 @@
<Configuration status="WARN">
<Appenders>
<Queue name="ServerGuiConsole">
- <PatternLayout pattern="[%d{HH:mm:ss} %level]: %msg{nolookups}%n" />
+ <!-- Purpur start - copied from TerminalConsole -->
+ <PatternLayout>
+ <LoggerNamePatternSelector defaultPattern="%highlightGUIError{[%d{HH:mm:ss} %level]: [%logger] %stripAnsi{%msg}%n%xEx{full}}">
+ <!-- Log root, Minecraft, Mojang and Bukkit loggers without prefix -->
+ <!-- Disable prefix for various plugins that bypass the plugin logger -->
+ <PatternMatch key=",net.minecraft.,Minecraft,com.mojang.,com.sk89q.,ru.tehkode.,Minecraft.AWE"
+ pattern="%highlightGUIError{[%d{HH:mm:ss} %level]: %stripAnsi{%msg}%n%xEx{full}}" />
+ </LoggerNamePatternSelector>
+ </PatternLayout>
+ <!-- Purpur end -->
</Queue>
<TerminalConsole name="TerminalConsole">
<PatternLayout>

View File

@@ -0,0 +1,253 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: EOT3000 <egor.tolstenkov@outlook.com>
Date: Sat, 10 Jun 2023 20:27:12 -0400
Subject: [PATCH] Stored Bee API
diff --git a/src/main/java/net/minecraft/world/level/block/entity/BeehiveBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BeehiveBlockEntity.java
index d8efb00c325448d566c59418fe22268c6eb4cfce..f7a6ab35c95ffda73f17843916ddb624ad290b42 100644
--- a/src/main/java/net/minecraft/world/level/block/entity/BeehiveBlockEntity.java
+++ b/src/main/java/net/minecraft/world/level/block/entity/BeehiveBlockEntity.java
@@ -146,11 +146,33 @@ public class BeehiveBlockEntity extends BlockEntity {
return list;
}
+ // Purpur start
+ 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
+
@VisibleForDebug
public int getOccupantCount() {
return this.stored.size();
}
+ // Purpur start
+ public List<BeeData> getStored() {
+ return stored;
+ }
+ // Purpur end
+
// Paper start - Add EntityBlockStorage clearEntities
public void clearBees() {
this.stored.clear();
@@ -471,9 +493,9 @@ public class BeehiveBlockEntity extends BlockEntity {
}
}
- private static class BeeData {
+ public static class BeeData { // Purpur - change from private to public
- private final BeehiveBlockEntity.Occupant occupant;
+ public final BeehiveBlockEntity.Occupant occupant; // Purpur - make public
private int exitTickCounter; // Paper - Fix bees aging inside hives; separate counter for checking if bee should exit to reduce exit attempts
private int ticksInHive;
diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBeehive.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBeehive.java
index 1a2a05160ba51d9c75f1ae6ae61d944d81428722..3beb26ad2ef0fded49a8da8c5dec64f9508c1995 100644
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBeehive.java
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBeehive.java
@@ -16,8 +16,15 @@ import org.bukkit.entity.Bee;
public class CraftBeehive extends CraftBlockEntityState<BeehiveBlockEntity> implements Beehive {
+ private final List<org.purpurmc.purpur.entity.StoredEntity<Bee>> storage = new ArrayList<>(); // Purpur
+
public CraftBeehive(World world, BeehiveBlockEntity tileEntity) {
super(world, tileEntity);
+ // Purpur start - load bees to be able to modify them individually
+ for(BeehiveBlockEntity.BeeData data : tileEntity.getStored()) {
+ storage.add(new org.purpurmc.purpur.entity.PurpurStoredBee(data, this));
+ }
+ // Purpur end
}
protected CraftBeehive(CraftBeehive state, Location location) {
@@ -75,15 +82,54 @@ public class CraftBeehive extends CraftBlockEntityState<BeehiveBlockEntity> impl
bees.add((Bee) bee.getBukkitEntity());
}
}
-
+ storage.clear(); // Purpur
return bees;
}
+ // Purpur start
+ @Override
+ public Bee releaseEntity(org.purpurmc.purpur.entity.StoredEntity<Bee> entity) {
+ ensureNoWorldGeneration();
+
+ if(!getEntities().contains(entity)) {
+ return null;
+ }
+
+ if(isPlaced()) {
+ BeehiveBlockEntity beehive = ((BeehiveBlockEntity) this.getTileEntityFromWorld());
+ BeehiveBlockEntity.BeeData data = ((org.purpurmc.purpur.entity.PurpurStoredBee) entity).getHandle();
+
+ List<Entity> list = beehive.releaseBee(getHandle(), data, BeeReleaseStatus.BEE_RELEASED, true);
+
+ if (list.size() == 1) {
+ storage.remove(entity);
+
+ return (Bee) list.get(0).getBukkitEntity();
+ }
+ }
+
+ return null;
+ }
+
+ @Override
+ public List<org.purpurmc.purpur.entity.StoredEntity<Bee>> getEntities() {
+ return new ArrayList<>(storage);
+ }
+ // Purpur end
+
@Override
public void addEntity(Bee entity) {
Preconditions.checkArgument(entity != null, "Entity must not be null");
- this.getSnapshot().addOccupant(((CraftBee) entity).getHandle());
+ int length = this.getSnapshot().getStored().size(); // Purpur
+ getSnapshot().addOccupant(((CraftBee) entity).getHandle());
+
+ // Purpur start - check if new bee was added, and if yes, add to stored bees
+ List<BeehiveBlockEntity.BeeData> storedBeeData = this.getSnapshot().getStored();
+ if(length < storedBeeData.size()) {
+ storage.add(new org.purpurmc.purpur.entity.PurpurStoredBee(storedBeeData.getLast(), this));
+ }
+ // Purpur end
}
@Override
@@ -100,6 +146,7 @@ public class CraftBeehive extends CraftBlockEntityState<BeehiveBlockEntity> impl
@Override
public void clearEntities() {
getSnapshot().clearBees();
+ storage.clear(); // Purpur
}
// Paper end
}
diff --git a/src/main/java/org/purpurmc/purpur/entity/PurpurStoredBee.java b/src/main/java/org/purpurmc/purpur/entity/PurpurStoredBee.java
new file mode 100644
index 0000000000000000000000000000000000000000..7608bf0981fa0d37031e51e57e4086cb5ec4c88b
--- /dev/null
+++ b/src/main/java/org/purpurmc/purpur/entity/PurpurStoredBee.java
@@ -0,0 +1,106 @@
+package org.purpurmc.purpur.entity;
+
+import io.papermc.paper.adventure.PaperAdventure;
+import net.kyori.adventure.text.Component;
+import net.minecraft.nbt.CompoundTag;
+import net.minecraft.nbt.Tag;
+import net.minecraft.server.MinecraftServer;
+import net.minecraft.world.item.component.CustomData;
+import net.minecraft.world.level.block.entity.BeehiveBlockEntity;
+import org.bukkit.block.EntityBlockStorage;
+import org.bukkit.craftbukkit.persistence.CraftPersistentDataContainer;
+import org.bukkit.craftbukkit.persistence.CraftPersistentDataTypeRegistry;
+import org.bukkit.entity.Bee;
+import org.bukkit.entity.EntityType;
+import org.bukkit.persistence.PersistentDataContainer;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Locale;
+
+public class PurpurStoredBee implements StoredEntity<Bee> {
+ private static final CraftPersistentDataTypeRegistry DATA_TYPE_REGISTRY = new CraftPersistentDataTypeRegistry();
+
+ private final EntityBlockStorage<Bee> blockStorage;
+ private final BeehiveBlockEntity.BeeData handle;
+ private final CraftPersistentDataContainer persistentDataContainer = new CraftPersistentDataContainer(PurpurStoredBee.DATA_TYPE_REGISTRY);
+
+ private Component customName;
+
+ public PurpurStoredBee(BeehiveBlockEntity.BeeData data, EntityBlockStorage<Bee> blockStorage) {
+ this.handle = data;
+ this.blockStorage = blockStorage;
+
+ CompoundTag customData = handle.occupant.entityData().copyTag();
+ this.customName = customData.contains("CustomName")
+ ? PaperAdventure.asAdventure(net.minecraft.network.chat.Component.Serializer.fromJson(customData.getString("CustomName"), MinecraftServer.getDefaultRegistryAccess()))
+ : null;
+
+ if(customData.contains("BukkitValues", Tag.TAG_COMPOUND)) {
+ this.persistentDataContainer.putAll(customData.getCompound("BukkitValues"));
+ }
+ }
+
+ public BeehiveBlockEntity.BeeData getHandle() {
+ return handle;
+ }
+
+ @Override
+ public @Nullable Component customName() {
+ return customName;
+ }
+
+ @Override
+ public void customName(@Nullable Component customName) {
+ this.customName = customName;
+ }
+
+ @Override
+ public @Nullable String getCustomName() {
+ return PaperAdventure.asPlain(customName, Locale.US);
+ }
+
+ @Override
+ public void setCustomName(@Nullable String name) {
+ customName(name != null ? Component.text(name) : null);
+ }
+
+ @Override
+ public @NotNull PersistentDataContainer getPersistentDataContainer() {
+ return persistentDataContainer;
+ }
+
+ @Override
+ public boolean hasBeenReleased() {
+ return !blockStorage.getEntities().contains(this);
+ }
+
+ @Override
+ public @Nullable Bee release() {
+ return blockStorage.releaseEntity(this);
+ }
+
+ @Override
+ public @Nullable EntityBlockStorage<Bee> getBlockStorage() {
+ if(hasBeenReleased()) {
+ return null;
+ }
+
+ return blockStorage;
+ }
+
+ @Override
+ public @NotNull EntityType getType() {
+ return EntityType.BEE;
+ }
+
+ @Override
+ public void update() {
+ handle.occupant.entityData().copyTag().put("BukkitValues", this.persistentDataContainer.toTagCompound());
+ if(customName == null) {
+ handle.occupant.entityData().copyTag().remove("CustomName");
+ } else {
+ handle.occupant.entityData().copyTag().putString("CustomName", net.minecraft.network.chat.Component.Serializer.toJson(PaperAdventure.asVanilla(customName), MinecraftServer.getDefaultRegistryAccess()));
+ }
+ }
+}

View File

@@ -0,0 +1,59 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: MrFishCakes <FinlayOxby@outlook.com>
Date: Sun, 2 Jul 2023 00:50:14 +0100
Subject: [PATCH] Shears can defuse TNT
Shears can now defuse TNT. Each world can have a configured chance for the TNT to be defused when right clicking with a set of shears and damage dealt to the shears accordingly. If the TNT is defused then it will drop the TNT item instead and the entity removed from the world no longer existing. All the interaction is handled within the net.minecraft.world.entity.item.PrimedTnt class similar to how it is handled for when sheep are sheared.
By default the option is disabled to avoid breaking any possible vanilla mechanics.
diff --git a/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java b/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java
index 42bd2d9a1528b6210e4dfb56233062fd97c9743b..2a4425d04917b32c7ae5af3e7422c0bafc2aa1c2 100644
--- a/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java
+++ b/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java
@@ -230,4 +230,29 @@ public class PrimedTnt extends Entity implements TraceableEntity {
return !level().paperConfig().fixes.preventTntFromMovingInWater && super.isPushedByFluid();
}
// Paper end - Option to prevent TNT from moving in water
+ // Purpur start - Shears can defuse TNT
+ @Override
+ public net.minecraft.world.InteractionResult interact(net.minecraft.world.entity.player.Player player, net.minecraft.world.InteractionHand hand) {
+ if (!level().isClientSide && level().purpurConfig.shearsCanDefuseTnt) {
+ final net.minecraft.world.item.ItemStack inHand = player.getItemInHand(hand);
+
+ if (!inHand.is(net.minecraft.world.item.Items.SHEARS) || !player.getBukkitEntity().hasPermission("purpur.tnt.defuse") ||
+ level().random.nextFloat() > level().purpurConfig.shearsCanDefuseTntChance) return net.minecraft.world.InteractionResult.PASS;
+
+ net.minecraft.world.entity.item.ItemEntity tntItem = new net.minecraft.world.entity.item.ItemEntity(level(), getX(), getY(), getZ(),
+ new net.minecraft.world.item.ItemStack(net.minecraft.world.item.Items.TNT));
+ tntItem.setPickUpDelay(10);
+
+ inHand.hurtAndBreak(1, player, LivingEntity.getSlotForHand(hand));
+ level().addFreshEntity(tntItem, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.CUSTOM);
+
+ this.playSound(net.minecraft.sounds.SoundEvents.SHEEP_SHEAR);
+
+ this.kill();
+ return net.minecraft.world.InteractionResult.SUCCESS;
+ }
+
+ return super.interact(player, hand);
+ }
+ // Purpur end - Shears can defuse TNT
}
diff --git a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
index 62328bd56578789dd898b203396d37a76e75f1e4..9e5dfbd8bc8c7dc16dbe1c00ba9420ad338ed671 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
@@ -3281,4 +3281,11 @@ public class PurpurWorldConfig {
cauldronDripstoneWaterFillChance = (float) getDouble("blocks.cauldron.fill-chances.dripstone-water", cauldronDripstoneWaterFillChance);
cauldronDripstoneLavaFillChance = (float) getDouble("blocks.cauldron.fill-chances.dripstone-lava", cauldronDripstoneLavaFillChance);
}
+
+ public float shearsCanDefuseTntChance = 0.00F;
+ public boolean shearsCanDefuseTnt = false;
+ private void shearsCanDefuseTntSettings() {
+ shearsCanDefuseTntChance = (float) getDouble("gameplay-mechanics.item.shears.defuse-tnt-chance", 0.00D);
+ shearsCanDefuseTnt = shearsCanDefuseTntChance > 0.00F;
+ }
}

View File

@@ -0,0 +1,45 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: William Blake Galbreath <blake.galbreath@gmail.com>
Date: Wed, 5 Jul 2023 12:48:15 -0500
Subject: [PATCH] Explorer Map API
diff --git a/src/main/java/net/minecraft/world/item/MapItem.java b/src/main/java/net/minecraft/world/item/MapItem.java
index ce461b1a8d7fab87ae28e30205f6fab67f1808b6..608390ed36710a419de1542b80340dd3fcc7299c 100644
--- a/src/main/java/net/minecraft/world/item/MapItem.java
+++ b/src/main/java/net/minecraft/world/item/MapItem.java
@@ -195,6 +195,7 @@ public class MapItem extends ComplexItem {
public static void renderBiomePreviewMap(ServerLevel world, ItemStack map) {
MapItemSavedData mapItemSavedData = getSavedData(map, world);
if (mapItemSavedData != null) {
+ mapItemSavedData.isExplorerMap = true; // Purpur
if (world.dimension() == mapItemSavedData.dimension) {
int i = 1 << mapItemSavedData.scale;
int j = mapItemSavedData.centerX;
diff --git a/src/main/java/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java b/src/main/java/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java
index a43544704109f21bab230dd9bf0401e28f878582..627d4ee90a2ebc137d7e94d988eba2f212b7f26d 100644
--- a/src/main/java/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java
+++ b/src/main/java/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java
@@ -79,6 +79,7 @@ public class MapItemSavedData extends SavedData {
public final Map<String, MapDecoration> decorations = Maps.newLinkedHashMap();
private final Map<String, MapFrame> frameMarkers = Maps.newHashMap();
private int trackedDecorationCount;
+ public boolean isExplorerMap; // Purpur
// CraftBukkit start
public final CraftMapView mapView;
diff --git a/src/main/java/org/bukkit/craftbukkit/map/CraftMapRenderer.java b/src/main/java/org/bukkit/craftbukkit/map/CraftMapRenderer.java
index 0cbbd915631904fe8c6effefb92895422b33eff6..aef19cfbecb4ddfc8dc71c4f3b2a011364c12dc2 100644
--- a/src/main/java/org/bukkit/craftbukkit/map/CraftMapRenderer.java
+++ b/src/main/java/org/bukkit/craftbukkit/map/CraftMapRenderer.java
@@ -47,4 +47,10 @@ public class CraftMapRenderer extends MapRenderer {
}
}
+ // Purpur - start
+ @Override
+ public boolean isExplorerMap() {
+ return this.worldMap.isExplorerMap;
+ }
+ // Purpur - end
}

View File

@@ -0,0 +1,39 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: William Blake Galbreath <blake.galbreath@gmail.com>
Date: Fri, 21 Jul 2023 11:04:47 -0500
Subject: [PATCH] Option Ocelot Spawn Under Sea Level
diff --git a/src/main/java/net/minecraft/world/entity/animal/Ocelot.java b/src/main/java/net/minecraft/world/entity/animal/Ocelot.java
index e09ca4aa99f2e58f97159a40e33ed863fa2ae7df..6e866ec44a83ec9064ac3228bd96eb251f3b28b0 100644
--- a/src/main/java/net/minecraft/world/entity/animal/Ocelot.java
+++ b/src/main/java/net/minecraft/world/entity/animal/Ocelot.java
@@ -284,7 +284,7 @@ public class Ocelot extends Animal {
if (world.isUnobstructed(this) && !world.containsAnyLiquid(this.getBoundingBox())) {
BlockPos blockposition = this.blockPosition();
- if (blockposition.getY() < world.getSeaLevel()) {
+ if (!level().purpurConfig.ocelotSpawnUnderSeaLevel && blockposition.getY() < world.getSeaLevel()) {
return false;
}
diff --git a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
index 9e5dfbd8bc8c7dc16dbe1c00ba9420ad338ed671..4af55c74a5ad9752f105b7330a32061de217a6e6 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
@@ -2100,6 +2100,7 @@ public class PurpurWorldConfig {
public int ocelotBreedingTicks = 6000;
public boolean ocelotTakeDamageFromWater = false;
public boolean ocelotAlwaysDropExp = false;
+ public boolean ocelotSpawnUnderSeaLevel = false;
private void ocelotSettings() {
ocelotRidable = getBoolean("mobs.ocelot.ridable", ocelotRidable);
ocelotRidableInWater = getBoolean("mobs.ocelot.ridable-in-water", ocelotRidableInWater);
@@ -2113,6 +2114,7 @@ public class PurpurWorldConfig {
ocelotBreedingTicks = getInt("mobs.ocelot.breeding-delay-ticks", ocelotBreedingTicks);
ocelotTakeDamageFromWater = getBoolean("mobs.ocelot.takes-damage-from-water", ocelotTakeDamageFromWater);
ocelotAlwaysDropExp = getBoolean("mobs.ocelot.always-drop-exp", ocelotAlwaysDropExp);
+ ocelotSpawnUnderSeaLevel = getBoolean("mobs.ocelot.spawn-below-sea-level", ocelotSpawnUnderSeaLevel);
}
public boolean pandaRidable = false;

View File

@@ -0,0 +1,50 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: granny <contact@granny.dev>
Date: Sun, 13 Aug 2023 06:26:08 -0700
Subject: [PATCH] add an option for piglins to ignore gold-trimmed armor
diff --git a/src/main/java/net/minecraft/world/entity/monster/piglin/PiglinAi.java b/src/main/java/net/minecraft/world/entity/monster/piglin/PiglinAi.java
index 0192b62fd66621a72fcf2f20896647e5950ba993..d079d5492b6ed709b1e0a7d84fb5f8f6896fc2fe 100644
--- a/src/main/java/net/minecraft/world/entity/monster/piglin/PiglinAi.java
+++ b/src/main/java/net/minecraft/world/entity/monster/piglin/PiglinAi.java
@@ -606,11 +606,18 @@ public class PiglinAi {
ItemStack itemstack = (ItemStack) iterator.next();
item = itemstack.getItem();
- } while (!(item instanceof ArmorItem) || !((ArmorItem) item).getMaterial().is(ArmorMaterials.GOLD));
+ } while (!(item instanceof ArmorItem) || !((ArmorItem) item).getMaterial().is(ArmorMaterials.GOLD) && (!entity.level().purpurConfig.piglinIgnoresArmorWithGoldTrim || !isWearingGoldTrim(item))); // Purpur
return true;
}
+ // Purpur start
+ private static boolean isWearingGoldTrim(Item itemstack) {
+ net.minecraft.world.item.armortrim.ArmorTrim armorTrim = itemstack.components().get(net.minecraft.core.component.DataComponents.TRIM);
+ return armorTrim != null && armorTrim.material().is(net.minecraft.world.item.armortrim.TrimMaterials.GOLD);
+ }
+ // Purpur end
+
private static void stopWalking(Piglin piglin) {
piglin.getBrain().eraseMemory(MemoryModuleType.WALK_TARGET);
piglin.getNavigation().stop();
diff --git a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
index 4af55c74a5ad9752f105b7330a32061de217a6e6..07dbd2768b52d3143d65c34adf48884bfde00c4d 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
@@ -2269,6 +2269,7 @@ public class PurpurWorldConfig {
public int piglinPortalSpawnModifier = 2000;
public boolean piglinAlwaysDropExp = false;
public double piglinHeadVisibilityPercent = 0.5D;
+ public boolean piglinIgnoresArmorWithGoldTrim = false;
private void piglinSettings() {
piglinRidable = getBoolean("mobs.piglin.ridable", piglinRidable);
piglinRidableInWater = getBoolean("mobs.piglin.ridable-in-water", piglinRidableInWater);
@@ -2284,6 +2285,7 @@ public class PurpurWorldConfig {
piglinPortalSpawnModifier = getInt("mobs.piglin.portal-spawn-modifier", piglinPortalSpawnModifier);
piglinAlwaysDropExp = getBoolean("mobs.piglin.always-drop-exp", piglinAlwaysDropExp);
piglinHeadVisibilityPercent = getDouble("mobs.piglin.head-visibility-percent", piglinHeadVisibilityPercent);
+ piglinIgnoresArmorWithGoldTrim = getBoolean("mobs.piglin.ignores-armor-with-gold-trim", piglinIgnoresArmorWithGoldTrim);
}
public boolean piglinBruteRidable = false;

View File

@@ -0,0 +1,46 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: MelnCat <melncatuwu@gmail.com>
Date: Tue, 22 Aug 2023 22:18:26 -0700
Subject: [PATCH] Add option for always showing item in player death messages
diff --git a/src/main/java/net/minecraft/world/damagesource/CombatTracker.java b/src/main/java/net/minecraft/world/damagesource/CombatTracker.java
index 357a79d72a2de02a019595e457fe432bf409e516..4fb025a63628eb60509d90b680922a0220104bcb 100644
--- a/src/main/java/net/minecraft/world/damagesource/CombatTracker.java
+++ b/src/main/java/net/minecraft/world/damagesource/CombatTracker.java
@@ -54,7 +54,7 @@ public class CombatTracker {
private Component getMessageForAssistedFall(Entity attacker, Component attackerDisplayName, String itemDeathTranslationKey, String deathTranslationKey) {
ItemStack itemStack = attacker instanceof LivingEntity livingEntity ? livingEntity.getMainHandItem() : ItemStack.EMPTY;
- return !itemStack.isEmpty() && itemStack.has(DataComponents.CUSTOM_NAME)
+ return !itemStack.isEmpty() && (org.purpurmc.purpur.PurpurConfig.playerDeathsAlwaysShowItem || itemStack.has(DataComponents.CUSTOM_NAME)) // Purpur
? Component.translatable(itemDeathTranslationKey, this.mob.getDisplayName(), attackerDisplayName, itemStack.getDisplayName())
: Component.translatable(deathTranslationKey, this.mob.getDisplayName(), attackerDisplayName);
}
diff --git a/src/main/java/net/minecraft/world/damagesource/DamageSource.java b/src/main/java/net/minecraft/world/damagesource/DamageSource.java
index d95d122601dd47a27e8d82a13b071919c360fe68..4a96d914f8aa6f0c5f13fc85369a311f25835ac2 100644
--- a/src/main/java/net/minecraft/world/damagesource/DamageSource.java
+++ b/src/main/java/net/minecraft/world/damagesource/DamageSource.java
@@ -218,7 +218,7 @@ public class DamageSource {
ItemStack itemstack1 = itemstack;
- return !itemstack1.isEmpty() && itemstack1.has(DataComponents.CUSTOM_NAME) ? Component.translatable(s + ".item", killed.getDisplayName(), ichatbasecomponent, itemstack1.getDisplayName()) : Component.translatable(s, killed.getDisplayName(), ichatbasecomponent);
+ return !itemstack1.isEmpty() && (org.purpurmc.purpur.PurpurConfig.playerDeathsAlwaysShowItem || itemstack1.has(DataComponents.CUSTOM_NAME)) ? Component.translatable(s + ".item", killed.getDisplayName(), ichatbasecomponent, itemstack1.getDisplayName()) : Component.translatable(s, killed.getDisplayName(), ichatbasecomponent);
}
}
diff --git a/src/main/java/org/purpurmc/purpur/PurpurConfig.java b/src/main/java/org/purpurmc/purpur/PurpurConfig.java
index 920dc26d4485f3c12d237c2b55e3d70671246ddc..f93224fe05c29cdecf5e04afec1624a4edfbb77b 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurConfig.java
@@ -562,4 +562,9 @@ public class PurpurConfig {
block.fallDistanceMultiplier = fallDistanceMultiplier.floatValue();
});
}
+
+ public static boolean playerDeathsAlwaysShowItem = false;
+ private static void playerDeathsAlwaysShowItem() {
+ playerDeathsAlwaysShowItem = getBoolean("settings.player-deaths-always-show-item", playerDeathsAlwaysShowItem);
+ }
}

View File

@@ -0,0 +1,39 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: granny <contact@granny.dev>
Date: Wed, 23 Aug 2023 01:39:14 -0700
Subject: [PATCH] place end crystal on any block
diff --git a/src/main/java/net/minecraft/world/item/EndCrystalItem.java b/src/main/java/net/minecraft/world/item/EndCrystalItem.java
index 5f51e64cb0611a4ba6bdcdcacbcba1063a7f3a5c..8fb564f43e2f1194d2ad68d35c4df6b921d50cfc 100644
--- a/src/main/java/net/minecraft/world/item/EndCrystalItem.java
+++ b/src/main/java/net/minecraft/world/item/EndCrystalItem.java
@@ -27,7 +27,7 @@ public class EndCrystalItem extends Item {
BlockPos blockposition = context.getClickedPos();
BlockState iblockdata = world.getBlockState(blockposition);
- if (!iblockdata.is(Blocks.OBSIDIAN) && !iblockdata.is(Blocks.BEDROCK)) {
+ if (!world.purpurConfig.endCrystalPlaceAnywhere && !iblockdata.is(Blocks.OBSIDIAN) && !iblockdata.is(Blocks.BEDROCK)) {
return InteractionResult.FAIL;
} else {
BlockPos blockposition1 = blockposition.above(); final BlockPos aboveBlockPosition = blockposition1; // Paper - OBFHELPER
diff --git a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
index 07dbd2768b52d3143d65c34adf48884bfde00c4d..ddc188c67246fd9b0a887a6c4248e369e08acff0 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
@@ -957,6 +957,7 @@ public class PurpurWorldConfig {
public boolean basedEndCrystalExplosionFire = false;
public net.minecraft.world.level.Level.ExplosionInteraction basedEndCrystalExplosionEffect = net.minecraft.world.level.Level.ExplosionInteraction.BLOCK;
public int endCrystalCramming = 0;
+ public boolean endCrystalPlaceAnywhere = false;
private void endCrystalSettings() {
if (PurpurConfig.version < 31) {
if ("DESTROY".equals(getString("blocks.end-crystal.baseless.explosion-effect", baselessEndCrystalExplosionEffect.name()))) {
@@ -985,6 +986,7 @@ public class PurpurWorldConfig {
basedEndCrystalExplosionEffect = net.minecraft.world.level.Level.ExplosionInteraction.BLOCK;
}
endCrystalCramming = getInt("blocks.end-crystal.cramming-amount", endCrystalCramming);
+ endCrystalPlaceAnywhere = getBoolean("gameplay-mechanics.item.end-crystal.place-anywhere", endCrystalPlaceAnywhere);
}
public boolean farmlandBypassMobGriefing = false;

View File

@@ -0,0 +1,39 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Meln Cat <melncatuwu@gmail.com>
Date: Mon, 9 Oct 2023 12:21:49 -0700
Subject: [PATCH] Add option to disable the copper oxidation proximity penalty
diff --git a/src/main/java/net/minecraft/world/level/block/ChangeOverTimeBlock.java b/src/main/java/net/minecraft/world/level/block/ChangeOverTimeBlock.java
index daae7fd6e0148cfba8e359d990748a0c83a3376e..0e06b1bcd906e92c083dc74d56d6d0a2a36f62a7 100644
--- a/src/main/java/net/minecraft/world/level/block/ChangeOverTimeBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/ChangeOverTimeBlock.java
@@ -67,7 +67,7 @@ public interface ChangeOverTimeBlock<T extends Enum<T>> {
}
float f = (float) (k + 1) / (float) (k + j + 1);
- float f1 = f * f * this.getChanceModifier();
+ float f1 = world.purpurConfig.disableOxidationProximityPenalty ? this.getChanceModifier() : f * f * this.getChanceModifier(); // Purpur
return random.nextFloat() < f1 ? this.getNext(state) : Optional.empty();
}
diff --git a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
index ddc188c67246fd9b0a887a6c4248e369e08acff0..913ec0b08cbffcbd30579c0925ffa301c9466101 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
@@ -143,6 +143,7 @@ public class PurpurWorldConfig {
public boolean rainStopsAfterSleep = true;
public boolean thunderStopsAfterSleep = true;
public int mobLastHurtByPlayerTime = 100;
+ public boolean disableOxidationProximityPenalty = false;
private void miscGameplayMechanicsSettings() {
useBetterMending = getBoolean("gameplay-mechanics.use-better-mending", useBetterMending);
alwaysTameInCreative = getBoolean("gameplay-mechanics.always-tame-in-creative", alwaysTameInCreative);
@@ -175,6 +176,7 @@ public class PurpurWorldConfig {
rainStopsAfterSleep = getBoolean("gameplay-mechanics.rain-stops-after-sleep", rainStopsAfterSleep);
thunderStopsAfterSleep = getBoolean("gameplay-mechanics.thunder-stops-after-sleep", thunderStopsAfterSleep);
mobLastHurtByPlayerTime = getInt("gameplay-mechanics.mob-last-hurt-by-player-time", mobLastHurtByPlayerTime);
+ disableOxidationProximityPenalty = getBoolean("gameplay-mechanics.disable-oxidation-proximity-penalty", disableOxidationProximityPenalty);
}
public int daytimeTicks = 12000;

View File

@@ -0,0 +1,47 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: granny <contact@granny.dev>
Date: Sun, 18 Feb 2024 16:28:32 -0800
Subject: [PATCH] register minecraft debug commands
diff --git a/src/main/java/net/minecraft/commands/Commands.java b/src/main/java/net/minecraft/commands/Commands.java
index 7bcc0f87337547f8783dd9cc8adff61187cd41d7..d559b6f0e5ae4f761cd5fe4124bc26034ef297eb 100644
--- a/src/main/java/net/minecraft/commands/Commands.java
+++ b/src/main/java/net/minecraft/commands/Commands.java
@@ -221,8 +221,8 @@ public class Commands {
JfrCommand.register(this.dispatcher);
}
- if (SharedConstants.IS_RUNNING_IN_IDE) {
- TestCommand.register(this.dispatcher);
+ if (org.purpurmc.purpur.PurpurConfig.registerMinecraftDebugCommands || SharedConstants.IS_RUNNING_IN_IDE) { // Purpur
+ if (!org.purpurmc.purpur.PurpurConfig.registerMinecraftDebugCommands) TestCommand.register(this.dispatcher); // Purpur
RaidCommand.register(this.dispatcher, commandRegistryAccess);
DebugPathCommand.register(this.dispatcher);
DebugMobSpawningCommand.register(this.dispatcher);
diff --git a/src/main/java/net/minecraft/server/Main.java b/src/main/java/net/minecraft/server/Main.java
index 824afdc486a50952bf5e32b06509f7952da9bba5..abb60e5cf3ecdb40561510dc53294e3010fbe039 100644
--- a/src/main/java/net/minecraft/server/Main.java
+++ b/src/main/java/net/minecraft/server/Main.java
@@ -122,6 +122,7 @@ public class Main {
// Purpur start - load config files early
org.bukkit.configuration.file.YamlConfiguration purpurConfiguration = io.papermc.paper.configuration.PaperConfigurations.loadLegacyConfigFile((File) optionset.valueOf("purpur-settings"));
org.purpurmc.purpur.PurpurConfig.clampEnchantLevels = purpurConfiguration.getBoolean("settings.enchantment.clamp-levels");
+ org.purpurmc.purpur.PurpurConfig.registerMinecraftDebugCommands = purpurConfiguration.getBoolean("settings.register-minecraft-debug-commands");
// Purpur end - load config files early
io.papermc.paper.plugin.PluginInitializerManager.load(optionset); // Paper
diff --git a/src/main/java/org/purpurmc/purpur/PurpurConfig.java b/src/main/java/org/purpurmc/purpur/PurpurConfig.java
index f93224fe05c29cdecf5e04afec1624a4edfbb77b..a6681c9e0ba0544bf1fd80d73be7f22f4fed1157 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurConfig.java
@@ -567,4 +567,9 @@ public class PurpurConfig {
private static void playerDeathsAlwaysShowItem() {
playerDeathsAlwaysShowItem = getBoolean("settings.player-deaths-always-show-item", playerDeathsAlwaysShowItem);
}
+
+ public static boolean registerMinecraftDebugCommands = false;
+ private static void registerMinecraftDebugCommands() {
+ registerMinecraftDebugCommands = getBoolean("settings.register-minecraft-debug-commands", registerMinecraftDebugCommands);
+ }
}

View File

@@ -0,0 +1,54 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Pantera <zeruskr@gmail.com>
Date: Fri, 26 Jan 2024 15:57:24 +0900
Subject: [PATCH] Configurable-villager-search-radius
diff --git a/src/main/java/net/minecraft/world/entity/ai/behavior/AcquirePoi.java b/src/main/java/net/minecraft/world/entity/ai/behavior/AcquirePoi.java
index e8aa27547e3fa1a42720889c7038d4fb0273e7b5..2638c5502016da62c54ec02a1d62834cba8e69d3 100644
--- a/src/main/java/net/minecraft/world/entity/ai/behavior/AcquirePoi.java
+++ b/src/main/java/net/minecraft/world/entity/ai/behavior/AcquirePoi.java
@@ -72,7 +72,7 @@ public class AcquirePoi {
}
};
Set<Pair<Holder<PoiType>, BlockPos>> set = poiManager.findAllClosestFirstWithType(
- poiPredicate, predicate2, entity.blockPosition(), 48, PoiManager.Occupancy.HAS_SPACE
+ poiPredicate, predicate2, entity.blockPosition(), world.purpurConfig.villagerAcquirePoiSearchRadius, PoiManager.Occupancy.HAS_SPACE // Purpur
)
.limit(5L)
.collect(Collectors.toSet());
diff --git a/src/main/java/net/minecraft/world/entity/ai/sensing/NearestBedSensor.java b/src/main/java/net/minecraft/world/entity/ai/sensing/NearestBedSensor.java
index d5a549f08b98c80a5cf0eef02cb8a389c32dfecb..222c87e80cb089867ce9a7d2dceebe21b4bfe0de 100644
--- a/src/main/java/net/minecraft/world/entity/ai/sensing/NearestBedSensor.java
+++ b/src/main/java/net/minecraft/world/entity/ai/sensing/NearestBedSensor.java
@@ -54,7 +54,7 @@ public class NearestBedSensor extends Sensor<Mob> {
}
};
Set<Pair<Holder<PoiType>, BlockPos>> set = poiManager.findAllWithType(
- holder -> holder.is(PoiTypes.HOME), predicate, entity.blockPosition(), 48, PoiManager.Occupancy.ANY
+ holder -> holder.is(PoiTypes.HOME), predicate, entity.blockPosition(), world.purpurConfig.villagerNearestBedSensorSearchRadius, PoiManager.Occupancy.ANY
)
.collect(Collectors.toSet());
Path path = AcquirePoi.findPathToPois(entity, set);
diff --git a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
index 913ec0b08cbffcbd30579c0925ffa301c9466101..624a7992143431df4d61b89a0da64bdf2ff124ad 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
@@ -2898,6 +2898,8 @@ public class PurpurWorldConfig {
public boolean villagerDisplayTradeItem = true;
public int villagerSpawnIronGolemRadius = 0;
public int villagerSpawnIronGolemLimit = 0;
+ public int villagerAcquirePoiSearchRadius = 48;
+ public int villagerNearestBedSensorSearchRadius = 48;
private void villagerSettings() {
villagerRidable = getBoolean("mobs.villager.ridable", villagerRidable);
villagerRidableInWater = getBoolean("mobs.villager.ridable-in-water", villagerRidableInWater);
@@ -2933,6 +2935,8 @@ public class PurpurWorldConfig {
villagerDisplayTradeItem = getBoolean("mobs.villager.display-trade-item", villagerDisplayTradeItem);
villagerSpawnIronGolemRadius = getInt("mobs.villager.spawn-iron-golem.radius", villagerSpawnIronGolemRadius);
villagerSpawnIronGolemLimit = getInt("mobs.villager.spawn-iron-golem.limit", villagerSpawnIronGolemLimit);
+ villagerAcquirePoiSearchRadius = getInt("mobs.villager.search-radius.acquire-poi", villagerAcquirePoiSearchRadius);
+ villagerNearestBedSensorSearchRadius = getInt("mobs.villager.search-radius.nearest-bed-sensor", villagerNearestBedSensorSearchRadius);
}
public boolean vindicatorRidable = false;

View File

@@ -0,0 +1,39 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: granny <granny@purpurmc.org>
Date: Tue, 7 May 2024 04:59:57 -0700
Subject: [PATCH] option to make ravagers afraid of rabbits
https://github.com/PurpurMC/Purpur/discussions/713
diff --git a/src/main/java/net/minecraft/world/entity/monster/Ravager.java b/src/main/java/net/minecraft/world/entity/monster/Ravager.java
index 714a37974e3256913c15193f2bd292fe45072c7f..0c494a8c71e316307af2c0e256ccfd23685f8219 100644
--- a/src/main/java/net/minecraft/world/entity/monster/Ravager.java
+++ b/src/main/java/net/minecraft/world/entity/monster/Ravager.java
@@ -112,6 +112,7 @@ public class Ravager extends Raider {
super.registerGoals();
this.goalSelector.addGoal(0, new FloatGoal(this));
this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur
+ if (level().purpurConfig.ravagerAvoidRabbits) this.goalSelector.addGoal(3, new net.minecraft.world.entity.ai.goal.AvoidEntityGoal<>(this, net.minecraft.world.entity.animal.Rabbit.class, 6.0F, 1.0D, 1.2D)); // Purpur
this.goalSelector.addGoal(4, new MeleeAttackGoal(this, 1.0D, true));
this.goalSelector.addGoal(5, new WaterAvoidingRandomStrollGoal(this, 0.4D));
this.goalSelector.addGoal(6, new LookAtPlayerGoal(this, Player.class, 6.0F));
diff --git a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
index 624a7992143431df4d61b89a0da64bdf2ff124ad..95afa69b30eb67226b23b91d10eb1516181d36d4 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
@@ -2415,6 +2415,7 @@ public class PurpurWorldConfig {
public boolean ravagerTakeDamageFromWater = false;
public List<Block> ravagerGriefableBlocks = new ArrayList<>();
public boolean ravagerAlwaysDropExp = false;
+ public boolean ravagerAvoidRabbits = false;
private void ravagerSettings() {
ravagerRidable = getBoolean("mobs.ravager.ridable", ravagerRidable);
ravagerRidableInWater = getBoolean("mobs.ravager.ridable-in-water", ravagerRidableInWater);
@@ -2445,6 +2446,7 @@ public class PurpurWorldConfig {
}
});
ravagerAlwaysDropExp = getBoolean("mobs.ravager.always-drop-exp", ravagerAlwaysDropExp);
+ ravagerAvoidRabbits = getBoolean("mobs.ravager.avoid-rabbits", ravagerAvoidRabbits);
}
public boolean salmonRidable = false;

View File

@@ -0,0 +1,48 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: granny <granny@purpurmc.org>
Date: Sun, 5 May 2024 02:27:52 -0700
Subject: [PATCH] config for startup commands
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
index 49020c26d2bf6d30fadc3352925a76b91c490561..e36cb57db8776ef01cb4e56819ada249d1919b46 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -1162,6 +1162,16 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
}
// Paper end - Add onboarding message for initial server start
+ // Purpur start
+ 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);
+ ((DedicatedServer) this).handleConsoleInput(startupCommand, this.createCommandSourceStack());
+ }
+ }
+ // Purpur end
+
while (this.running) {
long i;
diff --git a/src/main/java/org/purpurmc/purpur/PurpurConfig.java b/src/main/java/org/purpurmc/purpur/PurpurConfig.java
index a6681c9e0ba0544bf1fd80d73be7f22f4fed1157..fd4081662aa71d508b2f1bc1dbd70b1b28687848 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurConfig.java
@@ -572,4 +572,16 @@ public class PurpurConfig {
private static void registerMinecraftDebugCommands() {
registerMinecraftDebugCommands = getBoolean("settings.register-minecraft-debug-commands", registerMinecraftDebugCommands);
}
+
+ public static List<String> startupCommands = new ArrayList<>();
+ private static void startupCommands() {
+ startupCommands.clear();
+ getList("settings.startup-commands", new ArrayList<String>()).forEach(line -> {
+ String command = line.toString();
+ if (command.startsWith("/")) {
+ command = command.substring(1);
+ }
+ startupCommands.add(command);
+ });
+ }
}

View File

@@ -0,0 +1,45 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: granny <granny@purpurmc.org>
Date: Sat, 8 Jun 2024 22:06:47 -0700
Subject: [PATCH] Config to reverse bubble column flow
diff --git a/src/main/java/net/minecraft/world/level/block/BubbleColumnBlock.java b/src/main/java/net/minecraft/world/level/block/BubbleColumnBlock.java
index 4c1f20fafdbd86011959cc2d4983b6c2f8e87a5f..78679c2c26a36cf08cf3ffe78617d97d3439e14c 100644
--- a/src/main/java/net/minecraft/world/level/block/BubbleColumnBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/BubbleColumnBlock.java
@@ -122,10 +122,10 @@ public class BubbleColumnBlock extends Block implements BucketPickup {
if (state.is(Blocks.BUBBLE_COLUMN)) {
return state;
} else if (state.is(Blocks.SOUL_SAND)) {
- return Blocks.BUBBLE_COLUMN.defaultBlockState().setValue(DRAG_DOWN, Boolean.valueOf(false));
+ return Blocks.BUBBLE_COLUMN.defaultBlockState().setValue(DRAG_DOWN, Boolean.valueOf(org.purpurmc.purpur.PurpurConfig.soulSandBlockReverseBubbleColumnFlow)); // Purpur
} else {
return state.is(Blocks.MAGMA_BLOCK)
- ? Blocks.BUBBLE_COLUMN.defaultBlockState().setValue(DRAG_DOWN, Boolean.valueOf(true))
+ ? Blocks.BUBBLE_COLUMN.defaultBlockState().setValue(DRAG_DOWN, Boolean.valueOf(!org.purpurmc.purpur.PurpurConfig.magmaBlockReverseBubbleColumnFlow)) // Purpur
: Blocks.WATER.defaultBlockState();
}
}
diff --git a/src/main/java/org/purpurmc/purpur/PurpurConfig.java b/src/main/java/org/purpurmc/purpur/PurpurConfig.java
index fd4081662aa71d508b2f1bc1dbd70b1b28687848..c10293aec83128e0bb4954690d6973a115607775 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurConfig.java
@@ -341,6 +341,8 @@ public class PurpurConfig {
public static int kelpMaxGrowthAge = 25;
public static int twistingVinesMaxGrowthAge = 25;
public static int weepingVinesMaxGrowthAge = 25;
+ public static boolean magmaBlockReverseBubbleColumnFlow = false;
+ public static boolean soulSandBlockReverseBubbleColumnFlow = false;
private static void blockSettings() {
if (version < 3) {
boolean oldValue = getBoolean("settings.barrel.packed-barrels", true);
@@ -412,6 +414,8 @@ public class PurpurConfig {
log(Level.WARNING, "blocks.weeping_vines.max-growth-age is set to above maximum allowed value of 25");
log(Level.WARNING, "Using value of 25 to prevent issues");
}
+ magmaBlockReverseBubbleColumnFlow = getBoolean("settings.blocks.magma-block.reverse-bubble-column-flow", magmaBlockReverseBubbleColumnFlow);
+ soulSandBlockReverseBubbleColumnFlow = getBoolean("settings.blocks.soul-sand.reverse-bubble-column-flow", soulSandBlockReverseBubbleColumnFlow);
}
public static boolean allowShearsLooting = false;

View File

@@ -0,0 +1,45 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: granny <granny@purpurmc.org>
Date: Thu, 13 Jun 2024 16:00:30 -0700
Subject: [PATCH] Adopt MaterialRerouting
Adopts the purpur-api to the material rerouting infrastructure introduced
by upstream's upstream.
diff --git a/src/main/java/org/bukkit/craftbukkit/legacy/MaterialRerouting.java b/src/main/java/org/bukkit/craftbukkit/legacy/MaterialRerouting.java
index 9c004e7cb46841d874ab997bf2e3b63ae763aec7..36003e5c7c61d964f11e81fa56845a52a8785468 100644
--- a/src/main/java/org/bukkit/craftbukkit/legacy/MaterialRerouting.java
+++ b/src/main/java/org/bukkit/craftbukkit/legacy/MaterialRerouting.java
@@ -678,4 +678,32 @@ public class MaterialRerouting {
return itemStack.withType(material);
}
// Paper end - register paper API specific material consumers in rerouting
+ // Purpur start
+ // Method added post 1.13, no-op (https://github.com/PurpurMC/Purpur/pull/570)
+ public static void addFuel(Server server, Material material, int burnTime) {
+ server.addFuel(material, burnTime);
+ }
+
+ // Method added post 1.13, no-op (https://github.com/PurpurMC/Purpur/pull/570)
+ public static void removeFuel(Server server, Material material) {
+ server.removeFuel(material);
+ }
+
+ // Method added post 1.13, no-op (https://github.com/PurpurMC/Purpur/pull/570)
+ @RerouteStatic("org/bukkit/Bukkit")
+ public static void addFuel(Material material, int burnTime) {
+ Bukkit.addFuel(material, burnTime);
+ }
+
+ // Method added post 1.13, no-op (https://github.com/PurpurMC/Purpur/pull/570)
+ @RerouteStatic("org/bukkit/Bukkit")
+ public static void removeFuel(Material material) {
+ Bukkit.removeFuel(material);
+ }
+
+ // Method added post 1.13, no-op (https://github.com/PurpurMC/Purpur/commit/607d909efba516893072b782c0393c53d048210e)
+ public static BlockData getBlockData(ItemStack itemStack, Material material) {
+ return itemStack.getBlockData(MaterialRerouting.transformToBlockType(material));
+ }
+ // Purpur end
}