the rest of the patches

This commit is contained in:
granny
2023-09-23 04:50:44 -07:00
parent 87e5f450c3
commit e74f718fdf
106 changed files with 958 additions and 1027 deletions

View File

@@ -0,0 +1,41 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: 12emin34 <macanovic.emin@gmail.com>
Date: Fri, 6 Aug 2021 22:30:10 +0200
Subject: [PATCH] Customizeable Zombie Villager curing times
diff --git a/src/main/java/net/minecraft/world/entity/monster/ZombieVillager.java b/src/main/java/net/minecraft/world/entity/monster/ZombieVillager.java
index 5933bff2db353644705f5e1cfec3b0f2dedbad87..ecf41531855e1f60d9739ac6d2d82df7794f072f 100644
--- a/src/main/java/net/minecraft/world/entity/monster/ZombieVillager.java
+++ b/src/main/java/net/minecraft/world/entity/monster/ZombieVillager.java
@@ -221,7 +221,7 @@ public class ZombieVillager extends Zombie implements VillagerDataHolder {
}
if (!this.level().isClientSide) {
- this.startConverting(player.getUUID(), this.random.nextInt(2401) + 3600);
+ this.startConverting(player.getUUID(), this.random.nextInt(level().purpurConfig.zombieVillagerCuringTimeMax - level().purpurConfig.zombieVillagerCuringTimeMin + 1) + level().purpurConfig.zombieVillagerCuringTimeMin); // Purpur
}
return InteractionResult.SUCCESS;
diff --git a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
index 8cece9543a87ac86a8320fef4a23b39dbc76ab5c..b2f365ab51b56a83ed7ea67c921c163c3511b834 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
@@ -2770,6 +2770,8 @@ public class PurpurWorldConfig {
public double zombieVillagerJockeyChance = 0.05D;
public boolean zombieVillagerJockeyTryExistingChickens = true;
public boolean zombieVillagerTakeDamageFromWater = false;
+ public int zombieVillagerCuringTimeMin = 3600;
+ public int zombieVillagerCuringTimeMax = 6000;
private void zombieVillagerSettings() {
zombieVillagerRidable = getBoolean("mobs.zombie_villager.ridable", zombieVillagerRidable);
zombieVillagerRidableInWater = getBoolean("mobs.zombie_villager.ridable-in-water", zombieVillagerRidableInWater);
@@ -2785,6 +2787,8 @@ public class PurpurWorldConfig {
zombieVillagerJockeyChance = getDouble("mobs.zombie_villager.jockey.chance", zombieVillagerJockeyChance);
zombieVillagerJockeyTryExistingChickens = getBoolean("mobs.zombie_villager.jockey.try-existing-chickens", zombieVillagerJockeyTryExistingChickens);
zombieVillagerTakeDamageFromWater = getBoolean("mobs.zombie_villager.takes-damage-from-water", zombieVillagerTakeDamageFromWater);
+ zombieVillagerCuringTimeMin = getInt("mobs.zombie_villager.curing_time.min", zombieVillagerCuringTimeMin);
+ zombieVillagerCuringTimeMax = getInt("mobs.zombie_villager.curing_time.max", zombieVillagerCuringTimeMax);
}
public boolean zombifiedPiglinRidable = false;

View File

@@ -0,0 +1,49 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: 12emin34 <macanovic.emin@gmail.com>
Date: Sat, 7 Aug 2021 20:23:31 +0200
Subject: [PATCH] Option for sponges to work on lava and mud
Co-authored by: granny <granny@purpurmc.org>
diff --git a/src/main/java/net/minecraft/world/level/block/SpongeBlock.java b/src/main/java/net/minecraft/world/level/block/SpongeBlock.java
index e7b19fa84d9dce28dd88a3b4adcb83576dcb98a8..cc1ac862526377b2ac7b66bc20f428dc1aed6e78 100644
--- a/src/main/java/net/minecraft/world/level/block/SpongeBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/SpongeBlock.java
@@ -70,7 +70,7 @@ public class SpongeBlock extends Block {
FluidState fluid = blockList.getFluidState(blockposition1);
// CraftBukkit end
- if (!fluid.is(FluidTags.WATER)) {
+ if (!fluid.is(FluidTags.WATER) && (!world.purpurConfig.spongeAbsorbsLava || !fluid.is(FluidTags.LAVA)) && (!world.purpurConfig.spongeAbsorbsWaterFromMud || !iblockdata.is(Blocks.MUD))) { // Purpur
return false;
} else {
Block block = iblockdata.getBlock();
@@ -85,6 +85,10 @@ public class SpongeBlock extends Block {
if (iblockdata.getBlock() instanceof LiquidBlock) {
blockList.setBlock(blockposition1, Blocks.AIR.defaultBlockState(), 3); // CraftBukkit
+ // Purpur start
+ } else if (iblockdata.is(Blocks.MUD)) {
+ blockList.setBlock(blockposition1, Blocks.CLAY.defaultBlockState(), 3);
+ // Purpur end
} else {
if (!iblockdata.is(Blocks.KELP) && !iblockdata.is(Blocks.KELP_PLANT) && !iblockdata.is(Blocks.SEAGRASS) && !iblockdata.is(Blocks.TALL_SEAGRASS)) {
return false;
diff --git a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
index b2f365ab51b56a83ed7ea67c921c163c3511b834..13aa8ae8f33834793adf18c12541c2ecd2d0699f 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
@@ -949,9 +949,13 @@ public class PurpurWorldConfig {
public int spongeAbsorptionArea = 65;
public int spongeAbsorptionRadius = 6;
+ public boolean spongeAbsorbsLava = false;
+ public boolean spongeAbsorbsWaterFromMud = false;
private void spongeSettings() {
spongeAbsorptionArea = getInt("blocks.sponge.absorption.area", spongeAbsorptionArea);
spongeAbsorptionRadius = getInt("blocks.sponge.absorption.radius", spongeAbsorptionRadius);
+ spongeAbsorbsLava = getBoolean("blocks.sponge.absorbs-lava", spongeAbsorbsLava);
+ spongeAbsorbsWaterFromMud = getBoolean("blocks.sponge.absorbs-water-from-mud", spongeAbsorbsWaterFromMud);
}
public boolean turtleEggsBreakFromExpOrbs = true;

View File

@@ -0,0 +1,39 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: 12emin34 <macanovic.emin@gmail.com>
Date: Sat, 7 Aug 2021 21:27:56 +0200
Subject: [PATCH] Toggle for Wither's spawn sound
diff --git a/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java b/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java
index 86b06182616fe07f1a5ef2b1799c434884cba149..9abc47eb3d0c1a0ee0868ec223431f4de4925c77 100644
--- a/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java
+++ b/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java
@@ -418,7 +418,7 @@ public class WitherBoss extends Monster implements PowerableMob, RangedAttackMob
}
// CraftBukkit end
- if (!this.isSilent()) {
+ if (!this.isSilent() && level().purpurConfig.witherPlaySpawnSound) {
// CraftBukkit start - Use relative location for far away sounds
// this.level().globalLevelEvent(1023, new BlockPosition(this), 0);
int viewDistance = ((ServerLevel) this.level()).getCraftServer().getViewDistance() * 16;
diff --git a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
index 13aa8ae8f33834793adf18c12541c2ecd2d0699f..7670e4e1291e8c48b960ee44977d4850b470a81e 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
@@ -2617,6 +2617,7 @@ public class PurpurWorldConfig {
public boolean witherTakeDamageFromWater = false;
public boolean witherCanRideVehicles = false;
public float witherExplosionRadius = 1.0F;
+ public boolean witherPlaySpawnSound = true;
private void witherSettings() {
witherRidable = getBoolean("mobs.wither.ridable", witherRidable);
witherRidableInWater = getBoolean("mobs.wither.ridable-in-water", witherRidableInWater);
@@ -2638,6 +2639,7 @@ public class PurpurWorldConfig {
witherTakeDamageFromWater = getBoolean("mobs.wither.takes-damage-from-water", witherTakeDamageFromWater);
witherCanRideVehicles = getBoolean("mobs.wither.can-ride-vehicles", witherCanRideVehicles);
witherExplosionRadius = (float) getDouble("mobs.wither.explosion-radius", witherExplosionRadius);
+ witherPlaySpawnSound = getBoolean("mobs.wither.play-spawn-sound", witherPlaySpawnSound);
}
public boolean witherSkeletonRidable = false;

View File

@@ -0,0 +1,35 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: William Blake Galbreath <blake.galbreath@gmail.com>
Date: Sat, 7 Aug 2021 03:37:56 -0500
Subject: [PATCH] Cactus breaks from solid neighbors config
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 0003fb51ae3a6575575e10b4c86719f3061e2577..c2ca3432a47124d02e1aaf8ffb621f9a2c7d7a62 100644
--- a/src/main/java/net/minecraft/world/level/block/CactusBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/CactusBlock.java
@@ -107,7 +107,7 @@ public class CactusBlock extends Block {
enumdirection = (Direction) iterator.next();
iblockdata1 = world.getBlockState(pos.relative(enumdirection));
- } while (!iblockdata1.isSolid() && !world.getFluidState(pos.relative(enumdirection)).is(FluidTags.LAVA));
+ } while ((!world.getWorldBorder().world.purpurConfig.cactusBreaksFromSolidNeighbors || !iblockdata1.isSolid()) && !world.getFluidState(pos.relative(enumdirection)).is(FluidTags.LAVA)); // Purpur
return false;
}
diff --git a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
index 7670e4e1291e8c48b960ee44977d4850b470a81e..2951c05d64f7c1667343dd781800816b7fae5cb9 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
@@ -775,6 +775,11 @@ public class PurpurWorldConfig {
});
}
+ public boolean cactusBreaksFromSolidNeighbors = true;
+ private void cactusSettings() {
+ cactusBreaksFromSolidNeighbors = getBoolean("blocks.cactus.breaks-from-solid-neighbors", cactusBreaksFromSolidNeighbors);
+ }
+
public boolean chestOpenWithBlockOnTop = false;
private void chestSettings() {
chestOpenWithBlockOnTop = getBoolean("blocks.chest.open-with-solid-block-on-top", chestOpenWithBlockOnTop);

View File

@@ -0,0 +1,47 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Encode42 <me@encode42.dev>
Date: Sun, 8 Aug 2021 16:59:21 -0400
Subject: [PATCH] Config to remove curse of binding with weakness
diff --git a/src/main/java/net/minecraft/world/inventory/InventoryMenu.java b/src/main/java/net/minecraft/world/inventory/InventoryMenu.java
index b399903e8f11ec6c12fe7e724b7d9c8292acd573..a4afa946cd47238eb0fed297a27b24013d5ba77c 100644
--- a/src/main/java/net/minecraft/world/inventory/InventoryMenu.java
+++ b/src/main/java/net/minecraft/world/inventory/InventoryMenu.java
@@ -4,6 +4,7 @@ import com.mojang.datafixers.util.Pair;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.Container;
+import net.minecraft.world.effect.MobEffects;
import net.minecraft.world.entity.EquipmentSlot;
import net.minecraft.world.entity.Mob;
import net.minecraft.world.entity.player.Inventory;
@@ -95,7 +96,7 @@ public class InventoryMenu extends RecipeBookMenu<CraftingContainer> {
public boolean mayPickup(Player playerEntity) {
ItemStack itemstack = this.getItem();
- return !itemstack.isEmpty() && !playerEntity.isCreative() && EnchantmentHelper.hasBindingCurse(itemstack) ? false : super.mayPickup(playerEntity);
+ return !itemstack.isEmpty() && !playerEntity.isCreative() && EnchantmentHelper.hasBindingCurse(itemstack) ? playerEntity.level().purpurConfig.playerRemoveBindingWithWeakness && playerEntity.hasEffect(MobEffects.WEAKNESS) : super.mayPickup(playerEntity); // Purpur
}
@Override
diff --git a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
index 2951c05d64f7c1667343dd781800816b7fae5cb9..f64c758f51134e8102ca4092bc313eefd346d211 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
@@ -406,6 +406,7 @@ public class PurpurWorldConfig {
public int playerPortalWaitTime = 80;
public int playerCreativePortalWaitTime = 1;
public boolean playerRidableInWater = false;
+ public boolean playerRemoveBindingWithWeakness = false;
private void playerSettings() {
if (PurpurConfig.version < 19) {
boolean oldVal = getBoolean("gameplay-mechanics.player.idle-timeout.mods-target", idleTimeoutTargetPlayer);
@@ -431,6 +432,7 @@ public class PurpurWorldConfig {
playerPortalWaitTime = getInt("gameplay-mechanics.player.portal-wait-time", playerPortalWaitTime);
playerCreativePortalWaitTime = getInt("gameplay-mechanics.player.creative-portal-wait-time", playerCreativePortalWaitTime);
playerRidableInWater = getBoolean("gameplay-mechanics.player.ridable-in-water", playerRidableInWater);
+ playerRemoveBindingWithWeakness = getBoolean("gameplay-mechanics.player.curse-of-binding.remove-with-weakness", playerRemoveBindingWithWeakness);
}
private static boolean projectileDespawnRateSettingsMigrated = false;

View File

@@ -0,0 +1,110 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Encode42 <me@encode42.dev>
Date: Sun, 8 Aug 2021 18:14:31 -0400
Subject: [PATCH] Conduit behavior configuration
diff --git a/src/main/java/net/minecraft/world/level/block/entity/ConduitBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/ConduitBlockEntity.java
index 963a596154091b79ca139af6274aa323518ad1ad..4dcac3899a500d8586580bcfd5b4516e1dcdcd4a 100644
--- a/src/main/java/net/minecraft/world/level/block/entity/ConduitBlockEntity.java
+++ b/src/main/java/net/minecraft/world/level/block/entity/ConduitBlockEntity.java
@@ -171,7 +171,7 @@ public class ConduitBlockEntity extends BlockEntity {
if ((l > 1 || i1 > 1 || j1 > 1) && (i == 0 && (i1 == 2 || j1 == 2) || j == 0 && (l == 2 || j1 == 2) || k == 0 && (l == 2 || i1 == 2))) {
BlockPos blockposition2 = pos.offset(i, j, k);
BlockState iblockdata = world.getBlockState(blockposition2);
- Block[] ablock = ConduitBlockEntity.VALID_BLOCKS;
+ Block[] ablock = world.purpurConfig.conduitBlocks; // Purpur
int k1 = ablock.length;
for (int l1 = 0; l1 < k1; ++l1) {
@@ -191,7 +191,7 @@ public class ConduitBlockEntity extends BlockEntity {
private static void applyEffects(Level world, BlockPos pos, List<BlockPos> activatingBlocks) {
int i = activatingBlocks.size();
- int j = i / 7 * 16;
+ int j = i / 7 * world.purpurConfig.conduitDistance; // Purpur
int k = pos.getX();
int l = pos.getY();
int i1 = pos.getZ();
@@ -222,21 +222,21 @@ public class ConduitBlockEntity extends BlockEntity {
blockEntity.destroyTarget = ConduitBlockEntity.findDestroyTarget(world, pos, blockEntity.destroyTargetUUID);
blockEntity.destroyTargetUUID = null;
} else if (blockEntity.destroyTarget == null) {
- List<LivingEntity> list1 = world.getEntitiesOfClass(LivingEntity.class, ConduitBlockEntity.getDestroyRangeAABB(pos), (entityliving1) -> {
+ List<LivingEntity> list1 = world.getEntitiesOfClass(LivingEntity.class, ConduitBlockEntity.getDestroyRangeAABB(pos, world), (entityliving1) -> { // Purpur
return entityliving1 instanceof Enemy && entityliving1.isInWaterOrRain();
});
if (!list1.isEmpty()) {
blockEntity.destroyTarget = (LivingEntity) list1.get(world.random.nextInt(list1.size()));
}
- } else if (!blockEntity.destroyTarget.isAlive() || !pos.closerThan(blockEntity.destroyTarget.blockPosition(), 8.0D)) {
+ } else if (!blockEntity.destroyTarget.isAlive() || !pos.closerThan(blockEntity.destroyTarget.blockPosition(), world.purpurConfig.conduitDamageDistance)) { // Purpur
blockEntity.destroyTarget = null;
}
if (blockEntity.destroyTarget != null) {
// CraftBukkit start
CraftEventFactory.blockDamage = CraftBlock.at(world, pos);
- if (blockEntity.destroyTarget.hurt(world.damageSources().magic(), 4.0F)) {
+ if (blockEntity.destroyTarget.hurt(world.damageSources().magic(), world.purpurConfig.conduitDamageAmount)) { // Purpur
world.playSound((Player) null, blockEntity.destroyTarget.getX(), blockEntity.destroyTarget.getY(), blockEntity.destroyTarget.getZ(), SoundEvents.CONDUIT_ATTACK_TARGET, SoundSource.BLOCKS, 1.0F, 1.0F);
}
CraftEventFactory.blockDamage = null;
@@ -262,16 +262,22 @@ public class ConduitBlockEntity extends BlockEntity {
}
private static AABB getDestroyRangeAABB(BlockPos pos) {
+ // Purpur start
+ return getDestroyRangeAABB(pos, null);
+ }
+
+ private static AABB getDestroyRangeAABB(BlockPos pos, Level level) {
+ // Purpur end
int i = pos.getX();
int j = pos.getY();
int k = pos.getZ();
- return (new AABB((double) i, (double) j, (double) k, (double) (i + 1), (double) (j + 1), (double) (k + 1))).inflate(8.0D);
+ return (new AABB((double) i, (double) j, (double) k, (double) (i + 1), (double) (j + 1), (double) (k + 1))).inflate(level == null ? 8.0D : level.purpurConfig.conduitDamageDistance); // Purpur
}
@Nullable
private static LivingEntity findDestroyTarget(Level world, BlockPos pos, UUID uuid) {
- List<LivingEntity> list = world.getEntitiesOfClass(LivingEntity.class, ConduitBlockEntity.getDestroyRangeAABB(pos), (entityliving) -> {
+ List<LivingEntity> list = world.getEntitiesOfClass(LivingEntity.class, ConduitBlockEntity.getDestroyRangeAABB(pos, world), (entityliving) -> { // Purpur
return entityliving.getUUID().equals(uuid);
});
diff --git a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
index f64c758f51134e8102ca4092bc313eefd346d211..5fd3e6bab03a2adcb776720b242c902b1330779e 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
@@ -2836,4 +2836,27 @@ public class PurpurWorldConfig {
private void hungerSettings() {
hungerStarvationDamage = (float) getDouble("hunger.starvation-damage", hungerStarvationDamage);
}
+
+ public int conduitDistance = 16;
+ public double conduitDamageDistance = 8;
+ public float conduitDamageAmount = 4;
+ public Block[] conduitBlocks;
+ private void conduitSettings() {
+ conduitDistance = getInt("blocks.conduit.effect-distance", conduitDistance);
+ conduitDamageDistance = getDouble("blocks.conduit.mob-damage.distance", conduitDamageDistance);
+ conduitDamageAmount = (float) getDouble("blocks.conduit.mob-damage.damage-amount", conduitDamageAmount);
+ List<Block> conduitBlockList = new ArrayList<>();
+ getList("blocks.conduit.valid-ring-blocks", new ArrayList<String>(){{
+ add("minecraft:prismarine");
+ add("minecraft:prismarine_bricks");
+ add("minecraft:sea_lantern");
+ add("minecraft:dark_prismarine");
+ }}).forEach(key -> {
+ Block block = BuiltInRegistries.BLOCK.get(new ResourceLocation(key.toString()));
+ if (!block.defaultBlockState().isAir()) {
+ conduitBlockList.add(block);
+ }
+ });
+ conduitBlocks = conduitBlockList.toArray(Block[]::new);
+ }
}

View File

@@ -0,0 +1,68 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Encode42 <me@encode42.dev>
Date: Sun, 8 Aug 2021 18:38:44 -0400
Subject: [PATCH] Cauldron fill chances
diff --git a/src/main/java/net/minecraft/world/level/block/CauldronBlock.java b/src/main/java/net/minecraft/world/level/block/CauldronBlock.java
index 2f85b893dd0abc39fcedec65acc89e1567faf6f0..3ee012a9ef8cada0b2203e53b2f731f60f697cb1 100644
--- a/src/main/java/net/minecraft/world/level/block/CauldronBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/CauldronBlock.java
@@ -29,7 +29,7 @@ public class CauldronBlock extends AbstractCauldronBlock {
}
protected static boolean shouldHandlePrecipitation(Level world, Biome.Precipitation precipitation) {
- return precipitation == Biome.Precipitation.RAIN ? world.getRandom().nextFloat() < 0.05F : (precipitation == Biome.Precipitation.SNOW ? world.getRandom().nextFloat() < 0.1F : false);
+ return precipitation == Biome.Precipitation.RAIN ? world.getRandom().nextFloat() < world.purpurConfig.cauldronRainChance : (precipitation == Biome.Precipitation.SNOW ? world.getRandom().nextFloat() < world.purpurConfig.cauldronPowderSnowChance : false); // Purpur
}
@Override
diff --git a/src/main/java/net/minecraft/world/level/block/PointedDripstoneBlock.java b/src/main/java/net/minecraft/world/level/block/PointedDripstoneBlock.java
index cd943997f11f5ea5c600fdc6db96043fb0fa713c..4adeda49a2e422e11f885bffb311653d99159bf4 100644
--- a/src/main/java/net/minecraft/world/level/block/PointedDripstoneBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/PointedDripstoneBlock.java
@@ -186,7 +186,7 @@ public class PointedDripstoneBlock extends Block implements Fallable, SimpleWate
@VisibleForTesting
public static void maybeTransferFluid(BlockState state, ServerLevel world, BlockPos pos, float dripChance) {
- if (dripChance <= 0.17578125F || dripChance <= 0.05859375F) {
+ if (dripChance <= world.purpurConfig.cauldronDripstoneWaterFillChance || dripChance <= world.purpurConfig.cauldronDripstoneLavaFillChance) { // Purpur
if (PointedDripstoneBlock.isStalactiteStartPos(state, world, pos)) {
Optional<PointedDripstoneBlock.FluidInfo> optional = PointedDripstoneBlock.getFluidAboveStalactite(world, pos, state);
@@ -195,13 +195,13 @@ public class PointedDripstoneBlock extends Block implements Fallable, SimpleWate
float f1;
if (fluidtype == Fluids.WATER) {
- f1 = 0.17578125F;
+ f1 = world.purpurConfig.cauldronDripstoneWaterFillChance; // Purpur
} else {
if (fluidtype != Fluids.LAVA) {
return;
}
- f1 = 0.05859375F;
+ f1 = world.purpurConfig.cauldronDripstoneLavaFillChance; // Purpur
}
if (dripChance < f1) {
diff --git a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
index 5fd3e6bab03a2adcb776720b242c902b1330779e..909e6bb2781637e5f4c2525371de2ad0b5524afe 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
@@ -2859,4 +2859,15 @@ public class PurpurWorldConfig {
});
conduitBlocks = conduitBlockList.toArray(Block[]::new);
}
+
+ public float cauldronRainChance = 0.05F;
+ public float cauldronPowderSnowChance = 0.1F;
+ public float cauldronDripstoneWaterFillChance = 0.17578125F;
+ public float cauldronDripstoneLavaFillChance = 0.05859375F;
+ private void cauldronSettings() {
+ cauldronRainChance = (float) getDouble("blocks.cauldron.fill-chances.rain", cauldronRainChance);
+ cauldronPowderSnowChance = (float) getDouble("blocks.cauldron.fill-chances.powder-snow", cauldronPowderSnowChance);
+ cauldronDripstoneWaterFillChance = (float) getDouble("blocks.cauldron.fill-chances.dripstone-water", cauldronDripstoneWaterFillChance);
+ cauldronDripstoneLavaFillChance = (float) getDouble("blocks.cauldron.fill-chances.dripstone-lava", cauldronDripstoneLavaFillChance);
+ }
}

View File

@@ -0,0 +1,39 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Encode42 <me@encode42.dev>
Date: Sun, 8 Aug 2021 22:50:23 -0400
Subject: [PATCH] Config to allow mobs to pathfind over rails
diff --git a/src/main/java/net/minecraft/world/level/pathfinder/WalkNodeEvaluator.java b/src/main/java/net/minecraft/world/level/pathfinder/WalkNodeEvaluator.java
index 3583fcf5284bc5883308876dbd9886664b391e28..d976a6df54c1e817def2d588692abe25a03ee0fa 100644
--- a/src/main/java/net/minecraft/world/level/pathfinder/WalkNodeEvaluator.java
+++ b/src/main/java/net/minecraft/world/level/pathfinder/WalkNodeEvaluator.java
@@ -241,7 +241,7 @@ public class WalkNodeEvaluator extends NodeEvaluator {
}
if (blockPathTypes != BlockPathTypes.WALKABLE && (!this.isAmphibious() || blockPathTypes != BlockPathTypes.WATER)) {
- if ((node == null || node.costMalus < 0.0F) && maxYStep > 0 && (blockPathTypes != BlockPathTypes.FENCE || this.canWalkOverFences()) && blockPathTypes != BlockPathTypes.UNPASSABLE_RAIL && blockPathTypes != BlockPathTypes.TRAPDOOR && blockPathTypes != BlockPathTypes.POWDER_SNOW) {
+ if ((node == null || node.costMalus < 0.0F) && maxYStep > 0 && (blockPathTypes != BlockPathTypes.FENCE || this.canWalkOverFences()) && (this.mob.level().purpurConfig.mobsIgnoreRails || blockPathTypes != BlockPathTypes.UNPASSABLE_RAIL) && blockPathTypes != BlockPathTypes.TRAPDOOR && blockPathTypes != BlockPathTypes.POWDER_SNOW) { // Purpur
node = this.findAcceptedNode(x, y + 1, z, maxYStep - 1, prevFeetY, direction, nodeType);
if (node != null && (node.type == BlockPathTypes.OPEN || node.type == BlockPathTypes.WALKABLE) && this.mob.getBbWidth() < 1.0F) {
double g = (double)(x - direction.getStepX()) + 0.5D;
diff --git a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
index 909e6bb2781637e5f4c2525371de2ad0b5524afe..8ae2e7f81d1d6a09d9b733ae27ad6c99a58aeb2e 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
@@ -138,6 +138,7 @@ public class PurpurWorldConfig {
public double voidDamageDealt = 4.0D;
public int raidCooldownSeconds = 0;
public int animalBreedingCooldownSeconds = 0;
+ public boolean mobsIgnoreRails = false;
private void miscGameplayMechanicsSettings() {
useBetterMending = getBoolean("gameplay-mechanics.use-better-mending", useBetterMending);
alwaysTameInCreative = getBoolean("gameplay-mechanics.always-tame-in-creative", alwaysTameInCreative);
@@ -159,6 +160,7 @@ public class PurpurWorldConfig {
voidDamageDealt = getDouble("gameplay-mechanics.void-damage-dealt", voidDamageDealt);
raidCooldownSeconds = getInt("gameplay-mechanics.raid-cooldown-seconds", raidCooldownSeconds);
animalBreedingCooldownSeconds = getInt("gameplay-mechanics.animal-breeding-cooldown-seconds", animalBreedingCooldownSeconds);
+ mobsIgnoreRails = getBoolean("gameplay-mechanics.mobs-ignore-rails", mobsIgnoreRails);
}
public int daytimeTicks = 12000;

View File

@@ -0,0 +1,68 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: William Blake Galbreath <blake.galbreath@gmail.com>
Date: Sat, 21 Aug 2021 00:07:39 -0500
Subject: [PATCH] Shulker change color with dye
diff --git a/src/main/java/net/minecraft/world/entity/monster/Shulker.java b/src/main/java/net/minecraft/world/entity/monster/Shulker.java
index 786fe41cc743817f2ed613969c7eeec9fc001b4b..40f4a53cf244549e9cf392f4286bdec1a6852574 100644
--- a/src/main/java/net/minecraft/world/entity/monster/Shulker.java
+++ b/src/main/java/net/minecraft/world/entity/monster/Shulker.java
@@ -22,6 +22,8 @@ import net.minecraft.tags.DamageTypeTags;
import net.minecraft.util.Mth;
import net.minecraft.world.Difficulty;
import net.minecraft.world.DifficultyInstance;
+import net.minecraft.world.InteractionHand;
+import net.minecraft.world.InteractionResult;
import net.minecraft.world.damagesource.DamageSource;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityDimensions;
@@ -49,6 +51,8 @@ import net.minecraft.world.entity.player.Player;
import net.minecraft.world.entity.projectile.AbstractArrow;
import net.minecraft.world.entity.projectile.ShulkerBullet;
import net.minecraft.world.item.DyeColor;
+import net.minecraft.world.item.DyeItem;
+import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.ServerLevelAccessor;
import net.minecraft.world.level.block.Blocks;
@@ -124,6 +128,19 @@ public class Shulker extends AbstractGolem implements VariantHolder<Optional<Dye
return this.level().purpurConfig.shulkerTakeDamageFromWater;
}
+ @Override
+ protected InteractionResult mobInteract(Player player, InteractionHand hand) {
+ ItemStack itemstack = player.getItemInHand(hand);
+ if (player.level().purpurConfig.shulkerChangeColorWithDye && itemstack.getItem() instanceof DyeItem dye && dye.getDyeColor() != this.getColor()) {
+ this.setVariant(Optional.of(dye.getDyeColor()));
+ if (!player.getAbilities().instabuild) {
+ itemstack.shrink(1);
+ }
+ return InteractionResult.SUCCESS;
+ }
+ return super.mobInteract(player, hand);
+ }
+
@Override
protected void registerGoals() {
this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur
diff --git a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
index 8ae2e7f81d1d6a09d9b733ae27ad6c99a58aeb2e..a8cddd10832e6be2704569b6c1fb995bd9caf0b9 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
@@ -2179,6 +2179,7 @@ public class PurpurWorldConfig {
public double shulkerSpawnFromBulletNearbyRange = 8.0D;
public String shulkerSpawnFromBulletNearbyEquation = "(nearby - 1) / 5.0";
public boolean shulkerSpawnFromBulletRandomColor = false;
+ public boolean shulkerChangeColorWithDye = false;
private void shulkerSettings() {
shulkerRidable = getBoolean("mobs.shulker.ridable", shulkerRidable);
shulkerRidableInWater = getBoolean("mobs.shulker.ridable-in-water", shulkerRidableInWater);
@@ -2195,6 +2196,7 @@ public class PurpurWorldConfig {
shulkerSpawnFromBulletNearbyRange = getDouble("mobs.shulker.spawn-from-bullet.nearby-range", shulkerSpawnFromBulletNearbyRange);
shulkerSpawnFromBulletNearbyEquation = getString("mobs.shulker.spawn-from-bullet.nearby-equation", shulkerSpawnFromBulletNearbyEquation);
shulkerSpawnFromBulletRandomColor = getBoolean("mobs.shulker.spawn-from-bullet.random-color", shulkerSpawnFromBulletRandomColor);
+ shulkerChangeColorWithDye = getBoolean("mobs.shulker.change-color-with-dye", shulkerChangeColorWithDye);
}
public boolean silverfishRidable = false;

View File

@@ -0,0 +1,257 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: YouHaveTrouble <youhavetrouble@youhavetrouble.me>
Date: Sun, 22 Aug 2021 05:12:05 +0200
Subject: [PATCH] Extended OfflinePlayer API
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java b/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java
index 03fc90a470c0f63d44161843cac88bea09166858..88640ac32d70ced6e8b1984663e1c492dd673cb5 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java
@@ -567,4 +567,213 @@ public class CraftOfflinePlayer implements OfflinePlayer, ConfigurationSerializa
manager.save();
}
}
+
+ // Purpur start - OfflinePlayer API
+ @Override
+ public boolean getAllowFlight() {
+ if (this.isOnline()) {
+ return this.getPlayer().getAllowFlight();
+ } else {
+ CompoundTag data = this.getData();
+ if (data == null) return false;
+ if (!data.contains("abilities")) return false;
+ CompoundTag abilities = data.getCompound("abilities");
+ return abilities.getByte("mayfly") == (byte) 1;
+ }
+ }
+
+ @Override
+ public void setAllowFlight(boolean flight) {
+ if (this.isOnline()) {
+ this.getPlayer().setAllowFlight(flight);
+ } else {
+ CompoundTag data = this.getData();
+ if (data == null) return;
+ if (!data.contains("abilities")) return;
+ CompoundTag abilities = data.getCompound("abilities");
+ abilities.putByte("mayfly", (byte) (flight ? 1 : 0));
+ data.put("abilities", abilities);
+ save(data);
+ }
+ }
+
+ @Override
+ public boolean isFlying() {
+ if (this.isOnline()) {
+ return this.isFlying();
+ } else {
+ CompoundTag data = this.getData();
+ if (data == null) return false;
+ if (!data.contains("abilities")) return false;
+ CompoundTag abilities = data.getCompound("abilities");
+ return abilities.getByte("flying") == (byte) 1;
+ }
+ }
+
+ @Override
+ public void setFlying(boolean value) {
+ if (this.isOnline()) {
+ this.getPlayer().setFlying(value);
+ } else {
+ CompoundTag data = this.getData();
+ if (data == null) return;
+ if (!data.contains("abilities")) return;
+ CompoundTag abilities = data.getCompound("abilities");
+ abilities.putByte("mayfly", (byte) (value ? 1 : 0));
+ data.put("abilities", abilities);
+ save(data);
+ }
+ }
+
+ @Override
+ public void setFlySpeed(float value) throws IllegalArgumentException {
+ if (value < -1f || value > 1f) throw new IllegalArgumentException("FlySpeed needs to be between -1 and 1");
+ if (this.isOnline()) {
+ this.getPlayer().setFlySpeed(value);
+ } else {
+ CompoundTag data = this.getData();
+ if (data == null) return;
+ if (!data.contains("abilities")) return;
+ CompoundTag abilities = data.getCompound("abilities");
+ abilities.putFloat("flySpeed", value);
+ data.put("abilities", abilities);
+ save(data);
+ }
+ }
+
+ @Override
+ public float getFlySpeed() {
+ if (this.isOnline()) {
+ return this.getPlayer().getFlySpeed();
+ } else {
+ CompoundTag data = this.getData();
+ if (data == null) return 0;
+ if (!data.contains("abilities")) return 0;
+ CompoundTag abilities = data.getCompound("abilities");
+ return abilities.getFloat("flySpeed");
+ }
+ }
+
+ @Override
+ public void setWalkSpeed(float value) throws IllegalArgumentException {
+ if (value < -1f || value > 1f) throw new IllegalArgumentException("WalkSpeed needs to be between -1 and 1");
+ if (this.isOnline()) {
+ this.getPlayer().setWalkSpeed(value);
+ } else {
+ CompoundTag data = this.getData();
+ if (data == null) return;
+ if (!data.contains("abilities")) return;
+ CompoundTag abilities = data.getCompound("abilities");
+ abilities.putFloat("walkSpeed", value);
+ data.put("abilities", abilities);
+ save(data);
+ }
+ }
+
+ @Override
+ public float getWalkSpeed() {
+ if (this.isOnline()) {
+ return this.getPlayer().getWalkSpeed();
+ } else {
+ CompoundTag data = this.getData();
+ if (data == null) return 0;
+ if (!data.contains("abilities")) return 0;
+ CompoundTag abilities = data.getCompound("abilities");
+ return abilities.getFloat("walkSpeed");
+ }
+ }
+
+ @Override
+ public Location getLocation() {
+ if (this.isOnline()) {
+ return this.getPlayer().getLocation();
+ } else {
+ CompoundTag data = this.getData();
+ if (data == null) return null;
+ long worldUUIDMost = data.getLong("WorldUUIDMost");
+ long worldUUIDLeast = data.getLong("WorldUUIDLeast");
+ net.minecraft.nbt.ListTag position = data.getList("Pos", org.bukkit.craftbukkit.util.CraftMagicNumbers.NBT.TAG_DOUBLE);
+ net.minecraft.nbt.ListTag rotation = data.getList("Rotation", org.bukkit.craftbukkit.util.CraftMagicNumbers.NBT.TAG_FLOAT);
+ UUID worldUuid = new UUID(worldUUIDMost, worldUUIDLeast);
+ org.bukkit.World world = server.getWorld(worldUuid);
+ double x = position.getDouble(0);
+ double y = position.getDouble(1);
+ double z = position.getDouble(2);
+ float yaw = rotation.getFloat(0);
+ float pitch = rotation.getFloat(1);
+ return new Location(world, x, y, z, yaw, pitch);
+ }
+ }
+
+ @Override
+ public boolean teleportOffline(Location destination) {
+ if (this.isOnline()) {
+ return this.getPlayer().teleport(destination);
+ } else {
+ return setLocation(destination);
+ }
+ }
+
+ @Override
+ public boolean teleportOffline(Location destination, org.bukkit.event.player.PlayerTeleportEvent.TeleportCause cause){
+ if (this.isOnline()) {
+ return this.getPlayer().teleport(destination, cause);
+ } else {
+ return setLocation(destination);
+ }
+ }
+
+ @Override
+ public java.util.concurrent.CompletableFuture<Boolean> teleportOfflineAsync(Location destination) {
+ if (this.isOnline()) {
+ return this.getPlayer().teleportAsync(destination);
+ } else {
+ return java.util.concurrent.CompletableFuture.completedFuture(setLocation(destination));
+ }
+ }
+
+ @Override
+ public java.util.concurrent.CompletableFuture<Boolean> teleportOfflineAsync(Location destination, org.bukkit.event.player.PlayerTeleportEvent.TeleportCause cause) {
+ if (this.isOnline()) {
+ return this.getPlayer().teleportAsync(destination, cause);
+ } else {
+ return java.util.concurrent.CompletableFuture.completedFuture(setLocation(destination));
+ }
+ }
+
+ private boolean setLocation(Location location) {
+ CompoundTag data = this.getData();
+ if (data == null) return false;
+ data.putLong("WorldUUIDMost", location.getWorld().getUID().getMostSignificantBits());
+ data.putLong("WorldUUIDLeast", location.getWorld().getUID().getLeastSignificantBits());
+ net.minecraft.nbt.ListTag position = new net.minecraft.nbt.ListTag();
+ position.add(net.minecraft.nbt.DoubleTag.valueOf(location.getX()));
+ position.add(net.minecraft.nbt.DoubleTag.valueOf(location.getY()));
+ position.add(net.minecraft.nbt.DoubleTag.valueOf(location.getZ()));
+ data.put("Pos", position);
+ net.minecraft.nbt.ListTag rotation = new net.minecraft.nbt.ListTag();
+ rotation.add(net.minecraft.nbt.FloatTag.valueOf(location.getYaw()));
+ rotation.add(net.minecraft.nbt.FloatTag.valueOf(location.getPitch()));
+ data.put("Rotation", rotation);
+ save(data);
+ return true;
+ }
+
+ /**
+ * Safely replaces player's .dat file with provided CompoundTag
+ * @param compoundTag
+ */
+ private void save(CompoundTag compoundTag) {
+ File playerDir = server.console.playerDataStorage.getPlayerDir();
+ try {
+ File tempFile = File.createTempFile(this.getUniqueId()+"-", ".dat", playerDir);
+ net.minecraft.nbt.NbtIo.writeCompressed(compoundTag, tempFile);
+ File playerDataFile = new File(playerDir, this.getUniqueId()+".dat");
+ File playerDataFileOld = new File(playerDir, this.getUniqueId()+".dat_old");
+ net.minecraft.Util.safeReplaceFile(playerDataFile, tempFile, playerDataFileOld);
+ } catch (java.io.IOException e) {
+ e.printStackTrace();
+ }
+ }
+ // Purpur end - OfflinePlayer API
}
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
index a0523c36af5a2e33f8f46663794a8df68409f80f..19f6bad1b81c5a5c249631b43e1f6c159dc994e0 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
@@ -2521,6 +2521,28 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
return this.getHandle().getAbilities().walkingSpeed * 2f;
}
+ // Purpur start - OfflinePlayer API
+ @Override
+ public boolean teleportOffline(@NotNull Location destination) {
+ return this.teleport(destination);
+ }
+
+ @Override
+ public boolean teleportOffline(Location destination, PlayerTeleportEvent.TeleportCause cause) {
+ return this.teleport(destination, cause);
+ }
+
+ @Override
+ public java.util.concurrent.CompletableFuture<Boolean> teleportOfflineAsync(@NotNull Location destination) {
+ return this.teleportAsync(destination);
+ }
+
+ @Override
+ public java.util.concurrent.CompletableFuture<Boolean> teleportOfflineAsync(@NotNull Location destination, PlayerTeleportEvent.TeleportCause cause) {
+ return this.teleportAsync(destination, cause);
+ }
+ // Purpur end - OfflinePlayer API
+
private void validateSpeed(float value) {
Preconditions.checkArgument(value <= 1f && value >= -1f, "Speed value (%s) need to be between -1f and 1f", value);
}

View File

@@ -0,0 +1,76 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: DoctaEnkoda <bierquejason@gmail.com>
Date: Mon, 9 Aug 2021 13:22:20 +0200
Subject: [PATCH] Added the ability to add combustible items
diff --git a/src/main/java/net/minecraft/world/inventory/AbstractFurnaceMenu.java b/src/main/java/net/minecraft/world/inventory/AbstractFurnaceMenu.java
index 1af7e1548f0648890a1ef2fc0ff4e4c3a56c947c..decea1697c075e7549ccc7501c8e59357d198a60 100644
--- a/src/main/java/net/minecraft/world/inventory/AbstractFurnaceMenu.java
+++ b/src/main/java/net/minecraft/world/inventory/AbstractFurnaceMenu.java
@@ -147,7 +147,13 @@ public abstract class AbstractFurnaceMenu extends RecipeBookMenu<Container> {
} else if (slot != 1 && slot != 0) {
if (this.canSmelt(itemstack1)) {
if (!this.moveItemStackTo(itemstack1, 0, 1, false)) {
- return ItemStack.EMPTY;
+ // Purpur start - fix #625
+ if (this.isFuel(itemstack1)) {
+ if (!this.moveItemStackTo(itemstack1, 1, 2, false)) {
+ return ItemStack.EMPTY;
+ }
+ }
+ // Purpur end
}
} else if (this.isFuel(itemstack1)) {
if (!this.moveItemStackTo(itemstack1, 1, 2, false)) {
diff --git a/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java
index b0afc384907bb75dfa26e432a2328fe080660019..92e58d9503daf4cc9bc1f4c7785e159e0c1f4bf3 100644
--- a/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java
+++ b/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java
@@ -208,6 +208,22 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit
// Paper end
}
+ // Purpur start
+ public static void addFuel(ItemStack itemStack, Integer burnTime) {
+ Map<Item, Integer> map = Maps.newLinkedHashMap();
+ map.putAll(getFuel());
+ map.put(itemStack.getItem(), burnTime);
+ cachedBurnDurations = com.google.common.collect.ImmutableMap.copyOf(map);
+ }
+
+ public static void removeFuel(ItemStack itemStack) {
+ Map<Item, Integer> map = Maps.newLinkedHashMap();
+ map.putAll(getFuel());
+ map.remove(itemStack.getItem());
+ cachedBurnDurations = com.google.common.collect.ImmutableMap.copyOf(map);
+ }
+ // Purpur End
+
// CraftBukkit start - add fields and methods
private int maxStack = MAX_STACK;
public List<HumanEntity> transaction = new java.util.ArrayList<HumanEntity>();
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
index 3f06e418e1322b966f19b488beb2780e7168b45b..cb912efba182aff9e8f080aa473f78115eae8a47 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
@@ -1532,6 +1532,19 @@ public final class CraftServer implements Server {
return true;
}
+ // Purpur Start
+ @Override
+ public void addFuel(org.bukkit.Material material, int burnTime) {
+ Preconditions.checkArgument(burnTime > 0, "BurnTime must be greater than 0");
+ net.minecraft.world.level.block.entity.AbstractFurnaceBlockEntity.addFuel(net.minecraft.world.item.ItemStack.fromBukkitCopy(new ItemStack(material)), burnTime);
+ }
+
+ @Override
+ public void removeFuel(org.bukkit.Material material) {
+ net.minecraft.world.level.block.entity.AbstractFurnaceBlockEntity.removeFuel(net.minecraft.world.item.ItemStack.fromBukkitCopy(new ItemStack(material)));
+ }
+ // Purpur End
+
@Override
public List<Recipe> getRecipesFor(ItemStack result) {
Preconditions.checkArgument(result != null, "ItemStack cannot be null");

View File

@@ -0,0 +1,48 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: 12emin34 <macanovic.emin@gmail.com>
Date: Mon, 23 Aug 2021 17:59:29 +0200
Subject: [PATCH] Option for if rain and thunder should stop on sleep
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
index bbb3052a3b2704e25696457d53d0940664fa263a..cb35bac1923fe40f172a521ce5892e0dcfd7e305 100644
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
@@ -1241,6 +1241,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
private void resetWeatherCycle() {
// CraftBukkit start
+ if (this.purpurConfig.rainStopsAfterSleep) // Purpur
this.serverLevelData.setRaining(false, org.bukkit.event.weather.WeatherChangeEvent.Cause.SLEEP); // Paper - when passing the night
// If we stop due to everyone sleeping we should reset the weather duration to some other random value.
// Not that everyone ever manages to get the whole server to sleep at the same time....
@@ -1248,6 +1249,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
this.serverLevelData.setRainTime(0);
}
// CraftBukkit end
+ if (this.purpurConfig.thunderStopsAfterSleep) // Purpur
this.serverLevelData.setThundering(false, org.bukkit.event.weather.ThunderChangeEvent.Cause.SLEEP); // Paper - when passing the night
// CraftBukkit start
// If we stop due to everyone sleeping we should reset the weather duration to some other random value.
diff --git a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
index a8cddd10832e6be2704569b6c1fb995bd9caf0b9..1da30e052c08c27370755cae3e1890a397a2f323 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
@@ -139,6 +139,8 @@ public class PurpurWorldConfig {
public int raidCooldownSeconds = 0;
public int animalBreedingCooldownSeconds = 0;
public boolean mobsIgnoreRails = false;
+ public boolean rainStopsAfterSleep = true;
+ public boolean thunderStopsAfterSleep = true;
private void miscGameplayMechanicsSettings() {
useBetterMending = getBoolean("gameplay-mechanics.use-better-mending", useBetterMending);
alwaysTameInCreative = getBoolean("gameplay-mechanics.always-tame-in-creative", alwaysTameInCreative);
@@ -161,6 +163,8 @@ public class PurpurWorldConfig {
raidCooldownSeconds = getInt("gameplay-mechanics.raid-cooldown-seconds", raidCooldownSeconds);
animalBreedingCooldownSeconds = getInt("gameplay-mechanics.animal-breeding-cooldown-seconds", animalBreedingCooldownSeconds);
mobsIgnoreRails = getBoolean("gameplay-mechanics.mobs-ignore-rails", mobsIgnoreRails);
+ rainStopsAfterSleep = getBoolean("gameplay-mechanics.rain-stops-after-sleep", rainStopsAfterSleep);
+ thunderStopsAfterSleep = getBoolean("gameplay-mechanics.thunder-stops-after-sleep", thunderStopsAfterSleep);
}
public int daytimeTicks = 12000;

View File

@@ -0,0 +1,74 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: William Blake Galbreath <blake.galbreath@gmail.com>
Date: Mon, 23 Aug 2021 20:57:04 -0500
Subject: [PATCH] Chance for azalea blocks to grow into trees naturally
diff --git a/src/main/java/net/minecraft/world/level/block/AzaleaBlock.java b/src/main/java/net/minecraft/world/level/block/AzaleaBlock.java
index 087f3b3cc180e16195efdc0b402701fd9f5d78b4..aa4e13f1c77f10221128569483497668cd2eb7d3 100644
--- a/src/main/java/net/minecraft/world/level/block/AzaleaBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/AzaleaBlock.java
@@ -43,6 +43,20 @@ public class AzaleaBlock extends BushBlock implements BonemealableBlock {
@Override
public void performBonemeal(ServerLevel world, RandomSource random, BlockPos pos, BlockState state) {
+ // Purpur start
+ growTree(world, random, pos, state);
+ }
+
+ @Override
+ public void randomTick(net.minecraft.world.level.block.state.BlockState state, ServerLevel world, BlockPos pos, RandomSource random) {
+ double chance = state.getBlock() == Blocks.FLOWERING_AZALEA ? world.purpurConfig.floweringAzaleaGrowthChance : world.purpurConfig.azaleaGrowthChance;
+ if (chance > 0.0D && world.getMaxLocalRawBrightness(pos.above()) > 9 && random.nextDouble() < chance) {
+ growTree(world, random, pos, state);
+ }
+ }
+
+ private void growTree(ServerLevel world, RandomSource random, BlockPos pos, net.minecraft.world.level.block.state.BlockState state) {
+ // Purpur end
TREE_GROWER.growTree(world, world.getChunkSource().getGenerator(), pos, state, random);
}
diff --git a/src/main/java/net/minecraft/world/level/block/Blocks.java b/src/main/java/net/minecraft/world/level/block/Blocks.java
index b49e02ac7b3db9a5b79ce3f106ead19af4e7cfa6..6425bc42bb8024aa7936b841d6c2ee2c892eb329 100644
--- a/src/main/java/net/minecraft/world/level/block/Blocks.java
+++ b/src/main/java/net/minecraft/world/level/block/Blocks.java
@@ -1094,8 +1094,8 @@ public class Blocks {
public static final Block CAVE_VINES = register("cave_vines", new CaveVinesBlock(BlockBehaviour.Properties.of().mapColor(MapColor.PLANT).randomTicks().noCollission().lightLevel(CaveVines.emission(14)).instabreak().sound(SoundType.CAVE_VINES).pushReaction(PushReaction.DESTROY)));
public static final Block CAVE_VINES_PLANT = register("cave_vines_plant", new CaveVinesPlantBlock(BlockBehaviour.Properties.of().mapColor(MapColor.PLANT).noCollission().lightLevel(CaveVines.emission(14)).instabreak().sound(SoundType.CAVE_VINES).pushReaction(PushReaction.DESTROY)));
public static final Block SPORE_BLOSSOM = register("spore_blossom", new SporeBlossomBlock(BlockBehaviour.Properties.of().mapColor(MapColor.PLANT).instabreak().noCollission().sound(SoundType.SPORE_BLOSSOM).pushReaction(PushReaction.DESTROY)));
- public static final Block AZALEA = register("azalea", new AzaleaBlock(BlockBehaviour.Properties.of().mapColor(MapColor.PLANT).forceSolidOff().instabreak().sound(SoundType.AZALEA).noOcclusion().pushReaction(PushReaction.DESTROY)));
- public static final Block FLOWERING_AZALEA = register("flowering_azalea", new AzaleaBlock(BlockBehaviour.Properties.of().mapColor(MapColor.PLANT).forceSolidOff().instabreak().sound(SoundType.FLOWERING_AZALEA).noOcclusion().pushReaction(PushReaction.DESTROY)));
+ public static final Block AZALEA = register("azalea", new AzaleaBlock(BlockBehaviour.Properties.of().mapColor(MapColor.PLANT).forceSolidOff().randomTicks().instabreak().sound(SoundType.AZALEA).noOcclusion().pushReaction(PushReaction.DESTROY))); // Purpur
+ public static final Block FLOWERING_AZALEA = register("flowering_azalea", new AzaleaBlock(BlockBehaviour.Properties.of().mapColor(MapColor.PLANT).forceSolidOff().randomTicks().instabreak().sound(SoundType.FLOWERING_AZALEA).noOcclusion().pushReaction(PushReaction.DESTROY))); // Purpur
public static final Block MOSS_CARPET = register("moss_carpet", new CarpetBlock(BlockBehaviour.Properties.of().mapColor(MapColor.COLOR_GREEN).strength(0.1F).sound(SoundType.MOSS_CARPET).pushReaction(PushReaction.DESTROY)));
public static final Block PINK_PETALS = register("pink_petals", new PinkPetalsBlock(BlockBehaviour.Properties.of().mapColor(MapColor.PLANT).noCollission().sound(SoundType.PINK_PETALS).pushReaction(PushReaction.DESTROY)));
public static final Block MOSS_BLOCK = register("moss_block", new MossBlock(BlockBehaviour.Properties.of().mapColor(MapColor.COLOR_GREEN).strength(0.1F).sound(SoundType.MOSS).pushReaction(PushReaction.DESTROY)));
diff --git a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
index 1da30e052c08c27370755cae3e1890a397a2f323..a3a5decf6586569c347d36f4416cf3cb3b0bef78 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
@@ -735,6 +735,11 @@ public class PurpurWorldConfig {
anvilColorsUseMiniMessage = getBoolean("blocks.anvil.use-mini-message", anvilColorsUseMiniMessage);
}
+ public double azaleaGrowthChance = 0.0D;
+ private void azaleaSettings() {
+ azaleaGrowthChance = getDouble("blocks.azalea.growth-chance", azaleaGrowthChance);
+ }
+
public int beaconLevelOne = 20;
public int beaconLevelTwo = 30;
public int beaconLevelThree = 40;
@@ -872,6 +877,11 @@ public class PurpurWorldConfig {
farmlandTramplingFeatherFalling = getBoolean("blocks.farmland.feather-fall-distance-affects-trampling", farmlandTramplingFeatherFalling);
}
+ public double floweringAzaleaGrowthChance = 0.0D;
+ private void floweringAzaleaSettings() {
+ floweringAzaleaGrowthChance = getDouble("blocks.flowering_azalea.growth-chance", floweringAzaleaGrowthChance);
+ }
+
public boolean furnaceUseLavaFromUnderneath = false;
private void furnaceSettings() {
if (PurpurConfig.version < 17) {

View File

@@ -0,0 +1,69 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: William Blake Galbreath <blake.galbreath@gmail.com>
Date: Tue, 24 Aug 2021 16:48:35 -0500
Subject: [PATCH] Shift right click to use exp for mending
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java
index 0488fe39acf7191754707b7c8f424e6a3e32c152..bcce65e453bec778739e8b2f9d89356f41dbbd20 100644
--- a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java
+++ b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java
@@ -516,6 +516,7 @@ public class ServerPlayerGameMode {
public InteractionHand interactHand;
public ItemStack interactItemStack;
public InteractionResult useItemOn(ServerPlayer player, Level world, ItemStack stack, InteractionHand hand, BlockHitResult hitResult) {
+ if (shiftClickMended(stack)) return InteractionResult.SUCCESS; // Purpur
BlockPos blockposition = hitResult.getBlockPos();
BlockState iblockdata = world.getBlockState(blockposition);
InteractionResult enuminteractionresult = InteractionResult.PASS;
@@ -618,4 +619,18 @@ public class ServerPlayerGameMode {
public void setLevel(ServerLevel world) {
this.level = world;
}
+
+ // Purpur start
+ public boolean shiftClickMended(ItemStack itemstack) {
+ if (this.player.level().purpurConfig.shiftRightClickRepairsMendingPoints > 0 && this.player.isShiftKeyDown() && this.player.getBukkitEntity().hasPermission("purpur.mending_shift_click")) {
+ int points = Math.min(this.player.totalExperience, this.player.level().purpurConfig.shiftRightClickRepairsMendingPoints);
+ if (points > 0 && itemstack.isDamaged() && net.minecraft.world.item.enchantment.EnchantmentHelper.getItemEnchantmentLevel(net.minecraft.world.item.enchantment.Enchantments.MENDING, itemstack) > 0) {
+ this.player.giveExperiencePoints(-points);
+ this.player.level().addFreshEntity(new net.minecraft.world.entity.ExperienceOrb(this.player.level(), this.player.getX(), this.player.getY(), this.player.getZ(), points, org.bukkit.entity.ExperienceOrb.SpawnReason.UNKNOWN, this.player, this.player));
+ return true;
+ }
+ }
+ return false;
+ }
+ // Purpur end
}
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
index fe4f8517f1d3614568be697720908609776f353e..70eaf9347d49924841f2cfa23932b3eadfe49c82 100644
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -2019,6 +2019,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
boolean cancelled;
if (movingobjectposition == null || movingobjectposition.getType() != HitResult.Type.BLOCK) {
+ if (this.player.gameMode.shiftClickMended(itemstack)) return; // Purpur
org.bukkit.event.player.PlayerInteractEvent event = CraftEventFactory.callPlayerInteractEvent(this.player, Action.RIGHT_CLICK_AIR, itemstack, enumhand);
cancelled = event.useItemInHand() == Event.Result.DENY;
} else {
diff --git a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
index a3a5decf6586569c347d36f4416cf3cb3b0bef78..8e658c5e81b85fa4fa36b9e18a02bd0634e42554 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
@@ -413,6 +413,7 @@ public class PurpurWorldConfig {
public int playerCreativePortalWaitTime = 1;
public boolean playerRidableInWater = false;
public boolean playerRemoveBindingWithWeakness = false;
+ public int shiftRightClickRepairsMendingPoints = 0;
private void playerSettings() {
if (PurpurConfig.version < 19) {
boolean oldVal = getBoolean("gameplay-mechanics.player.idle-timeout.mods-target", idleTimeoutTargetPlayer);
@@ -439,6 +440,7 @@ public class PurpurWorldConfig {
playerCreativePortalWaitTime = getInt("gameplay-mechanics.player.creative-portal-wait-time", playerCreativePortalWaitTime);
playerRidableInWater = getBoolean("gameplay-mechanics.player.ridable-in-water", playerRidableInWater);
playerRemoveBindingWithWeakness = getBoolean("gameplay-mechanics.player.curse-of-binding.remove-with-weakness", playerRemoveBindingWithWeakness);
+ shiftRightClickRepairsMendingPoints = getInt("gameplay-mechanics.player.shift-right-click-repairs-mending-points", shiftRightClickRepairsMendingPoints);
}
private static boolean projectileDespawnRateSettingsMigrated = false;

View File

@@ -0,0 +1,69 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: William Blake Galbreath <blake.galbreath@gmail.com>
Date: Mon, 30 Aug 2021 22:14:39 -0500
Subject: [PATCH] Dolphins naturally aggressive to players chance
diff --git a/src/main/java/net/minecraft/world/entity/animal/Dolphin.java b/src/main/java/net/minecraft/world/entity/animal/Dolphin.java
index 77746eeffdc612793a6c907f222753bce5cd0ed4..b6342637f1b42b6368dcda17eea4b39a22ec3b79 100644
--- a/src/main/java/net/minecraft/world/entity/animal/Dolphin.java
+++ b/src/main/java/net/minecraft/world/entity/animal/Dolphin.java
@@ -82,6 +82,7 @@ public class Dolphin extends WaterAnimal {
public static final Predicate<ItemEntity> ALLOWED_ITEMS = (entityitem) -> {
return !entityitem.hasPickUpDelay() && entityitem.isAlive() && entityitem.isInWater();
};
+ private boolean isNaturallyAggressiveToPlayers; // Purpur
private int spitCooldown; // Purpur
public Dolphin(EntityType<? extends Dolphin> type, Level world) {
@@ -173,6 +174,7 @@ public class Dolphin extends WaterAnimal {
public SpawnGroupData finalizeSpawn(ServerLevelAccessor world, DifficultyInstance difficulty, MobSpawnType spawnReason, @Nullable SpawnGroupData entityData, @Nullable CompoundTag entityNbt) {
this.setAirSupply(this.getMaxAirSupply());
this.setXRot(0.0F);
+ this.isNaturallyAggressiveToPlayers = world.getLevel().purpurConfig.dolphinNaturallyAggressiveToPlayersChance > 0.0D && random.nextDouble() <= world.getLevel().purpurConfig.dolphinNaturallyAggressiveToPlayersChance; // Purpur
return super.finalizeSpawn(world, difficulty, spawnReason, entityData, entityNbt);
}
@@ -242,6 +244,7 @@ public class Dolphin extends WaterAnimal {
protected void registerGoals() {
this.goalSelector.addGoal(0, new BreathAirGoal(this));
this.goalSelector.addGoal(0, new TryFindWaterGoal(this));
+ this.goalSelector.addGoal(1, new MeleeAttackGoal(this, 1.2000000476837158D, true)); // Purpur
this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur
this.goalSelector.addGoal(1, new Dolphin.DolphinSwimToTreasureGoal(this));
this.goalSelector.addGoal(2, new Dolphin.DolphinSwimWithPlayerGoal(this, 4.0D));
@@ -249,12 +252,13 @@ public class Dolphin extends WaterAnimal {
this.goalSelector.addGoal(4, new RandomLookAroundGoal(this));
this.goalSelector.addGoal(5, new LookAtPlayerGoal(this, Player.class, 6.0F));
this.goalSelector.addGoal(5, new DolphinJumpGoal(this, 10));
- this.goalSelector.addGoal(6, new MeleeAttackGoal(this, 1.2000000476837158D, true));
+ //this.goalSelector.addGoal(6, new MeleeAttackGoal(this, 1.2000000476837158D, true)); // Purpur - moved up
this.goalSelector.addGoal(8, new Dolphin.PlayWithItemsGoal());
this.goalSelector.addGoal(8, new FollowBoatGoal(this));
this.goalSelector.addGoal(9, new AvoidEntityGoal<>(this, Guardian.class, 8.0F, 1.0D, 1.0D));
this.targetSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur
this.targetSelector.addGoal(1, (new HurtByTargetGoal(this, new Class[]{Guardian.class})).setAlertOthers());
+ this.targetSelector.addGoal(2, new net.minecraft.world.entity.ai.goal.target.NearestAttackableTargetGoal<>(this, Player.class, 10, true, false, target -> isNaturallyAggressiveToPlayers)); // Purpur
}
public static AttributeSupplier.Builder createAttributes() {
diff --git a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
index 8e658c5e81b85fa4fa36b9e18a02bd0634e42554..c146356aa04126f2cd74aabf50c1436fa111aa6a 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
@@ -1277,6 +1277,7 @@ public class PurpurWorldConfig {
public double dolphinMaxHealth = 10.0D;
public boolean dolphinDisableTreasureSearching = false;
public boolean dolphinTakeDamageFromWater = false;
+ public double dolphinNaturallyAggressiveToPlayersChance = 0.0D;
private void dolphinSettings() {
dolphinRidable = getBoolean("mobs.dolphin.ridable", dolphinRidable);
dolphinControllable = getBoolean("mobs.dolphin.controllable", dolphinControllable);
@@ -1291,6 +1292,7 @@ public class PurpurWorldConfig {
dolphinMaxHealth = getDouble("mobs.dolphin.attributes.max_health", dolphinMaxHealth);
dolphinDisableTreasureSearching = getBoolean("mobs.dolphin.disable-treasure-searching", dolphinDisableTreasureSearching);
dolphinTakeDamageFromWater = getBoolean("mobs.dolphin.takes-damage-from-water", dolphinTakeDamageFromWater);
+ dolphinNaturallyAggressiveToPlayersChance = getDouble("mobs.dolphin.naturally-aggressive-to-players-chance", dolphinNaturallyAggressiveToPlayersChance);
}
public boolean donkeyRidableInWater = false;

View File

@@ -0,0 +1,86 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: William Blake Galbreath <blake.galbreath@gmail.com>
Date: Mon, 30 Aug 2021 22:49:53 -0500
Subject: [PATCH] Cows naturally aggressive to players chance
diff --git a/src/main/java/net/minecraft/world/entity/animal/Cow.java b/src/main/java/net/minecraft/world/entity/animal/Cow.java
index f76b0d92150fd985a8fc699f6f884527d589dfd3..3c12e179861b5514e081d0db1664f7173955629c 100644
--- a/src/main/java/net/minecraft/world/entity/animal/Cow.java
+++ b/src/main/java/net/minecraft/world/entity/animal/Cow.java
@@ -42,6 +42,7 @@ import org.bukkit.event.player.PlayerBucketFillEvent;
// CraftBukkit end
public class Cow extends Animal {
+ private boolean isNaturallyAggressiveToPlayers; // Purpur
public Cow(EntityType<? extends Cow> type, Level world) {
super(type, world);
@@ -67,6 +68,7 @@ public class Cow extends Animal {
@Override
public void initAttributes() {
this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(this.level().purpurConfig.cowMaxHealth);
+ this.getAttribute(Attributes.ATTACK_DAMAGE).setBaseValue(this.level().purpurConfig.cowNaturallyAggressiveToPlayersDamage); // Purpur
}
@Override
@@ -79,11 +81,18 @@ public class Cow extends Animal {
return this.level().purpurConfig.cowTakeDamageFromWater;
}
+ @Override
+ public net.minecraft.world.entity.SpawnGroupData finalizeSpawn(net.minecraft.world.level.ServerLevelAccessor world, net.minecraft.world.DifficultyInstance difficulty, net.minecraft.world.entity.MobSpawnType spawnReason, net.minecraft.world.entity.SpawnGroupData entityData, net.minecraft.nbt.CompoundTag entityNbt) {
+ this.isNaturallyAggressiveToPlayers = world.getLevel().purpurConfig.cowNaturallyAggressiveToPlayersChance > 0.0D && random.nextDouble() <= world.getLevel().purpurConfig.cowNaturallyAggressiveToPlayersChance;
+ return super.finalizeSpawn(world, difficulty, spawnReason, entityData, entityNbt);
+ }
+
@Override
protected void registerGoals() {
this.goalSelector.addGoal(0, new FloatGoal(this));
this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur
this.goalSelector.addGoal(1, new PanicGoal(this, 2.0D));
+ this.goalSelector.addGoal(1, new net.minecraft.world.entity.ai.goal.MeleeAttackGoal(this, 1.2000000476837158D, true)); // Purpur
this.goalSelector.addGoal(2, new BreedGoal(this, 1.0D));
if (level().purpurConfig.cowFeedMushrooms > 0) this.goalSelector.addGoal(3, new TemptGoal(this, 1.25D, Ingredient.of(Items.WHEAT, Blocks.RED_MUSHROOM.asItem(), Blocks.BROWN_MUSHROOM.asItem()), false)); else // Purpur
this.goalSelector.addGoal(3, new TemptGoal(this, 1.25D, Ingredient.of(Items.WHEAT), false));
@@ -91,10 +100,11 @@ public class Cow extends Animal {
this.goalSelector.addGoal(5, new WaterAvoidingRandomStrollGoal(this, 1.0D));
this.goalSelector.addGoal(6, new LookAtPlayerGoal(this, Player.class, 6.0F));
this.goalSelector.addGoal(7, new RandomLookAroundGoal(this));
+ this.targetSelector.addGoal(0, new net.minecraft.world.entity.ai.goal.target.NearestAttackableTargetGoal<>(this, Player.class, 10, true, false, target -> isNaturallyAggressiveToPlayers)); // Purpur
}
public static AttributeSupplier.Builder createAttributes() {
- return Mob.createMobAttributes().add(Attributes.MAX_HEALTH, 10.0D).add(Attributes.MOVEMENT_SPEED, 0.20000000298023224D);
+ return Mob.createMobAttributes().add(Attributes.MAX_HEALTH, 10.0D).add(Attributes.MOVEMENT_SPEED, 0.20000000298023224D).add(Attributes.ATTACK_DAMAGE, 0.0D); // Purpur
}
@Override
diff --git a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
index c146356aa04126f2cd74aabf50c1436fa111aa6a..e752c2050b696a0f1db12c5301fbe940488d87d1 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
@@ -1226,7 +1226,14 @@ public class PurpurWorldConfig {
public int cowFeedMushrooms = 0;
public int cowBreedingTicks = 6000;
public boolean cowTakeDamageFromWater = false;
+ public double cowNaturallyAggressiveToPlayersChance = 0.0D;
+ public double cowNaturallyAggressiveToPlayersDamage = 2.0D;
private void cowSettings() {
+ if (PurpurConfig.version < 22) {
+ double oldValue = getDouble("mobs.cow.naturally-aggressive-to-players-chance", cowNaturallyAggressiveToPlayersChance);
+ set("mobs.cow.naturally-aggressive-to-players-chance", null);
+ set("mobs.cow.naturally-aggressive-to-players.chance", oldValue);
+ }
cowRidable = getBoolean("mobs.cow.ridable", cowRidable);
cowRidableInWater = getBoolean("mobs.cow.ridable-in-water", cowRidableInWater);
cowControllable = getBoolean("mobs.cow.controllable", cowControllable);
@@ -1239,6 +1246,8 @@ public class PurpurWorldConfig {
cowFeedMushrooms = getInt("mobs.cow.feed-mushrooms-for-mooshroom", cowFeedMushrooms);
cowBreedingTicks = getInt("mobs.cow.breeding-delay-ticks", cowBreedingTicks);
cowTakeDamageFromWater = getBoolean("mobs.cow.takes-damage-from-water", cowTakeDamageFromWater);
+ cowNaturallyAggressiveToPlayersChance = getDouble("mobs.cow.naturally-aggressive-to-players.chance", cowNaturallyAggressiveToPlayersChance);
+ cowNaturallyAggressiveToPlayersDamage = getDouble("mobs.cow.naturally-aggressive-to-players.damage", cowNaturallyAggressiveToPlayersDamage);
}
public boolean creeperRidable = false;

View File

@@ -0,0 +1,43 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: 12emin34 <macanovic.emin@gmail.com>
Date: Tue, 31 Aug 2021 16:48:29 +0200
Subject: [PATCH] Option for beds to explode on villager sleep
diff --git a/src/main/java/net/minecraft/world/entity/npc/Villager.java b/src/main/java/net/minecraft/world/entity/npc/Villager.java
index d24f970c50c1a4937b66e7eb6e3edc1d3b61a07e..bae27f98d3deaa855da9bc2dc6e8bd7d80fea786 100644
--- a/src/main/java/net/minecraft/world/entity/npc/Villager.java
+++ b/src/main/java/net/minecraft/world/entity/npc/Villager.java
@@ -1113,6 +1113,12 @@ public class Villager extends AbstractVillager implements ReputationEventHandler
@Override
public void startSleeping(BlockPos pos) {
+ // Purpur start
+ if (level().purpurConfig.bedExplodeOnVillagerSleep && this.level().getBlockState(pos).getBlock() instanceof net.minecraft.world.level.block.BedBlock) {
+ this.level().explode(null, (double) pos.getX() + 0.5D, (double) pos.getY() + 0.5D, (double) pos.getZ() + 0.5D, (float) this.level().purpurConfig.bedExplosionPower, this.level().purpurConfig.bedExplosionFire, this.level().purpurConfig.bedExplosionEffect);
+ return;
+ }
+ // Purpur end
super.startSleeping(pos);
this.brain.setMemory(MemoryModuleType.LAST_SLEPT, this.level().getGameTime()); // CraftBukkit - decompile error
this.brain.eraseMemory(MemoryModuleType.WALK_TARGET);
diff --git a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
index e752c2050b696a0f1db12c5301fbe940488d87d1..dae834b637164fabea2b17d2d752a04df31ee88a 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
@@ -754,6 +754,7 @@ public class PurpurWorldConfig {
}
public boolean bedExplode = true;
+ public boolean bedExplodeOnVillagerSleep = false;
public double bedExplosionPower = 5.0D;
public boolean bedExplosionFire = true;
public net.minecraft.world.level.Level.ExplosionInteraction bedExplosionEffect = net.minecraft.world.level.Level.ExplosionInteraction.BLOCK;
@@ -764,6 +765,7 @@ public class PurpurWorldConfig {
}
}
bedExplode = getBoolean("blocks.bed.explode", bedExplode);
+ bedExplodeOnVillagerSleep = getBoolean("blocks.bed.explode-on-villager-sleep", bedExplodeOnVillagerSleep);
bedExplosionPower = getDouble("blocks.bed.explosion-power", bedExplosionPower);
bedExplosionFire = getBoolean("blocks.bed.explosion-fire", bedExplosionFire);
try {

View File

@@ -0,0 +1,79 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: DoctaEnkoda <bierquejason@gmail.com>
Date: Mon, 13 Sep 2021 04:48:21 +0200
Subject: [PATCH] Halloween options and optimizations
diff --git a/src/main/java/net/minecraft/world/entity/ambient/Bat.java b/src/main/java/net/minecraft/world/entity/ambient/Bat.java
index 91c7295b75cee5b9fc18434b94a67cb8db0151e3..fb3fff24d0146711faf1cd5eba706004ce203618 100644
--- a/src/main/java/net/minecraft/world/entity/ambient/Bat.java
+++ b/src/main/java/net/minecraft/world/entity/ambient/Bat.java
@@ -300,7 +300,7 @@ public class Bat extends AmbientCreature {
int i = world.getMaxLocalRawBrightness(pos);
byte b0 = 4;
- if (Bat.isHalloween()) {
+ if (Bat.isHalloweenSeason(world.getMinecraftWorld())) { // Purpur
b0 = 7;
} else if (random.nextBoolean()) {
return false;
@@ -310,6 +310,7 @@ public class Bat extends AmbientCreature {
}
}
+ public static boolean isHalloweenSeason(Level level) { return level.purpurConfig.forceHalloweenSeason || isHalloween(); } // Purpur
private static boolean isHalloween() {
LocalDate localdate = LocalDate.now();
int i = localdate.get(ChronoField.DAY_OF_MONTH);
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 f35637a105d5aa12fb57c2456f2b2a7db12a49f0..f3e1fa62d9f067c0fe8aacb88bf30b01ee0562c1 100644
--- a/src/main/java/net/minecraft/world/entity/monster/AbstractSkeleton.java
+++ b/src/main/java/net/minecraft/world/entity/monster/AbstractSkeleton.java
@@ -143,11 +143,7 @@ public abstract class AbstractSkeleton extends Monster implements RangedAttackMo
this.reassessWeaponGoal();
this.setCanPickUpLoot(this.level().paperConfig().entities.behavior.mobsCanAlwaysPickUpLoot.skeletons || randomsource.nextFloat() < 0.55F * difficulty.getSpecialMultiplier()); // Paper
if (this.getItemBySlot(EquipmentSlot.HEAD).isEmpty()) {
- LocalDate localdate = LocalDate.now();
- int i = localdate.get(ChronoField.DAY_OF_MONTH);
- int j = localdate.get(ChronoField.MONTH_OF_YEAR);
-
- if (j == 10 && i == 31 && randomsource.nextFloat() < 0.25F) {
+ if (net.minecraft.world.entity.ambient.Bat.isHalloweenSeason(world.getMinecraftWorld()) && this.random.nextFloat() < this.level().purpurConfig.chanceHeadHalloweenOnEntity) { // Purpur
this.setItemSlot(EquipmentSlot.HEAD, new ItemStack(randomsource.nextFloat() < 0.1F ? Blocks.JACK_O_LANTERN : Blocks.CARVED_PUMPKIN));
this.armorDropChances[EquipmentSlot.HEAD.getIndex()] = 0.0F;
}
diff --git a/src/main/java/net/minecraft/world/entity/monster/Zombie.java b/src/main/java/net/minecraft/world/entity/monster/Zombie.java
index 143ac5fac02a29516d03b69008b1345555857640..c265d2abd36857f6a25f8e0584e7cf939637b7a9 100644
--- a/src/main/java/net/minecraft/world/entity/monster/Zombie.java
+++ b/src/main/java/net/minecraft/world/entity/monster/Zombie.java
@@ -594,11 +594,7 @@ public class Zombie extends Monster {
}
if (this.getItemBySlot(EquipmentSlot.HEAD).isEmpty()) {
- LocalDate localdate = LocalDate.now();
- int i = localdate.get(ChronoField.DAY_OF_MONTH);
- int j = localdate.get(ChronoField.MONTH_OF_YEAR);
-
- if (j == 10 && i == 31 && randomsource.nextFloat() < 0.25F) {
+ if (net.minecraft.world.entity.ambient.Bat.isHalloweenSeason(world.getMinecraftWorld()) && this.random.nextFloat() < this.level().purpurConfig.chanceHeadHalloweenOnEntity) { // Purpur
this.setItemSlot(EquipmentSlot.HEAD, new ItemStack(randomsource.nextFloat() < 0.1F ? Blocks.JACK_O_LANTERN : Blocks.CARVED_PUMPKIN));
this.armorDropChances[EquipmentSlot.HEAD.getIndex()] = 0.0F;
}
diff --git a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
index dae834b637164fabea2b17d2d752a04df31ee88a..9f3fe0265904da5a4be55fd3bc0ed1d283d241a9 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
@@ -1619,6 +1619,13 @@ public class PurpurWorldConfig {
guardianTakeDamageFromWater = getBoolean("mobs.guardian.takes-damage-from-water", guardianTakeDamageFromWater);
}
+ public boolean forceHalloweenSeason = false;
+ public float chanceHeadHalloweenOnEntity = 0.25F;
+ private void halloweenSetting() {
+ forceHalloweenSeason = getBoolean("gameplay-mechanics.halloween.force", forceHalloweenSeason);
+ chanceHeadHalloweenOnEntity = (float) getDouble("gameplay-mechanics.halloween.head-chance", chanceHeadHalloweenOnEntity);
+ }
+
public boolean hoglinRidable = false;
public boolean hoglinRidableInWater = true;
public boolean hoglinControllable = true;

View File

@@ -0,0 +1,92 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Encode42 <me@encode42.dev>
Date: Wed, 29 Sep 2021 13:37:57 -0400
Subject: [PATCH] Config for grindstones
diff --git a/src/main/java/net/minecraft/world/inventory/GrindstoneMenu.java b/src/main/java/net/minecraft/world/inventory/GrindstoneMenu.java
index a21eadcdfbdc4be803c5793bc97996db3e706071..132a07e226ae3ac6b5abc6f53c62345e2ab2f31f 100644
--- a/src/main/java/net/minecraft/world/inventory/GrindstoneMenu.java
+++ b/src/main/java/net/minecraft/world/inventory/GrindstoneMenu.java
@@ -130,7 +130,7 @@ public class GrindstoneMenu extends AbstractContainerMenu {
Enchantment enchantment = (Enchantment) entry.getKey();
Integer integer = (Integer) entry.getValue();
- if (!enchantment.isCurse()) {
+ if (!org.purpurmc.purpur.PurpurConfig.grindstoneIgnoredEnchants.contains(enchantment)) { // Purpur
j += enchantment.getMinCost(integer);
}
}
@@ -230,7 +230,7 @@ public class GrindstoneMenu extends AbstractContainerMenu {
Entry<Enchantment, Integer> entry = (Entry) iterator.next();
Enchantment enchantment = (Enchantment) entry.getKey();
- if (!enchantment.isCurse() || EnchantmentHelper.getItemEnchantmentLevel(enchantment, itemstack2) == 0) {
+ if (!org.purpurmc.purpur.PurpurConfig.grindstoneIgnoredEnchants.contains(enchantment) || EnchantmentHelper.getItemEnchantmentLevel(enchantment, itemstack2) == 0) { // Purpur
itemstack2.enchant(enchantment, (Integer) entry.getValue());
}
}
@@ -250,7 +250,7 @@ public class GrindstoneMenu extends AbstractContainerMenu {
}
Map<Enchantment, Integer> map = (Map) EnchantmentHelper.getEnchantments(item).entrySet().stream().filter((entry) -> {
- return ((Enchantment) entry.getKey()).isCurse();
+ return org.purpurmc.purpur.PurpurConfig.grindstoneIgnoredEnchants.contains((Enchantment) entry.getKey()); // Purpur
}).collect(Collectors.toMap(Entry::getKey, Entry::getValue));
EnchantmentHelper.setEnchantments(map, itemstack1);
@@ -266,6 +266,20 @@ public class GrindstoneMenu extends AbstractContainerMenu {
itemstack1.setRepairCost(AnvilMenu.calculateIncreasedRepairCost(itemstack1.getBaseRepairCost()));
}
+ // Purpur start
+ if (org.purpurmc.purpur.PurpurConfig.grindstoneRemoveAttributes && itemstack1.getTag() != null) {
+ for (String key : itemstack1.getTag().getAllKeys()) {
+ if (!key.equals("display")) {
+ itemstack1.getTag().remove(key);
+ }
+ }
+ }
+
+ if (org.purpurmc.purpur.PurpurConfig.grindstoneRemoveDisplay && itemstack1.getTag() != null) {
+ itemstack1.getTag().remove("display");
+ }
+ // Purpur end
+
return itemstack1;
}
diff --git a/src/main/java/org/purpurmc/purpur/PurpurConfig.java b/src/main/java/org/purpurmc/purpur/PurpurConfig.java
index 62fa79eccbb6f679c0460a6dfd457c405b3a8e67..f3449eb7a1433a8420c0de6f4649f0fae70b2294 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurConfig.java
@@ -309,6 +309,9 @@ public class PurpurConfig {
public static int beeInsideBeeHive = 3;
public static boolean anvilCumulativeCost = true;
public static int lightningRodRange = 128;
+ public static Set<Enchantment> grindstoneIgnoredEnchants = new HashSet<>();
+ public static boolean grindstoneRemoveAttributes = false;
+ public static boolean grindstoneRemoveDisplay = false;
private static void blockSettings() {
if (version < 3) {
boolean oldValue = getBoolean("settings.barrel.packed-barrels", true);
@@ -343,6 +346,19 @@ public class PurpurConfig {
beeInsideBeeHive = getInt("settings.blocks.beehive.max-bees-inside", beeInsideBeeHive);
anvilCumulativeCost = getBoolean("settings.blocks.anvil.cumulative-cost", anvilCumulativeCost);
lightningRodRange = getInt("settings.blocks.lightning_rod.range", lightningRodRange);
+ ArrayList<String> defaultCurses = new ArrayList<>(){{
+ add("minecraft:binding_curse");
+ add("minecraft:vanishing_curse");
+ }};
+ if (version < 24 && !getBoolean("settings.blocks.grindstone.ignore-curses", true)) {
+ defaultCurses.clear();
+ }
+ getList("settings.blocks.grindstone.ignored-enchants", defaultCurses).forEach(key -> {
+ Enchantment enchantment = BuiltInRegistries.ENCHANTMENT.get(new ResourceLocation(key.toString()));
+ grindstoneIgnoredEnchants.add(enchantment);
+ });
+ grindstoneRemoveAttributes = getBoolean("settings.blocks.grindstone.remove-attributes", grindstoneRemoveAttributes);
+ grindstoneRemoveDisplay = getBoolean("settings.blocks.grindstone.remove-name-and-lore", grindstoneRemoveDisplay);
}
public static boolean allowInfinityMending = false;

View File

@@ -0,0 +1,82 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: William Blake Galbreath <Blake.Galbreath@GMail.com>
Date: Wed, 22 Jan 2020 20:13:40 -0600
Subject: [PATCH] UPnP Port Forwarding
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
index caaa154082fef69c6bf3ff6101242de5b037c583..5018f85fd87fe167389706bda04327bbe7d2c17a 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -303,6 +303,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
public final io.papermc.paper.configuration.PaperConfigurations paperConfigurations;
public static long currentTickLong = 0L; // Paper
public boolean lagging = false; // Purpur
+ protected boolean upnp = false; // Purpur
public volatile Thread shutdownThread; // Paper
public volatile boolean abnormalExit = false; // Paper
@@ -924,6 +925,14 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
MinecraftServer.LOGGER.info("Stopping server");
Commands.COMMAND_SENDING_POOL.shutdownNow(); // Paper - Shutdown and don't bother finishing
MinecraftTimings.stopServer(); // Paper
+ // Purpur start
+ if (upnp) {
+ if (dev.omega24.upnp4j.UPnP4J.close(this.getPort(), dev.omega24.upnp4j.util.Protocol.TCP)) {
+ LOGGER.info("[UPnP] Port {} closed", this.getPort());
+ } else {
+ LOGGER.error("[UPnP] Failed to close port {}", this.getPort());
+ }
+ }
// CraftBukkit start
if (this.server != null) {
this.server.disablePlugins();
diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
index f7e15e75333ae24ab97483aedccb60bb631a506d..2075f8f6096178930708268d0c4e2862824cbc45 100644
--- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
+++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
@@ -276,6 +276,30 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface
DedicatedServer.LOGGER.warn("Perhaps a server is already running on that port?");
return false;
}
+ // Purpur start
+ if (org.purpurmc.purpur.PurpurConfig.useUPnP) {
+ LOGGER.info("[UPnP] Attempting to start UPnP port forwarding service...");
+ if (dev.omega24.upnp4j.UPnP4J.isUPnPAvailable()) {
+ if (dev.omega24.upnp4j.UPnP4J.isOpen(this.getPort(), dev.omega24.upnp4j.util.Protocol.TCP)) {
+ this.upnp = false;
+ LOGGER.info("[UPnP] Port {} is already open", this.getPort());
+ } else if (dev.omega24.upnp4j.UPnP4J.open(this.getPort(), dev.omega24.upnp4j.util.Protocol.TCP)) {
+ this.upnp = true;
+ LOGGER.info("[UPnP] Successfully opened port {}", this.getPort());
+ } else {
+ this.upnp = false;
+ LOGGER.info("[UPnP] Failed to open port {}", this.getPort());
+ }
+
+ if (upnp) {
+ LOGGER.info("[UPnP] {}:{}", dev.omega24.upnp4j.UPnP4J.getExternalIP(), this.getPort());
+ }
+ } else {
+ this.upnp = false;
+ LOGGER.error("[UPnP] Service is unavailable");
+ }
+ }
+ // Purpur end
// CraftBukkit start
// this.setPlayerList(new DedicatedPlayerList(this, this.registries(), this.playerDataStorage)); // Spigot - moved up
diff --git a/src/main/java/org/purpurmc/purpur/PurpurConfig.java b/src/main/java/org/purpurmc/purpur/PurpurConfig.java
index f3449eb7a1433a8420c0de6f4649f0fae70b2294..f6cd1c56dcc3f7d118edc6d7a63e42da166ebd5f 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurConfig.java
@@ -419,4 +419,9 @@ public class PurpurConfig {
private static void tpsCatchup() {
tpsCatchup = getBoolean("settings.tps-catchup", tpsCatchup);
}
+
+ public static boolean useUPnP = false;
+ private static void networkSettings() {
+ useUPnP = getBoolean("settings.network.upnp-port-forwarding", useUPnP);
+ }
}

View File

@@ -0,0 +1,35 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: granny <granny@purpurmc.org>
Date: Thu, 14 Oct 2021 01:53:20 -0700
Subject: [PATCH] Campfire option for lit when placed
diff --git a/src/main/java/net/minecraft/world/level/block/CampfireBlock.java b/src/main/java/net/minecraft/world/level/block/CampfireBlock.java
index 7700461b8cd0bde1bf6c0d5e4b73184bed1adc4e..cfa02b274286374c7555919d0e8d66a2c8fb8b88 100644
--- a/src/main/java/net/minecraft/world/level/block/CampfireBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/CampfireBlock.java
@@ -123,7 +123,7 @@ public class CampfireBlock extends BaseEntityBlock implements SimpleWaterloggedB
BlockPos blockposition = ctx.getClickedPos();
boolean flag = world.getFluidState(blockposition).getType() == Fluids.WATER;
- return (BlockState) ((BlockState) ((BlockState) ((BlockState) this.defaultBlockState().setValue(CampfireBlock.WATERLOGGED, flag)).setValue(CampfireBlock.SIGNAL_FIRE, this.isSmokeSource(world.getBlockState(blockposition.below())))).setValue(CampfireBlock.LIT, !flag)).setValue(CampfireBlock.FACING, ctx.getHorizontalDirection());
+ return (BlockState) ((BlockState) ((BlockState) ((BlockState) this.defaultBlockState().setValue(CampfireBlock.WATERLOGGED, flag)).setValue(CampfireBlock.SIGNAL_FIRE, this.isSmokeSource(world.getBlockState(blockposition.below())))).setValue(CampfireBlock.LIT, world.purpurConfig.campFireLitWhenPlaced ? !flag : world.purpurConfig.campFireLitWhenPlaced)).setValue(CampfireBlock.FACING, ctx.getHorizontalDirection()); // Purpur
}
@Override
diff --git a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
index 9f3fe0265904da5a4be55fd3bc0ed1d283d241a9..19684e9d59f57d587818dcf5debd4873944298bf 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
@@ -797,6 +797,11 @@ public class PurpurWorldConfig {
cactusBreaksFromSolidNeighbors = getBoolean("blocks.cactus.breaks-from-solid-neighbors", cactusBreaksFromSolidNeighbors);
}
+ public boolean campFireLitWhenPlaced = true;
+ private void campFireSettings() {
+ campFireLitWhenPlaced = getBoolean("blocks.campfire.lit-when-placed", campFireLitWhenPlaced);
+ }
+
public boolean chestOpenWithBlockOnTop = false;
private void chestSettings() {
chestOpenWithBlockOnTop = getBoolean("blocks.chest.open-with-solid-block-on-top", chestOpenWithBlockOnTop);

View File

@@ -0,0 +1,71 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: granny <granny@purpurmc.org>
Date: Thu, 14 Oct 2021 02:05:52 -0700
Subject: [PATCH] options to extinguish fire blocks with snowballs
diff --git a/src/main/java/net/minecraft/world/entity/projectile/Snowball.java b/src/main/java/net/minecraft/world/entity/projectile/Snowball.java
index b90cedad282e95a067aca176fafa9f72a726f520..440d3d72d8b2dac14f83a83caa5ae9dbf3e979b6 100644
--- a/src/main/java/net/minecraft/world/entity/projectile/Snowball.java
+++ b/src/main/java/net/minecraft/world/entity/projectile/Snowball.java
@@ -57,6 +57,36 @@ public class Snowball extends ThrowableItemProjectile {
entity.hurt(this.damageSources().thrown(this, this.getOwner()), (float)i);
}
+ // Purpur start - borrowed and modified code from ThrownPotion#onHitBlock and ThrownPotion#dowseFire
+ @Override
+ protected void onHitBlock(net.minecraft.world.phys.BlockHitResult blockHitResult) {
+ super.onHitBlock(blockHitResult);
+
+ if (!this.level().isClientSide) {
+ net.minecraft.core.BlockPos blockposition = blockHitResult.getBlockPos();
+ net.minecraft.core.BlockPos blockposition1 = blockposition.relative(blockHitResult.getDirection());
+
+ net.minecraft.world.level.block.state.BlockState iblockdata = this.level().getBlockState(blockposition);
+
+ if (this.level().purpurConfig.snowballExtinguishesFire && this.level().getBlockState(blockposition1).is(net.minecraft.world.level.block.Blocks.FIRE)) {
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(this, blockposition1, net.minecraft.world.level.block.Blocks.AIR.defaultBlockState())) {
+ this.level().removeBlock(blockposition1, false);
+ }
+ } else if (this.level().purpurConfig.snowballExtinguishesCandles && net.minecraft.world.level.block.AbstractCandleBlock.isLit(iblockdata)) {
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(this, blockposition, iblockdata.setValue(net.minecraft.world.level.block.AbstractCandleBlock.LIT, false))) {
+ net.minecraft.world.level.block.AbstractCandleBlock.extinguish(null, iblockdata, this.level(), blockposition);
+ }
+ } else if (this.level().purpurConfig.snowballExtinguishesCampfires && net.minecraft.world.level.block.CampfireBlock.isLitCampfire(iblockdata)) {
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(this, blockposition, iblockdata.setValue(net.minecraft.world.level.block.CampfireBlock.LIT, false))) {
+ this.level().levelEvent(null, 1009, blockposition, 0);
+ net.minecraft.world.level.block.CampfireBlock.dowse(this.getOwner(), this.level(), blockposition, iblockdata);
+ this.level().setBlockAndUpdate(blockposition, iblockdata.setValue(net.minecraft.world.level.block.CampfireBlock.LIT, false));
+ }
+ }
+ }
+ }
+ // Purpur end
+
@Override
protected void onHit(HitResult hitResult) {
super.onHit(hitResult);
diff --git a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
index 19684e9d59f57d587818dcf5debd4873944298bf..51350d67992bba19be24bfbc75968cae29ca5d98 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
@@ -231,6 +231,9 @@ public class PurpurWorldConfig {
public int glowBerriesEatGlowDuration = 0;
public boolean shulkerBoxItemDropContentsWhenDestroyed = true;
public boolean compassItemShowsBossBar = false;
+ public boolean snowballExtinguishesFire = false;
+ public boolean snowballExtinguishesCandles = false;
+ public boolean snowballExtinguishesCampfires = false;
private void itemSettings() {
itemImmuneToCactus.clear();
getList("gameplay-mechanics.item.immune.cactus", new ArrayList<>()).forEach(key -> {
@@ -279,6 +282,9 @@ public class PurpurWorldConfig {
glowBerriesEatGlowDuration = getInt("gameplay-mechanics.item.glow_berries.eat-glow-duration", glowBerriesEatGlowDuration);
shulkerBoxItemDropContentsWhenDestroyed = getBoolean("gameplay-mechanics.item.shulker_box.drop-contents-when-destroyed", shulkerBoxItemDropContentsWhenDestroyed);
compassItemShowsBossBar = getBoolean("gameplay-mechanics.item.compass.holding-shows-bossbar", compassItemShowsBossBar);
+ snowballExtinguishesFire = getBoolean("gameplay-mechanics.item.snowball.extinguish.fire", snowballExtinguishesFire);
+ snowballExtinguishesCandles = getBoolean("gameplay-mechanics.item.snowball.extinguish.candles", snowballExtinguishesCandles);
+ snowballExtinguishesCampfires = getBoolean("gameplay-mechanics.item.snowball.extinguish.campfires", snowballExtinguishesCampfires);
}
public double minecartMaxSpeed = 0.4D;

View File

@@ -0,0 +1,39 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: rafael59r2 <12960698+rafael59r2@users.noreply.github.com>
Date: Tue, 19 Oct 2021 13:10:44 +0100
Subject: [PATCH] Add option to disable zombie villagers cure
diff --git a/src/main/java/net/minecraft/world/entity/monster/ZombieVillager.java b/src/main/java/net/minecraft/world/entity/monster/ZombieVillager.java
index ecf41531855e1f60d9739ac6d2d82df7794f072f..4bac02d30ec28ea0bce069f0f915b660b99b122d 100644
--- a/src/main/java/net/minecraft/world/entity/monster/ZombieVillager.java
+++ b/src/main/java/net/minecraft/world/entity/monster/ZombieVillager.java
@@ -215,7 +215,7 @@ public class ZombieVillager extends Zombie implements VillagerDataHolder {
ItemStack itemstack = player.getItemInHand(hand);
if (itemstack.is(Items.GOLDEN_APPLE)) {
- if (this.hasEffect(MobEffects.WEAKNESS)) {
+ if (this.hasEffect(MobEffects.WEAKNESS) && level().purpurConfig.zombieVillagerCureEnabled) { // Purpur
if (!player.getAbilities().instabuild) {
itemstack.shrink(1);
}
diff --git a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
index 51350d67992bba19be24bfbc75968cae29ca5d98..cbf30293766899b7aa66dc922ba76395feca1094 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
@@ -2836,6 +2836,7 @@ public class PurpurWorldConfig {
public boolean zombieVillagerTakeDamageFromWater = false;
public int zombieVillagerCuringTimeMin = 3600;
public int zombieVillagerCuringTimeMax = 6000;
+ public boolean zombieVillagerCureEnabled = true;
private void zombieVillagerSettings() {
zombieVillagerRidable = getBoolean("mobs.zombie_villager.ridable", zombieVillagerRidable);
zombieVillagerRidableInWater = getBoolean("mobs.zombie_villager.ridable-in-water", zombieVillagerRidableInWater);
@@ -2853,6 +2854,7 @@ public class PurpurWorldConfig {
zombieVillagerTakeDamageFromWater = getBoolean("mobs.zombie_villager.takes-damage-from-water", zombieVillagerTakeDamageFromWater);
zombieVillagerCuringTimeMin = getInt("mobs.zombie_villager.curing_time.min", zombieVillagerCuringTimeMin);
zombieVillagerCuringTimeMax = getInt("mobs.zombie_villager.curing_time.max", zombieVillagerCuringTimeMax);
+ zombieVillagerCureEnabled = getBoolean("mobs.zombie_villager.cure.enabled", zombieVillagerCureEnabled);
}
public boolean zombifiedPiglinRidable = false;

View File

@@ -0,0 +1,216 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jason Penilla <11360596+jpenilla@users.noreply.github.com>
Date: Wed, 30 Sep 2020 14:32:46 -0700
Subject: [PATCH] Persistent BlockEntity Lore and DisplayName
Makes it so that when a BlockEntity is placed in the world and then broken,
the dropped ItemStack retains any original custom display name/lore.
diff --git a/src/main/java/net/minecraft/world/item/BlockItem.java b/src/main/java/net/minecraft/world/item/BlockItem.java
index ec58193ebd73130f14dc5d8f51caa913b2036fc5..41728bcbd5ca3585da64f7c3289b26977f90c229 100644
--- a/src/main/java/net/minecraft/world/item/BlockItem.java
+++ b/src/main/java/net/minecraft/world/item/BlockItem.java
@@ -153,7 +153,24 @@ public class BlockItem extends Item {
}
protected boolean updateCustomBlockEntityTag(BlockPos pos, Level world, @Nullable Player player, ItemStack stack, BlockState state) {
- return BlockItem.updateCustomBlockEntityTag(world, player, pos, stack);
+ // Purpur start
+ boolean handled = updateCustomBlockEntityTag(world, player, pos, stack);
+ if (world.purpurConfig.persistentTileEntityDisplayNames && stack.hasTag()) {
+ CompoundTag display = stack.getTagElement("display");
+ if (display != null) {
+ BlockEntity blockEntity = world.getBlockEntity(pos);
+ if (blockEntity != null) {
+ if (display.contains("Name", 8)) {
+ blockEntity.setPersistentDisplayName(display.getString("Name"));
+ }
+ if (display.contains("Lore", 9)) {
+ blockEntity.setPersistentLore(display.getList("Lore", 8));
+ }
+ }
+ }
+ }
+ return handled;
+ // Purpur end
}
@Nullable
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 f65b54919d19d2ddc7261cc36853babbaef3c822..cee9e07a250ed61570cf9787236308f91724f02f 100644
--- a/src/main/java/net/minecraft/world/level/block/Block.java
+++ b/src/main/java/net/minecraft/world/level/block/Block.java
@@ -62,6 +62,13 @@ import net.minecraft.world.phys.shapes.Shapes;
import net.minecraft.world.phys.shapes.VoxelShape;
import org.slf4j.Logger;
+// Purpur start
+import net.minecraft.nbt.CompoundTag;
+import net.minecraft.nbt.ListTag;
+import net.minecraft.nbt.StringTag;
+import net.minecraft.world.Nameable;
+// Purpur end
+
public class Block extends BlockBehaviour implements ItemLike {
private static final Logger LOGGER = LogUtils.getLogger();
@@ -313,7 +320,7 @@ public class Block extends BlockBehaviour implements ItemLike {
public static void dropResources(BlockState state, LevelAccessor world, BlockPos pos, @Nullable BlockEntity blockEntity) {
if (world instanceof ServerLevel) {
Block.getDrops(state, (ServerLevel) world, pos, blockEntity).forEach((itemstack) -> {
- Block.popResource((ServerLevel) world, pos, itemstack);
+ Block.popResource((ServerLevel) world, pos, applyDisplayNameAndLoreFromTile(itemstack, blockEntity)); // Purpur
});
state.spawnAfterBreak((ServerLevel) world, pos, ItemStack.EMPTY, true);
}
@@ -329,7 +336,7 @@ public class Block extends BlockBehaviour implements ItemLike {
io.papermc.paper.event.block.BlockBreakBlockEvent event = new io.papermc.paper.event.block.BlockBreakBlockEvent(org.bukkit.craftbukkit.block.CraftBlock.at(world, pos), org.bukkit.craftbukkit.block.CraftBlock.at(world, source), items);
event.callEvent();
for (var drop : event.getDrops()) {
- popResource(world.getMinecraftWorld(), pos, org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(drop));
+ popResource(world.getMinecraftWorld(), pos, applyDisplayNameAndLoreFromTile(org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(drop), blockEntity)); // Purpur
}
state.spawnAfterBreak(world.getMinecraftWorld(), pos, ItemStack.EMPTY, true);
}
@@ -340,13 +347,53 @@ public class Block extends BlockBehaviour implements ItemLike {
public static void dropResources(BlockState state, Level world, BlockPos pos, @Nullable BlockEntity blockEntity, @Nullable Entity entity, ItemStack tool) {
if (world instanceof ServerLevel) {
Block.getDrops(state, (ServerLevel) world, pos, blockEntity, entity, tool).forEach((itemstack1) -> {
- Block.popResource(world, pos, itemstack1);
+ Block.popResource(world, pos, applyDisplayNameAndLoreFromTile(itemstack1, blockEntity)); // Purpur
});
state.spawnAfterBreak((ServerLevel) world, pos, tool, true);
}
}
+ // Purpur start
+ private static ItemStack applyDisplayNameAndLoreFromTile(ItemStack stack, BlockEntity blockEntity) {
+ if (stack.getItem() instanceof BlockItem) {
+ if (blockEntity != null && blockEntity.getLevel() instanceof ServerLevel && blockEntity.getLevel().purpurConfig.persistentTileEntityDisplayNames) {
+ String name = blockEntity.getPersistentDisplayName();
+ ListTag lore = blockEntity.getPersistentLore();
+ if (blockEntity instanceof Nameable) {
+ Nameable namedTile = (Nameable) blockEntity;
+ if (namedTile.hasCustomName()) {
+ name = Component.Serializer.toJson(namedTile.getCustomName());
+ }
+ }
+
+ if (name != null || lore != null) {
+ CompoundTag display = stack.getTagElement("display");
+ if (display == null) {
+ display = new CompoundTag();
+ }
+
+ if (name != null) {
+ display.put("Name", StringTag.valueOf(name));
+ }
+ if (lore != null) {
+ display.put("Lore", lore);
+ }
+
+ CompoundTag tag = stack.getTag();
+ if (tag == null) {
+ tag = new CompoundTag();
+ }
+ tag.put("display", display);
+
+ stack.setTag(tag);
+ }
+ }
+ }
+ return stack;
+ }
+ // Purpur end
+
public static void popResource(Level world, BlockPos pos, ItemStack stack) {
double d0 = (double) EntityType.ITEM.getHeight() / 2.0D;
double d1 = (double) pos.getX() + 0.5D + Mth.nextDouble(world.random, -0.25D, 0.25D);
diff --git a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java
index 370a25d2deb54f10a35ee24d9e7e92fbfde60edf..2f19f6ac5de454845f5d13a3ebb93af625b2afc8 100644
--- a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java
+++ b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java
@@ -6,6 +6,8 @@ import net.minecraft.CrashReportCategory;
import net.minecraft.core.BlockPos;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.nbt.CompoundTag;
+import net.minecraft.nbt.ListTag;
+import net.minecraft.nbt.StringTag;
import net.minecraft.network.protocol.Packet;
import net.minecraft.network.protocol.game.ClientGamePacketListener;
import net.minecraft.resources.ResourceLocation;
@@ -73,10 +75,27 @@ public abstract class BlockEntity {
if (persistentDataTag instanceof CompoundTag) {
this.persistentDataContainer.putAll((CompoundTag) persistentDataTag);
}
+ // Purpur start
+ if (nbt.contains("Purpur.persistentDisplayName")) {
+ this.persistentDisplayName = nbt.getString("Purpur.persistentDisplayName");
+ }
+ if (nbt.contains("Purpur.persistentLore")) {
+ this.persistentLore = nbt.getList("Purpur.persistentLore", 8);
+ }
+ // Purpur end
}
// CraftBukkit end
- protected void saveAdditional(CompoundTag nbt) {}
+ protected void saveAdditional(CompoundTag nbt) {
+ // Purpur start
+ if (this.persistentDisplayName != null) {
+ nbt.put("Purpur.persistentDisplayName", StringTag.valueOf(this.persistentDisplayName));
+ }
+ if (this.persistentLore != null) {
+ nbt.put("Purpur.persistentLore", this.persistentLore);
+ }
+ // Purpur end
+ }
public final CompoundTag saveWithFullMetadata() {
CompoundTag nbttagcompound = this.saveWithoutMetadata();
@@ -263,4 +282,24 @@ public abstract class BlockEntity {
}
// Paper end
+ // Purpur start
+ private String persistentDisplayName = null;
+ private ListTag persistentLore = null;
+
+ public void setPersistentDisplayName(String json) {
+ this.persistentDisplayName = json;
+ }
+
+ public void setPersistentLore(ListTag lore) {
+ this.persistentLore = lore;
+ }
+
+ public String getPersistentDisplayName() {
+ return this.persistentDisplayName;
+ }
+
+ public ListTag getPersistentLore() {
+ return this.persistentLore;
+ }
+ // Purpur end
}
diff --git a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
index cbf30293766899b7aa66dc922ba76395feca1094..0f8384ba3bb9b6f36bb36bf833c260076b49014e 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
@@ -130,6 +130,7 @@ public class PurpurWorldConfig {
public boolean milkCuresBadOmen = true;
public boolean noteBlockIgnoreAbove = false;
public boolean persistentDroppableEntityDisplayNames = true;
+ public boolean persistentTileEntityDisplayNames = false;
public boolean projectilesBypassMobGriefing = false;
public boolean tickFluids = true;
public double mobsBlindnessMultiplier = 1;
@@ -153,6 +154,7 @@ public class PurpurWorldConfig {
imposeTeleportRestrictionsOnGateways = getBoolean("gameplay-mechanics.impose-teleport-restrictions-on-gateways", imposeTeleportRestrictionsOnGateways);
milkCuresBadOmen = getBoolean("gameplay-mechanics.milk-cures-bad-omen", milkCuresBadOmen);
noteBlockIgnoreAbove = getBoolean("gameplay-mechanics.note-block-ignore-above", noteBlockIgnoreAbove);
+ persistentTileEntityDisplayNames = getBoolean("gameplay-mechanics.persistent-tileentity-display-names-and-lore", persistentTileEntityDisplayNames);
persistentDroppableEntityDisplayNames = getBoolean("gameplay-mechanics.persistent-droppable-entity-display-names", persistentDroppableEntityDisplayNames);
projectilesBypassMobGriefing = getBoolean("gameplay-mechanics.projectiles-bypass-mob-griefing", projectilesBypassMobGriefing);
tickFluids = getBoolean("gameplay-mechanics.tick-fluids", tickFluids);

View File

@@ -0,0 +1,101 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: William Blake Galbreath <blake.galbreath@gmail.com>
Date: Thu, 6 Jun 2019 17:40:30 -0500
Subject: [PATCH] Signs allow color codes
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
index 3e08dcd1a46adc6ef769f2cfc85970ad9cbbdd10..4f9796dfb1243befb6fa41b4fd633951a4bf0fc6 100644
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
@@ -1576,6 +1576,7 @@ public class ServerPlayer extends Player {
@Override
public void openTextEdit(SignBlockEntity sign, boolean front) {
+ if (level().purpurConfig.signAllowColors) this.connection.send(sign.getTranslatedUpdatePacket(textFilteringEnabled, front)); // Purpur
this.connection.send(new ClientboundBlockUpdatePacket(this.level(), sign.getBlockPos()));
this.connection.send(new ClientboundOpenSignEditorPacket(sign.getBlockPos(), front));
}
diff --git a/src/main/java/net/minecraft/world/level/block/entity/SignBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/SignBlockEntity.java
index 38cde466714e5663cd416b6afd5d2558e139ec09..2d625f18f2ba42ee5a1ebeea78ca395ad6f88b37 100644
--- a/src/main/java/net/minecraft/world/level/block/entity/SignBlockEntity.java
+++ b/src/main/java/net/minecraft/world/level/block/entity/SignBlockEntity.java
@@ -202,16 +202,31 @@ public class SignBlockEntity extends BlockEntity implements CommandSource { // C
return this.setText((SignText) textChanger.apply(signtext), front);
}
+ // Purpur start
+ private Component translateColors(org.bukkit.entity.Player player, String line, Style style) {
+ if (level.purpurConfig.signAllowColors) {
+ if (player.hasPermission("purpur.sign.color")) line = line.replaceAll("(?i)&([0-9a-fr])", "\u00a7$1");
+ if (player.hasPermission("purpur.sign.style")) line = line.replaceAll("(?i)&([l-or])", "\u00a7$1");
+ if (player.hasPermission("purpur.sign.magic")) line = line.replaceAll("(?i)&([kr])", "\u00a7$1");
+
+ return io.papermc.paper.adventure.PaperAdventure.asVanilla(net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(line));
+ } else {
+ return Component.literal(line).setStyle(style);
+ }
+ }
+ // Purpur end
+
private SignText setMessages(net.minecraft.world.entity.player.Player entityhuman, List<FilteredText> list, SignText signtext, boolean front) { // CraftBukkit
SignText originalText = signtext; // CraftBukkit
for (int i = 0; i < list.size(); ++i) {
FilteredText filteredtext = (FilteredText) list.get(i);
Style chatmodifier = signtext.getMessage(i, entityhuman.isTextFilteringEnabled()).getStyle();
+ org.bukkit.entity.Player player = (org.bukkit.craftbukkit.entity.CraftPlayer) entityhuman.getBukkitEntity(); // Purpur
if (entityhuman.isTextFilteringEnabled()) {
- signtext = signtext.setMessage(i, Component.literal(net.minecraft.SharedConstants.filterText(filteredtext.filteredOrEmpty())).setStyle(chatmodifier)); // Paper - filter sign text to chat only
+ signtext = signtext.setMessage(i, translateColors(player, net.minecraft.SharedConstants.filterText(filteredtext.filteredOrEmpty()), chatmodifier)); // Paper - filter sign text to chat only // Purpur
} else {
- signtext = signtext.setMessage(i, Component.literal(net.minecraft.SharedConstants.filterText(filteredtext.raw())).setStyle(chatmodifier), Component.literal(net.minecraft.SharedConstants.filterText(filteredtext.filteredOrEmpty())).setStyle(chatmodifier)); // Paper - filter sign text to chat only
+ signtext = signtext.setMessage(i, translateColors(player, net.minecraft.SharedConstants.filterText(filteredtext.raw()), chatmodifier), translateColors(player, net.minecraft.SharedConstants.filterText(filteredtext.filteredOrEmpty()), chatmodifier)); // Paper - filter sign text to chat only // Purpur
}
}
@@ -351,6 +366,28 @@ public class SignBlockEntity extends BlockEntity implements CommandSource { // C
return ClientboundBlockEntityDataPacket.create(this);
}
+ // Purpur start
+ public ClientboundBlockEntityDataPacket getTranslatedUpdatePacket(boolean filtered, boolean front) {
+ final CompoundTag nbt = new CompoundTag();
+ this.saveAdditional(nbt);
+ final Component[] lines = front ? frontText.getMessages(filtered) : backText.getMessages(filtered);
+ final String side = front ? "front_text" : "back_text";
+ for (int i = 0; i < 4; i++) {
+ final var component = io.papermc.paper.adventure.PaperAdventure.asAdventure(lines[i]);
+ final String line = net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacyAmpersand().serialize(component);
+ final var text = net.kyori.adventure.text.Component.text(line);
+ final String json = net.kyori.adventure.text.serializer.gson.GsonComponentSerializer.gson().serialize(text);
+ if (!nbt.contains(side)) nbt.put(side, new CompoundTag());
+ final CompoundTag sideNbt = nbt.getCompound(side);
+ if (!sideNbt.contains("messages")) sideNbt.put("messages", new net.minecraft.nbt.ListTag());
+ final net.minecraft.nbt.ListTag messagesNbt = sideNbt.getList("messages", Tag.TAG_STRING);
+ messagesNbt.set(i, net.minecraft.nbt.StringTag.valueOf(json));
+ }
+ nbt.putString("PurpurEditor", "true");
+ return ClientboundBlockEntityDataPacket.create(this, entity -> nbt);
+ }
+ // Purpur end
+
@Override
public CompoundTag getUpdateTag() {
return this.saveWithoutMetadata();
diff --git a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
index 0f8384ba3bb9b6f36bb36bf833c260076b49014e..3d07df1fbe7116df6f97a2fb3931e739c38b671e 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
@@ -977,6 +977,11 @@ public class PurpurWorldConfig {
shulkerBoxAllowOversizedStacks = getBoolean("blocks.shulker_box.allow-oversized-stacks", shulkerBoxAllowOversizedStacks);
}
+ public boolean signAllowColors = false;
+ private void signSettings() {
+ signAllowColors = getBoolean("blocks.sign.allow-colors", signAllowColors);
+ }
+
public boolean slabHalfBreak = false;
private void slabSettings() {
slabHalfBreak = getBoolean("blocks.slab.break-individual-slabs-when-sneaking", slabHalfBreak);

View File

@@ -0,0 +1,182 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: William Blake Galbreath <Blake.Galbreath@GMail.com>
Date: Sun, 22 Nov 2020 20:13:27 -0600
Subject: [PATCH] Kelp, cave, weeping, and twisting vines configurable max
growth age
diff --git a/src/main/java/net/minecraft/world/level/block/CaveVinesBlock.java b/src/main/java/net/minecraft/world/level/block/CaveVinesBlock.java
index ead7b37122c76d43af2cdd17af7f0da8014efb26..1acc2dcda68ec8e462d51927f2ea985e7952a830 100644
--- a/src/main/java/net/minecraft/world/level/block/CaveVinesBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/CaveVinesBlock.java
@@ -88,4 +88,11 @@ public class CaveVinesBlock extends GrowingPlantHeadBlock implements Bonemealabl
public void performBonemeal(ServerLevel world, RandomSource random, BlockPos pos, BlockState state) {
world.setBlock(pos, state.setValue(BERRIES, Boolean.valueOf(true)), 2);
}
+
+ // Purpur start
+ @Override
+ public int getMaxGrowthAge() {
+ return org.purpurmc.purpur.PurpurConfig.caveVinesMaxGrowthAge;
+ }
+ // Purpur end
}
diff --git a/src/main/java/net/minecraft/world/level/block/GrowingPlantHeadBlock.java b/src/main/java/net/minecraft/world/level/block/GrowingPlantHeadBlock.java
index b325fdec8eb99ce57152a5c0fefa5059685276e4..c93e60b01dd46e7de6a6b5a5149a522304f28178 100644
--- a/src/main/java/net/minecraft/world/level/block/GrowingPlantHeadBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/GrowingPlantHeadBlock.java
@@ -30,12 +30,12 @@ public abstract class GrowingPlantHeadBlock extends GrowingPlantBlock implements
@Override
public BlockState getStateForPlacement(LevelAccessor world) {
- return (BlockState) this.defaultBlockState().setValue(GrowingPlantHeadBlock.AGE, world.getRandom().nextInt(25));
+ return (BlockState) this.defaultBlockState().setValue(GrowingPlantHeadBlock.AGE, world.getRandom().nextInt(getMaxGrowthAge())); // Purpur
}
@Override
public boolean isRandomlyTicking(BlockState state) {
- return (Integer) state.getValue(GrowingPlantHeadBlock.AGE) < 25;
+ return (Integer) state.getValue(GrowingPlantHeadBlock.AGE) < getMaxGrowthAge(); // Purpur
}
@Override
@@ -51,7 +51,7 @@ public abstract class GrowingPlantHeadBlock extends GrowingPlantBlock implements
} else {
modifier = world.spigotConfig.caveVinesModifier;
}
- if ((Integer) state.getValue(GrowingPlantHeadBlock.AGE) < 25 && random.nextDouble() < ((modifier / 100.0D) * this.growPerTickProbability)) { // Spigot - SPIGOT-7159: Better modifier resolution
+ if ((Integer) state.getValue(GrowingPlantHeadBlock.AGE) < getMaxGrowthAge() && random.nextDouble() < ((modifier / 100.0D) * this.growPerTickProbability)) { // Spigot - SPIGOT-7159: Better modifier resolution // Purpur
// Spigot end
BlockPos blockposition1 = pos.relative(this.growthDirection);
@@ -73,11 +73,11 @@ public abstract class GrowingPlantHeadBlock extends GrowingPlantBlock implements
}
public BlockState getMaxAgeState(BlockState state) {
- return (BlockState) state.setValue(GrowingPlantHeadBlock.AGE, 25);
+ return (BlockState) state.setValue(GrowingPlantHeadBlock.AGE, getMaxGrowthAge()); // Purpur
}
public boolean isMaxAge(BlockState state) {
- return (Integer) state.getValue(GrowingPlantHeadBlock.AGE) == 25;
+ return (Integer) state.getValue(GrowingPlantHeadBlock.AGE) >= getMaxGrowthAge(); // Purpur
}
protected BlockState updateBodyAfterConvertedFromHead(BlockState from, BlockState to) {
@@ -119,13 +119,13 @@ public abstract class GrowingPlantHeadBlock extends GrowingPlantBlock implements
@Override
public void performBonemeal(ServerLevel world, RandomSource random, BlockPos pos, BlockState state) {
BlockPos blockposition1 = pos.relative(this.growthDirection);
- int i = Math.min((Integer) state.getValue(GrowingPlantHeadBlock.AGE) + 1, 25);
+ int i = Math.min((Integer) state.getValue(GrowingPlantHeadBlock.AGE) + 1, getMaxGrowthAge()); // Purpur
int j = this.getBlocksToGrowWhenBonemealed(random);
for (int k = 0; k < j && this.canGrowInto(world.getBlockState(blockposition1)); ++k) {
world.setBlockAndUpdate(blockposition1, (BlockState) state.setValue(GrowingPlantHeadBlock.AGE, i));
blockposition1 = blockposition1.relative(this.growthDirection);
- i = Math.min(i + 1, 25);
+ i = Math.min(i + 1, getMaxGrowthAge()); // Purpur
}
}
@@ -138,4 +138,6 @@ public abstract class GrowingPlantHeadBlock extends GrowingPlantBlock implements
protected GrowingPlantHeadBlock getHeadBlock() {
return this;
}
+
+ public abstract int getMaxGrowthAge(); // Purpur
}
diff --git a/src/main/java/net/minecraft/world/level/block/KelpBlock.java b/src/main/java/net/minecraft/world/level/block/KelpBlock.java
index ff30a93f4160e8e22b40c7a7033c14fa15839160..bf043e1b9f0ec5876a2fa2d0597ec3c60b32b2c0 100644
--- a/src/main/java/net/minecraft/world/level/block/KelpBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/KelpBlock.java
@@ -65,4 +65,11 @@ public class KelpBlock extends GrowingPlantHeadBlock implements LiquidBlockConta
public FluidState getFluidState(BlockState state) {
return Fluids.WATER.getSource(false);
}
+
+ // Purpur start
+ @Override
+ public int getMaxGrowthAge() {
+ return org.purpurmc.purpur.PurpurConfig.kelpMaxGrowthAge;
+ }
+ // Purpur end
}
diff --git a/src/main/java/net/minecraft/world/level/block/TwistingVinesBlock.java b/src/main/java/net/minecraft/world/level/block/TwistingVinesBlock.java
index 6866605c7ef5361b21130a19a59c3fa3660dfb19..dee5d76d29da13f8639ab5d392cd0143201e71ba 100644
--- a/src/main/java/net/minecraft/world/level/block/TwistingVinesBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/TwistingVinesBlock.java
@@ -27,4 +27,11 @@ public class TwistingVinesBlock extends GrowingPlantHeadBlock {
protected boolean canGrowInto(BlockState state) {
return NetherVines.isValidGrowthState(state);
}
+
+ // Purpur start
+ @Override
+ public int getMaxGrowthAge() {
+ return org.purpurmc.purpur.PurpurConfig.twistingVinesMaxGrowthAge;
+ }
+ // Purpur end
}
diff --git a/src/main/java/net/minecraft/world/level/block/WeepingVinesBlock.java b/src/main/java/net/minecraft/world/level/block/WeepingVinesBlock.java
index e5c135ec059746b75fe58516809584221285cdbe..713c7e6e31a3e1097b612c77a4fce147c9252e0b 100644
--- a/src/main/java/net/minecraft/world/level/block/WeepingVinesBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/WeepingVinesBlock.java
@@ -27,4 +27,11 @@ public class WeepingVinesBlock extends GrowingPlantHeadBlock {
protected boolean canGrowInto(BlockState state) {
return NetherVines.isValidGrowthState(state);
}
+
+ // Purpur start
+ @Override
+ public int getMaxGrowthAge() {
+ return org.purpurmc.purpur.PurpurConfig.weepingVinesMaxGrowthAge;
+ }
+ // Purpur end
}
diff --git a/src/main/java/org/purpurmc/purpur/PurpurConfig.java b/src/main/java/org/purpurmc/purpur/PurpurConfig.java
index f6cd1c56dcc3f7d118edc6d7a63e42da166ebd5f..f562729f543ef2b5998c6c38c0a08b3ae4dab1bf 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurConfig.java
@@ -312,6 +312,10 @@ public class PurpurConfig {
public static Set<Enchantment> grindstoneIgnoredEnchants = new HashSet<>();
public static boolean grindstoneRemoveAttributes = false;
public static boolean grindstoneRemoveDisplay = false;
+ public static int caveVinesMaxGrowthAge = 25;
+ public static int kelpMaxGrowthAge = 25;
+ public static int twistingVinesMaxGrowthAge = 25;
+ public static int weepingVinesMaxGrowthAge = 25;
private static void blockSettings() {
if (version < 3) {
boolean oldValue = getBoolean("settings.barrel.packed-barrels", true);
@@ -359,6 +363,30 @@ public class PurpurConfig {
});
grindstoneRemoveAttributes = getBoolean("settings.blocks.grindstone.remove-attributes", grindstoneRemoveAttributes);
grindstoneRemoveDisplay = getBoolean("settings.blocks.grindstone.remove-name-and-lore", grindstoneRemoveDisplay);
+ caveVinesMaxGrowthAge = getInt("settings.blocks.cave_vines.max-growth-age", caveVinesMaxGrowthAge);
+ if (caveVinesMaxGrowthAge > 25) {
+ caveVinesMaxGrowthAge = 25;
+ log(Level.WARNING, "blocks.cave_vines.max-growth-age is set to above maximum allowed value of 25");
+ log(Level.WARNING, "Using value of 25 to prevent issues");
+ }
+ kelpMaxGrowthAge = getInt("settings.blocks.kelp.max-growth-age", kelpMaxGrowthAge);
+ if (kelpMaxGrowthAge > 25) {
+ kelpMaxGrowthAge = 25;
+ log(Level.WARNING, "blocks.kelp.max-growth-age is set to above maximum allowed value of 25");
+ log(Level.WARNING, "Using value of 25 to prevent issues");
+ }
+ twistingVinesMaxGrowthAge = getInt("settings.blocks.twisting_vines.max-growth-age", twistingVinesMaxGrowthAge);
+ if (twistingVinesMaxGrowthAge > 25) {
+ twistingVinesMaxGrowthAge = 25;
+ log(Level.WARNING, "blocks.twisting_vines.max-growth-age is set to above maximum allowed value of 25");
+ log(Level.WARNING, "Using value of 25 to prevent issues");
+ }
+ weepingVinesMaxGrowthAge = getInt("settings.blocks.weeping_vines.max-growth-age", weepingVinesMaxGrowthAge);
+ if (weepingVinesMaxGrowthAge > 25) {
+ weepingVinesMaxGrowthAge = 25;
+ 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");
+ }
}
public static boolean allowInfinityMending = false;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,302 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Racci <tangentmoons@gmail.com>
Date: Sat, 4 Dec 2021 00:07:05 +1100
Subject: [PATCH] Potion NamespacedKey
diff --git a/src/main/java/net/minecraft/world/effect/MobEffectInstance.java b/src/main/java/net/minecraft/world/effect/MobEffectInstance.java
index 68e1b8271475996020af50b3b2cf04cd25aa6c85..4f2fcbcf90d6f5ee89e35c993a65cae6c5b7ed91 100644
--- a/src/main/java/net/minecraft/world/effect/MobEffectInstance.java
+++ b/src/main/java/net/minecraft/world/effect/MobEffectInstance.java
@@ -16,6 +16,7 @@ import net.minecraft.util.ExtraCodecs;
import net.minecraft.util.Mth;
import net.minecraft.world.entity.LivingEntity;
import org.slf4j.Logger;
+import org.bukkit.NamespacedKey;
public class MobEffectInstance implements Comparable<MobEffectInstance> {
private static final Logger LOGGER = LogUtils.getLogger();
@@ -35,6 +36,7 @@ public class MobEffectInstance implements Comparable<MobEffectInstance> {
private boolean visible;
private boolean showIcon;
@Nullable
+ private NamespacedKey key; // Purpur - add key
private MobEffectInstance hiddenEffect;
private final Optional<MobEffectInstance.FactorData> factorData;
@@ -54,17 +56,36 @@ public class MobEffectInstance implements Comparable<MobEffectInstance> {
this(type, duration, amplifier, ambient, visible, visible);
}
+ // Purpur start
+ public MobEffectInstance(MobEffect type, int duration, int amplifier, boolean ambient, boolean visible, @Nullable NamespacedKey key) {
+ this(type, duration, amplifier, ambient, visible, visible, key);
+ }
+ // Purpur end
+
public MobEffectInstance(MobEffect type, int duration, int amplifier, boolean ambient, boolean showParticles, boolean showIcon) {
- this(type, duration, amplifier, ambient, showParticles, showIcon, (MobEffectInstance)null, type.createFactorData());
+ // Purpur start
+ this(type, duration, amplifier, ambient, showParticles, showIcon, (MobEffectInstance)null, type.createFactorData(), (NamespacedKey)null);
+ }
+
+ public MobEffectInstance(MobEffect type, int duration, int amplifier, boolean ambient, boolean showParticles, boolean showIcon, @Nullable NamespacedKey key) {
+ this(type, duration, amplifier, ambient, showParticles, showIcon, (MobEffectInstance)null, type.createFactorData(), key);
+ // Purpur end
}
public MobEffectInstance(MobEffect type, int duration, int amplifier, boolean ambient, boolean showParticles, boolean showIcon, @Nullable MobEffectInstance hiddenEffect, Optional<MobEffectInstance.FactorData> factorCalculationData) {
+ // Purpur start
+ this(type, duration, amplifier, ambient, showParticles, showIcon, hiddenEffect, factorCalculationData, (NamespacedKey) null);
+ }
+
+ public MobEffectInstance(MobEffect type, int duration, int amplifier, boolean ambient, boolean showParticles, boolean showIcon, @Nullable MobEffectInstance hiddenEffect, Optional<MobEffectInstance.FactorData> factorCalculationData, @Nullable NamespacedKey key) {
+ // Purpur end
this.effect = type;
this.duration = duration;
this.amplifier = amplifier;
this.ambient = ambient;
this.visible = showParticles;
this.showIcon = showIcon;
+ this.key = key; // Purpur - add key
this.hiddenEffect = hiddenEffect;
this.factorData = factorCalculationData;
}
@@ -85,6 +106,7 @@ public class MobEffectInstance implements Comparable<MobEffectInstance> {
this.ambient = that.ambient;
this.visible = that.visible;
this.showIcon = that.showIcon;
+ this.key = that.key; // Purpur - add key
}
public boolean update(MobEffectInstance that) {
@@ -129,6 +151,13 @@ public class MobEffectInstance implements Comparable<MobEffectInstance> {
bl = true;
}
+ // Purpur start
+ if (that.key != this.key) {
+ this.key = that.key;
+ bl = true;
+ }
+ // Purpur end
+
return bl;
}
@@ -172,6 +201,17 @@ public class MobEffectInstance implements Comparable<MobEffectInstance> {
return this.showIcon;
}
+ // Purpur start
+ public boolean hasKey() {
+ return this.key != null;
+ }
+
+ @Nullable
+ public NamespacedKey getKey() {
+ return this.key;
+ }
+ // Purpur end
+
public boolean tick(LivingEntity entity, Runnable overwriteCallback) {
if (this.hasRemainingDuration()) {
int i = this.isInfiniteDuration() ? entity.tickCount : this.duration;
@@ -232,6 +272,12 @@ public class MobEffectInstance implements Comparable<MobEffectInstance> {
string = string + ", Show Icon: false";
}
+ // Purpur start
+ if (this.hasKey()) {
+ string = string + ", Key: " + this.key;
+ }
+ // Purpur end
+
return string;
}
@@ -247,7 +293,7 @@ public class MobEffectInstance implements Comparable<MobEffectInstance> {
return false;
} else {
MobEffectInstance mobEffectInstance = (MobEffectInstance)object;
- return this.duration == mobEffectInstance.duration && this.amplifier == mobEffectInstance.amplifier && this.ambient == mobEffectInstance.ambient && this.effect.equals(mobEffectInstance.effect);
+ return this.duration == mobEffectInstance.duration && this.amplifier == mobEffectInstance.amplifier && this.ambient == mobEffectInstance.ambient && this.effect.equals(mobEffectInstance.effect) && this.key == mobEffectInstance.key; // Purpur - add key
}
}
@@ -272,6 +318,11 @@ public class MobEffectInstance implements Comparable<MobEffectInstance> {
nbt.putBoolean("ambient", this.isAmbient());
nbt.putBoolean("show_particles", this.isVisible());
nbt.putBoolean("show_icon", this.showIcon());
+ // Purpur start
+ if (this.key != null) {
+ nbt.putString("key", this.key.toString());
+ }
+ // Purpur end
if (this.hiddenEffect != null) {
CompoundTag compoundTag = new CompoundTag();
this.hiddenEffect.save(compoundTag);
@@ -306,6 +357,13 @@ public class MobEffectInstance implements Comparable<MobEffectInstance> {
bl3 = nbt.getBoolean("show_icon");
}
+ // Purpur start
+ NamespacedKey key = null;
+ if (nbt.contains("key")) {
+ key = NamespacedKey.fromString(nbt.getString("key"));
+ }
+ // Purpur end
+
MobEffectInstance mobEffectInstance = null;
if (nbt.contains("hidden_effect", 10)) {
mobEffectInstance = loadSpecifiedEffect(type, nbt.getCompound("hidden_effect"));
@@ -318,7 +376,7 @@ public class MobEffectInstance implements Comparable<MobEffectInstance> {
optional = Optional.empty();
}
- return new MobEffectInstance(type, j, Math.max(i, 0), bl, bl2, bl3, mobEffectInstance, optional);
+ return new MobEffectInstance(type, j, Math.max(i, 0), bl, bl2, bl3, mobEffectInstance, optional, key); // Purpur - add key
}
@Override
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
index a6934034c9fc8e3f04365d7595fccbe68fc093b6..5ca34447926510f1d4c5c5ba9eb3c7c6369a85de 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
@@ -465,7 +465,7 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity {
@Override
public boolean addPotionEffect(PotionEffect effect, boolean force) {
org.spigotmc.AsyncCatcher.catchOp("effect add"); // Paper
- this.getHandle().addEffect(new MobEffectInstance(CraftPotionEffectType.bukkitToMinecraft(effect.getType()), effect.getDuration(), effect.getAmplifier(), effect.isAmbient(), effect.hasParticles(), effect.hasIcon()), EntityPotionEffectEvent.Cause.PLUGIN); // Paper - Don't ignore icon
+ this.getHandle().addEffect(new MobEffectInstance(CraftPotionEffectType.bukkitToMinecraft(effect.getType()), effect.getDuration(), effect.getAmplifier(), effect.isAmbient(), effect.hasParticles(), effect.hasIcon(), effect.getKey()), EntityPotionEffectEvent.Cause.PLUGIN); // Purpur - add key // Paper - Don't ignore icon
return true;
}
@@ -486,7 +486,7 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity {
@Override
public PotionEffect getPotionEffect(PotionEffectType type) {
MobEffectInstance handle = this.getHandle().getEffect(CraftPotionEffectType.bukkitToMinecraft(type));
- return (handle == null) ? null : new PotionEffect(CraftPotionEffectType.minecraftToBukkit(handle.getEffect()), handle.getDuration(), handle.getAmplifier(), handle.isAmbient(), handle.isVisible());
+ return (handle == null) ? null : new PotionEffect(CraftPotionEffectType.minecraftToBukkit(handle.getEffect()), handle.getDuration(), handle.getAmplifier(), handle.isAmbient(), handle.isVisible(), handle.getKey()); // Purpur - add key
}
@Override
@@ -498,7 +498,7 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity {
public Collection<PotionEffect> getActivePotionEffects() {
List<PotionEffect> effects = new ArrayList<PotionEffect>();
for (MobEffectInstance handle : this.getHandle().activeEffects.values()) {
- effects.add(new PotionEffect(CraftPotionEffectType.minecraftToBukkit(handle.getEffect()), handle.getDuration(), handle.getAmplifier(), handle.isAmbient(), handle.isVisible()));
+ effects.add(new PotionEffect(CraftPotionEffectType.minecraftToBukkit(handle.getEffect()), handle.getDuration(), handle.getAmplifier(), handle.isAmbient(), handle.isVisible()), handle.getKey()); // Purpur - add key
}
return effects;
}
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaPotion.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaPotion.java
index 5a71efd27180004ee91495d9255867dbdfa1783e..1dcc3405393d11836a21aa16e435be64c04f6e7d 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaPotion.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaPotion.java
@@ -43,6 +43,7 @@ class CraftMetaPotion extends CraftMetaItem implements PotionMeta {
static final ItemMetaKey POTION_COLOR = new ItemMetaKey("CustomPotionColor", "custom-color");
static final ItemMetaKey ID = new ItemMetaKey("id", "potion-id");
static final ItemMetaKey DEFAULT_POTION = new ItemMetaKey("Potion", "potion-type");
+ static final ItemMetaKey KEY = new ItemMetaKey("key", "namespacedkey"); // Purpur - add key
// Having an initial "state" in ItemMeta seems bit dirty but the UNCRAFTABLE potion type
// is treated as the empty form of the meta because it represents an empty potion with no effect
@@ -92,7 +93,13 @@ class CraftMetaPotion extends CraftMetaItem implements PotionMeta {
boolean ambient = effect.getBoolean(AMBIENT.NBT);
boolean particles = effect.contains(SHOW_PARTICLES.NBT, CraftMagicNumbers.NBT.TAG_BYTE) ? effect.getBoolean(SHOW_PARTICLES.NBT) : true;
boolean icon = effect.contains(SHOW_ICON.NBT, CraftMagicNumbers.NBT.TAG_BYTE) ? effect.getBoolean(SHOW_ICON.NBT) : particles;
- this.customEffects.add(new PotionEffect(type, duration, amp, ambient, particles, icon));
+ // Purpur start
+ NamespacedKey key = null;
+ if (tag.contains(KEY.NBT)) {
+ key = NamespacedKey.fromString(effect.getString(KEY.NBT));
+ }
+ this.customEffects.add(new PotionEffect(type, duration, amp, ambient, particles, icon, key));
+ // Purpur end
}
}
}
@@ -139,6 +146,11 @@ class CraftMetaPotion extends CraftMetaItem implements PotionMeta {
effectData.putBoolean(AMBIENT.NBT, effect.isAmbient());
effectData.putBoolean(SHOW_PARTICLES.NBT, effect.hasParticles());
effectData.putBoolean(SHOW_ICON.NBT, effect.hasIcon());
+ // Purpur start
+ if (effect.hasKey()) {
+ effectData.putString(KEY.NBT, effect.getKey().toString());
+ }
+ // Purpur end
effectList.add(effectData);
}
}
@@ -200,7 +212,7 @@ class CraftMetaPotion extends CraftMetaItem implements PotionMeta {
if (index != -1) {
if (overwrite) {
PotionEffect old = this.customEffects.get(index);
- if (old.getAmplifier() == effect.getAmplifier() && old.getDuration() == effect.getDuration() && old.isAmbient() == effect.isAmbient()) {
+ if (old.getAmplifier() == effect.getAmplifier() && old.getDuration() == effect.getDuration() && old.isAmbient() == effect.isAmbient() && old.getKey() == effect.getKey()) { // Purpur - add key
return false;
}
this.customEffects.set(index, effect);
diff --git a/src/main/java/org/bukkit/craftbukkit/potion/CraftPotionUtil.java b/src/main/java/org/bukkit/craftbukkit/potion/CraftPotionUtil.java
index 354393cbf0f113f14e936b40da56125a3130cbd9..a1ef7ecdf272546bdd76bb4b2ecd86a69c51c777 100644
--- a/src/main/java/org/bukkit/craftbukkit/potion/CraftPotionUtil.java
+++ b/src/main/java/org/bukkit/craftbukkit/potion/CraftPotionUtil.java
@@ -101,7 +101,7 @@ public class CraftPotionUtil {
public static MobEffectInstance fromBukkit(PotionEffect effect) {
MobEffect type = CraftPotionEffectType.bukkitToMinecraft(effect.getType());
- return new MobEffectInstance(type, effect.getDuration(), effect.getAmplifier(), effect.isAmbient(), effect.hasParticles());
+ return new MobEffectInstance(type, effect.getDuration(), effect.getAmplifier(), effect.isAmbient(), effect.hasParticles(), effect.getKey()); // Purpur - add key
}
public static PotionEffect toBukkit(MobEffectInstance effect) {
@@ -110,7 +110,7 @@ public class CraftPotionUtil {
int duration = effect.getDuration();
boolean ambient = effect.isAmbient();
boolean particles = effect.isVisible();
- return new PotionEffect(type, duration, amp, ambient, particles);
+ return new PotionEffect(type, duration, amp, ambient, particles, effect.getKey()); // Purpur - add key
}
public static boolean equals(MobEffect mobEffect, PotionEffectType type) {
diff --git a/src/test/java/org/bukkit/potion/PotionTest.java b/src/test/java/org/bukkit/potion/PotionTest.java
index 9457c66bd81f202e009c94f732c8e8e7f2ab9957..863f140260657f224fa3a2eb0bc6f929f74f5c0d 100644
--- a/src/test/java/org/bukkit/potion/PotionTest.java
+++ b/src/test/java/org/bukkit/potion/PotionTest.java
@@ -9,6 +9,7 @@ import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.effect.MobEffect;
import net.minecraft.world.effect.MobEffectInstance;
import net.minecraft.world.item.alchemy.Potion;
+import org.bukkit.NamespacedKey;
import org.bukkit.craftbukkit.potion.CraftPotionEffectType;
import org.bukkit.support.AbstractTestingBase;
import org.junit.Test;
@@ -46,4 +47,27 @@ public class PotionTest extends AbstractTestingBase {
assertEquals("Same type not returned by name " + key, bukkit, byName);
}
}
+
+ // Purpur start
+ @Test
+ public void testNamespacedKey() {
+ NamespacedKey key = new NamespacedKey("testnamespace", "testkey");
+ PotionEffect namedSpacedEffect = new PotionEffect(PotionEffectType.DOLPHINS_GRACE, 20, 0, true, true, true, key);
+ assertNotNull(namedSpacedEffect.getKey());
+ assertTrue(namedSpacedEffect.hasKey());
+ assertFalse(namedSpacedEffect.withKey(null).hasKey());
+
+ PotionEffect effect = new PotionEffect(PotionEffectType.DOLPHINS_GRACE, 20, 0, true, true, true);
+ assertNull(effect.getKey());
+ assertFalse(effect.hasKey());
+ assertTrue(namedSpacedEffect.withKey(key).hasKey());
+
+ Map<String, Object> s1 = namedSpacedEffect.serialize();
+ Map<String, Object> s2 = effect.serialize();
+ assertTrue(s1.containsKey("namespacedKey"));
+ assertFalse(s2.containsKey("namespacedKey"));
+ assertNotNull(new PotionEffect(s1).getKey());
+ assertNull(new PotionEffect(s2).getKey());
+ }
+ // Purpur end
}

View File

@@ -0,0 +1,33 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: BillyGalbreath <blake.galbreath@gmail.com>
Date: Mon, 27 Dec 2021 08:11:00 -0600
Subject: [PATCH] Grindstone API
diff --git a/src/main/java/net/minecraft/world/inventory/GrindstoneMenu.java b/src/main/java/net/minecraft/world/inventory/GrindstoneMenu.java
index 132a07e226ae3ac6b5abc6f53c62345e2ab2f31f..3b721092a7a73472756064e0eb91d3220fdc4bc8 100644
--- a/src/main/java/net/minecraft/world/inventory/GrindstoneMenu.java
+++ b/src/main/java/net/minecraft/world/inventory/GrindstoneMenu.java
@@ -95,9 +95,11 @@ public class GrindstoneMenu extends AbstractContainerMenu {
@Override
public void onTake(net.minecraft.world.entity.player.Player player, ItemStack stack) {
+ ItemStack itemstack = activeQuickItem == null ? stack : activeQuickItem; // Purpur
context.execute((world, blockposition) -> {
+ org.purpurmc.purpur.event.inventory.GrindstoneTakeResultEvent grindstoneTakeResultEvent = new org.purpurmc.purpur.event.inventory.GrindstoneTakeResultEvent(player.getBukkitEntity(), getBukkitView(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack), this.getExperienceAmount(world)); grindstoneTakeResultEvent.callEvent(); // Purpur
if (world instanceof ServerLevel) {
- ExperienceOrb.award((ServerLevel) world, Vec3.atCenterOf(blockposition), this.getExperienceAmount(world), org.bukkit.entity.ExperienceOrb.SpawnReason.GRINDSTONE, player); // Paper
+ ExperienceOrb.award((ServerLevel) world, Vec3.atCenterOf(blockposition), grindstoneTakeResultEvent.getExperienceAmount(), org.bukkit.entity.ExperienceOrb.SpawnReason.GRINDSTONE, player); // Paper // Purpur
}
world.levelEvent(1042, blockposition, 0);
@@ -341,7 +343,9 @@ public class GrindstoneMenu extends AbstractContainerMenu {
return ItemStack.EMPTY;
}
+ this.activeQuickItem = itemstack; // Purpur
slot1.onTake(player, itemstack1);
+ this.activeQuickItem = null; // Purpur
}
return itemstack;

View File

@@ -0,0 +1,97 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: BillyGalbreath <blake.galbreath@gmail.com>
Date: Tue, 28 Dec 2021 16:22:20 -0600
Subject: [PATCH] Ability for hoe to replant crops and nether warts
diff --git a/src/main/java/net/minecraft/world/level/block/BushBlock.java b/src/main/java/net/minecraft/world/level/block/BushBlock.java
index 03fde6e47c4a347c62fe9b4a3351769aedf874f6..ca906b0250e5332f7ececf1419ca6d2c1d385adc 100644
--- a/src/main/java/net/minecraft/world/level/block/BushBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/BushBlock.java
@@ -48,4 +48,24 @@ public class BushBlock extends Block {
public boolean isPathfindable(BlockState state, BlockGetter world, BlockPos pos, PathComputationType type) {
return type == PathComputationType.AIR && !this.hasCollision ? true : super.isPathfindable(state, world, pos, type);
}
+
+ // Purpur start
+ public void playerDestroyAndReplant(net.minecraft.world.level.Level world, net.minecraft.world.entity.player.Player player, BlockPos pos, BlockState state, @javax.annotation.Nullable net.minecraft.world.level.block.entity.BlockEntity blockEntity, net.minecraft.world.item.ItemStack itemInHand, net.minecraft.world.level.ItemLike itemToReplant) {
+ player.awardStat(net.minecraft.stats.Stats.BLOCK_MINED.get(this));
+ player.causeFoodExhaustion(0.005F, org.bukkit.event.entity.EntityExhaustionEvent.ExhaustionReason.BLOCK_MINED);
+ java.util.List<net.minecraft.world.item.ItemStack> dropList = Block.getDrops(state, (net.minecraft.server.level.ServerLevel) world, pos, blockEntity, player, itemInHand);
+
+ boolean planted = false;
+ for (net.minecraft.world.item.ItemStack itemToDrop : dropList) {
+ if (!planted && itemToDrop.getItem() == itemToReplant) {
+ world.setBlock(pos, defaultBlockState(), 3);
+ itemToDrop.setCount(itemToDrop.getCount() - 1);
+ planted = true;
+ }
+ Block.popResource(world, pos, itemToDrop);
+ }
+
+ state.spawnAfterBreak((net.minecraft.server.level.ServerLevel) world, pos, itemInHand, true);
+ }
+ // Purpur end
}
diff --git a/src/main/java/net/minecraft/world/level/block/CropBlock.java b/src/main/java/net/minecraft/world/level/block/CropBlock.java
index 3f429f083f45d34effc273ccaa5db4da089f7355..61d051f42d8c3d1f039b97fdc7a61b54f57ee86a 100644
--- a/src/main/java/net/minecraft/world/level/block/CropBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/CropBlock.java
@@ -207,4 +207,15 @@ public class CropBlock extends BushBlock implements BonemealableBlock {
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
builder.add(CropBlock.AGE);
}
+
+ // Purpur start
+ @Override
+ public void playerDestroy(Level world, net.minecraft.world.entity.player.Player player, BlockPos pos, BlockState state, @javax.annotation.Nullable net.minecraft.world.level.block.entity.BlockEntity blockEntity, ItemStack itemInHand, boolean includeDrops) {
+ if (world.purpurConfig.hoeReplantsCrops && itemInHand.getItem() instanceof net.minecraft.world.item.HoeItem) {
+ super.playerDestroyAndReplant(world, player, pos, state, blockEntity, itemInHand, getBaseSeedId());
+ } else {
+ super.playerDestroy(world, player, pos, state, blockEntity, itemInHand, includeDrops);
+ }
+ }
+ // 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 e55720c4d2fbdf6aae526910e87a67c29cf906fd..74fedd3e401c6d58c03c0579f4b919114404fd78 100644
--- a/src/main/java/net/minecraft/world/level/block/NetherWartBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/NetherWartBlock.java
@@ -60,4 +60,15 @@ public class NetherWartBlock extends BushBlock {
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
builder.add(NetherWartBlock.AGE);
}
+
+ // Purpur start
+ @Override
+ public void playerDestroy(net.minecraft.world.level.Level world, net.minecraft.world.entity.player.Player player, BlockPos pos, BlockState state, @javax.annotation.Nullable net.minecraft.world.level.block.entity.BlockEntity blockEntity, ItemStack itemInHand, boolean includeDrops) {
+ if (world.purpurConfig.hoeReplantsNetherWarts && itemInHand.getItem() instanceof net.minecraft.world.item.HoeItem) {
+ super.playerDestroyAndReplant(world, player, pos, state, blockEntity, itemInHand, Items.NETHER_WART);
+ } else {
+ super.playerDestroy(world, player, pos, state, blockEntity, itemInHand, includeDrops);
+ }
+ }
+ // Purpur end
}
diff --git a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
index 41b856485bbb6872cc49cfdc460303e465c3143e..bda73dd90c7d5e72996efca0a41e7f4785c6f548 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
@@ -543,6 +543,8 @@ public class PurpurWorldConfig {
public Map<Block, Weatherable> axeWeatherables = new HashMap<>();
public Map<Block, Tillable> hoeTillables = new HashMap<>();
public Map<Block, Flattenable> shovelFlattenables = new HashMap<>();
+ public boolean hoeReplantsCrops = false;
+ public boolean hoeReplantsNetherWarts = false;
private void toolSettings() {
axeStrippables.clear();
axeWaxables.clear();
@@ -736,6 +738,8 @@ public class PurpurWorldConfig {
});
shovelFlattenables.put(block, new Flattenable(into, drops));
});
+ hoeReplantsCrops = getBoolean("tools.hoe.replant-crops", hoeReplantsCrops);
+ hoeReplantsNetherWarts = getBoolean("tools.hoe.replant-nether-warts", hoeReplantsNetherWarts);
}
public boolean anvilAllowColors = false;

View File

@@ -0,0 +1,39 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: BillyGalbreath <blake.galbreath@gmail.com>
Date: Fri, 31 Dec 2021 06:03:12 -0600
Subject: [PATCH] Shearing jeb produces random color wool
diff --git a/src/main/java/net/minecraft/world/entity/animal/Sheep.java b/src/main/java/net/minecraft/world/entity/animal/Sheep.java
index f2d0c67709e38209a8a02e98f4392b9e0a53c211..fb477c3c594bb81e92ae0c606635c309840d0dc5 100644
--- a/src/main/java/net/minecraft/world/entity/animal/Sheep.java
+++ b/src/main/java/net/minecraft/world/entity/animal/Sheep.java
@@ -317,7 +317,7 @@ public class Sheep extends Animal implements Shearable {
for (int j = 0; j < i; ++j) {
this.forceDrops = true; // CraftBukkit
- ItemEntity entityitem = this.spawnAtLocation((ItemLike) Sheep.ITEM_BY_DYE.get(this.getColor()), 1);
+ ItemEntity entityitem = this.spawnAtLocation((ItemLike) Sheep.ITEM_BY_DYE.get(this.level().purpurConfig.sheepShearJebRandomColor && hasCustomName() && getCustomName().getString().equals("jeb_") ? DyeColor.random(this.level().random) : this.getColor()), 1); // Purpur
this.forceDrops = false; // CraftBukkit
if (entityitem != null) {
diff --git a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
index bda73dd90c7d5e72996efca0a41e7f4785c6f548..fad281ec8314d4431126abbcea997932401ea95e 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
@@ -2303,6 +2303,7 @@ public class PurpurWorldConfig {
public boolean sheepBypassMobGriefing = false;
public boolean sheepTakeDamageFromWater = false;
public boolean sheepAlwaysDropExp = false;
+ public boolean sheepShearJebRandomColor = false;
private void sheepSettings() {
sheepRidable = getBoolean("mobs.sheep.ridable", sheepRidable);
sheepRidableInWater = getBoolean("mobs.sheep.ridable-in-water", sheepRidableInWater);
@@ -2317,6 +2318,7 @@ public class PurpurWorldConfig {
sheepBypassMobGriefing = getBoolean("mobs.sheep.bypass-mob-griefing", sheepBypassMobGriefing);
sheepTakeDamageFromWater = getBoolean("mobs.sheep.takes-damage-from-water", sheepTakeDamageFromWater);
sheepAlwaysDropExp = getBoolean("mobs.sheep.always-drop-exp", sheepAlwaysDropExp);
+ sheepShearJebRandomColor = getBoolean("mobs.sheep.jeb-shear-random-color", sheepShearJebRandomColor);
}
public boolean shulkerRidable = false;

View File

@@ -0,0 +1,37 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: BillyGalbreath <blake.galbreath@gmail.com>
Date: Fri, 31 Dec 2021 06:18:54 -0600
Subject: [PATCH] Turtle eggs random tick crack chance
diff --git a/src/main/java/net/minecraft/world/level/block/TurtleEggBlock.java b/src/main/java/net/minecraft/world/level/block/TurtleEggBlock.java
index 9c834e3deed07eb70e6a57df2db732c1e2334737..8e975daca6a50c95d7fb620f2756b8bb2b7c7d6b 100644
--- a/src/main/java/net/minecraft/world/level/block/TurtleEggBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/TurtleEggBlock.java
@@ -162,7 +162,7 @@ public class TurtleEggBlock extends Block {
private boolean shouldUpdateHatchLevel(Level world) {
float f = world.getTimeOfDay(1.0F);
- return (double) f < 0.69D && (double) f > 0.65D ? true : world.random.nextInt(500) == 0;
+ return (double) f < 0.69D && (double) f > 0.65D ? true : world.random.nextInt(world.purpurConfig.turtleEggsRandomTickCrackChance) == 0;
}
@Override
diff --git a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
index fad281ec8314d4431126abbcea997932401ea95e..c300838d83652a36389694e7afbec5feff11cd8a 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
@@ -1011,11 +1011,13 @@ public class PurpurWorldConfig {
public boolean turtleEggsBreakFromItems = true;
public boolean turtleEggsBreakFromMinecarts = true;
public boolean turtleEggsBypassMobGriefing = false;
+ public int turtleEggsRandomTickCrackChance = 500;
private void turtleEggSettings() {
turtleEggsBreakFromExpOrbs = getBoolean("blocks.turtle_egg.break-from-exp-orbs", turtleEggsBreakFromExpOrbs);
turtleEggsBreakFromItems = getBoolean("blocks.turtle_egg.break-from-items", turtleEggsBreakFromItems);
turtleEggsBreakFromMinecarts = getBoolean("blocks.turtle_egg.break-from-minecarts", turtleEggsBreakFromMinecarts);
turtleEggsBypassMobGriefing = getBoolean("blocks.turtle_egg.bypass-mob-griefing", turtleEggsBypassMobGriefing);
+ turtleEggsRandomTickCrackChance = getInt("blocks.turtle_egg.random-tick-crack-chance", turtleEggsRandomTickCrackChance);
}
public int waterInfiniteRequiredSources = 2;

View File

@@ -0,0 +1,101 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: BillyGalbreath <blake.galbreath@gmail.com>
Date: Fri, 31 Dec 2021 06:40:19 -0600
Subject: [PATCH] Mob head visibility percent
diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java
index 7c91aa226517d9d574f102e3e4976904b419e657..11761085514d54e23fece41a408b74a2bde3effc 100644
--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java
+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java
@@ -1041,9 +1041,20 @@ public abstract class LivingEntity extends Entity implements Attackable {
ItemStack itemstack = this.getItemBySlot(EquipmentSlot.HEAD);
EntityType<?> entitytypes = entity.getType();
- if (entitytypes == EntityType.SKELETON && itemstack.is(Items.SKELETON_SKULL) || entitytypes == EntityType.ZOMBIE && itemstack.is(Items.ZOMBIE_HEAD) || entitytypes == EntityType.PIGLIN && itemstack.is(Items.PIGLIN_HEAD) || entitytypes == EntityType.PIGLIN_BRUTE && itemstack.is(Items.PIGLIN_HEAD) || entitytypes == EntityType.CREEPER && itemstack.is(Items.CREEPER_HEAD)) {
- d0 *= 0.5D;
+ // Purpur start
+ if (entitytypes == EntityType.SKELETON && itemstack.is(Items.SKELETON_SKULL)) {
+ d0 *= entity.level().purpurConfig.skeletonHeadVisibilityPercent;
+ }
+ else if (entitytypes == EntityType.ZOMBIE && itemstack.is(Items.ZOMBIE_HEAD)) {
+ d0 *= entity.level().purpurConfig.zombieHeadVisibilityPercent;
+ }
+ else if (entitytypes == EntityType.CREEPER && itemstack.is(Items.CREEPER_HEAD)) {
+ d0 *= entity.level().purpurConfig.creeperHeadVisibilityPercent;
}
+ else if ((entitytypes == EntityType.PIGLIN || entitytypes == EntityType.PIGLIN_BRUTE) && itemstack.is(Items.PIGLIN_HEAD)) {
+ d0 *= entity.level().purpurConfig.piglinHeadVisibilityPercent;
+ }
+ // Purpur end
// Purpur start
if (entity instanceof LivingEntity entityliving) {
diff --git a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
index c300838d83652a36389694e7afbec5feff11cd8a..a5f86aa5c3cd08dddb147c338a124953cacbf178 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
@@ -1305,6 +1305,7 @@ public class PurpurWorldConfig {
public boolean creeperExplodeWhenKilled = false;
public boolean creeperHealthRadius = false;
public boolean creeperAlwaysDropExp = false;
+ public double creeperHeadVisibilityPercent = 0.5D;
private void creeperSettings() {
creeperRidable = getBoolean("mobs.creeper.ridable", creeperRidable);
creeperRidableInWater = getBoolean("mobs.creeper.ridable-in-water", creeperRidableInWater);
@@ -1322,6 +1323,7 @@ public class PurpurWorldConfig {
creeperExplodeWhenKilled = getBoolean("mobs.creeper.explode-when-killed", creeperExplodeWhenKilled);
creeperHealthRadius = getBoolean("mobs.creeper.health-impacts-explosion", creeperHealthRadius);
creeperAlwaysDropExp = getBoolean("mobs.creeper.always-drop-exp", creeperAlwaysDropExp);
+ creeperHeadVisibilityPercent = getDouble("mobs.creeper.head-visibility-percent", creeperHeadVisibilityPercent);
}
public boolean dolphinRidable = false;
@@ -2108,6 +2110,7 @@ public class PurpurWorldConfig {
public boolean piglinTakeDamageFromWater = false;
public int piglinPortalSpawnModifier = 2000;
public boolean piglinAlwaysDropExp = false;
+ public double piglinHeadVisibilityPercent = 0.5D;
private void piglinSettings() {
piglinRidable = getBoolean("mobs.piglin.ridable", piglinRidable);
piglinRidableInWater = getBoolean("mobs.piglin.ridable-in-water", piglinRidableInWater);
@@ -2122,6 +2125,7 @@ public class PurpurWorldConfig {
piglinTakeDamageFromWater = getBoolean("mobs.piglin.takes-damage-from-water", piglinTakeDamageFromWater);
piglinPortalSpawnModifier = getInt("mobs.piglin.portal-spawn-modifier", piglinPortalSpawnModifier);
piglinAlwaysDropExp = getBoolean("mobs.piglin.always-drop-exp", piglinAlwaysDropExp);
+ piglinHeadVisibilityPercent = getDouble("mobs.piglin.head-visibility-percent", piglinHeadVisibilityPercent);
}
public boolean piglinBruteRidable = false;
@@ -2383,6 +2387,7 @@ public class PurpurWorldConfig {
public double skeletonMaxHealth = 20.0D;
public boolean skeletonTakeDamageFromWater = false;
public boolean skeletonAlwaysDropExp = false;
+ public double skeletonHeadVisibilityPercent = 0.5D;
private void skeletonSettings() {
skeletonRidable = getBoolean("mobs.skeleton.ridable", skeletonRidable);
skeletonRidableInWater = getBoolean("mobs.skeleton.ridable-in-water", skeletonRidableInWater);
@@ -2395,6 +2400,7 @@ public class PurpurWorldConfig {
skeletonMaxHealth = getDouble("mobs.skeleton.attributes.max_health", skeletonMaxHealth);
skeletonTakeDamageFromWater = getBoolean("mobs.skeleton.takes-damage-from-water", skeletonTakeDamageFromWater);
skeletonAlwaysDropExp = getBoolean("mobs.skeleton.always-drop-exp", skeletonAlwaysDropExp);
+ skeletonHeadVisibilityPercent = getDouble("mobs.skeleton.head-visibility-percent", skeletonHeadVisibilityPercent);
}
public boolean skeletonHorseRidableInWater = true;
@@ -2929,6 +2935,7 @@ public class PurpurWorldConfig {
public boolean zombieBypassMobGriefing = false;
public boolean zombieTakeDamageFromWater = false;
public boolean zombieAlwaysDropExp = false;
+ public double zombieHeadVisibilityPercent = 0.5D;
private void zombieSettings() {
zombieRidable = getBoolean("mobs.zombie.ridable", zombieRidable);
zombieRidableInWater = getBoolean("mobs.zombie.ridable-in-water", zombieRidableInWater);
@@ -2947,6 +2954,7 @@ public class PurpurWorldConfig {
zombieBypassMobGriefing = getBoolean("mobs.zombie.bypass-mob-griefing", zombieBypassMobGriefing);
zombieTakeDamageFromWater = getBoolean("mobs.zombie.takes-damage-from-water", zombieTakeDamageFromWater);
zombieAlwaysDropExp = getBoolean("mobs.zombie.always-drop-exp", zombieAlwaysDropExp);
+ zombieHeadVisibilityPercent = getDouble("mobs.zombie.head-visibility-percent", zombieHeadVisibilityPercent);
}
public boolean zombieHorseRidableInWater = false;

View File

@@ -0,0 +1,35 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: BillyGalbreath <blake.galbreath@gmail.com>
Date: Sat, 1 Jan 2022 18:38:58 -0600
Subject: [PATCH] Configurable valid characters for usernames
diff --git a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
index e615e417627840d645db259bc9640a0471a52b05..f0bbc48e2df1da42e4bf9f7113451738b986fbbf 100644
--- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
@@ -141,6 +141,8 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener,
return false;
}
+ if (true) return org.purpurmc.purpur.PurpurConfig.usernameValidCharactersPattern.matcher(in).matches(); // Purpur
+
for (int i = 0, len = in.length(); i < len; ++i) {
char c = in.charAt(i);
diff --git a/src/main/java/org/purpurmc/purpur/PurpurConfig.java b/src/main/java/org/purpurmc/purpur/PurpurConfig.java
index f562729f543ef2b5998c6c38c0a08b3ae4dab1bf..d56c2776d08306245618dca04cd39891bb61c1bd 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurConfig.java
@@ -452,4 +452,11 @@ public class PurpurConfig {
private static void networkSettings() {
useUPnP = getBoolean("settings.network.upnp-port-forwarding", useUPnP);
}
+
+ public static java.util.regex.Pattern usernameValidCharactersPattern;
+ private static void usernameValidationSettings() {
+ String defaultPattern = "^[a-zA-Z0-9_.]*$";
+ String setPattern = getString("settings.username-valid-characters", defaultPattern);
+ usernameValidCharactersPattern = java.util.regex.Pattern.compile(setPattern == null || setPattern.isBlank() ? defaultPattern : setPattern);
+ }
}

View File

@@ -0,0 +1,179 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: BillyGalbreath <Blake.Galbreath@Gmail.com>
Date: Mon, 3 Jan 2022 00:06:51 -0600
Subject: [PATCH] Shears can have looting enchantment
diff --git a/src/main/java/net/minecraft/core/dispenser/ShearsDispenseItemBehavior.java b/src/main/java/net/minecraft/core/dispenser/ShearsDispenseItemBehavior.java
index e17090003988ad2c890d48666c2234b14d511345..433f1f11b8b92c7d48352416f79ab5a394c33287 100644
--- a/src/main/java/net/minecraft/core/dispenser/ShearsDispenseItemBehavior.java
+++ b/src/main/java/net/minecraft/core/dispenser/ShearsDispenseItemBehavior.java
@@ -107,7 +107,7 @@ public class ShearsDispenseItemBehavior extends OptionalDispenseItemBehavior {
continue;
}
// CraftBukkit end
- ishearable.shear(SoundSource.BLOCKS);
+ ishearable.shear(SoundSource.BLOCKS, net.minecraft.world.item.enchantment.EnchantmentHelper.getItemEnchantmentLevel(net.minecraft.world.item.enchantment.Enchantments.MOB_LOOTING, CraftItemStack.asNMSCopy(craftItem))); // Purpur
worldserver.gameEvent((Entity) null, GameEvent.SHEAR, blockposition);
return true;
}
diff --git a/src/main/java/net/minecraft/world/entity/Shearable.java b/src/main/java/net/minecraft/world/entity/Shearable.java
index 5e8cc5cfac8888628c6d513148f41be09ca65a2c..a089fc61ec09be6b7490375489178dc6ba5a644b 100644
--- a/src/main/java/net/minecraft/world/entity/Shearable.java
+++ b/src/main/java/net/minecraft/world/entity/Shearable.java
@@ -3,7 +3,13 @@ package net.minecraft.world.entity;
import net.minecraft.sounds.SoundSource;
public interface Shearable {
- void shear(SoundSource shearedSoundCategory);
+ // Purpur start
+ default void shear(SoundSource shearedSoundCategory) {
+ shear(shearedSoundCategory, 0);
+ }
+
+ void shear(SoundSource shearedSoundCategory, int looting);
+ // Purpur end
boolean readyForShearing();
}
diff --git a/src/main/java/net/minecraft/world/entity/animal/MushroomCow.java b/src/main/java/net/minecraft/world/entity/animal/MushroomCow.java
index ab5b150b379598861666ad32906e1fe454437063..59ef1070c6c1ac876e097cd23835e4ed8b6e732f 100644
--- a/src/main/java/net/minecraft/world/entity/animal/MushroomCow.java
+++ b/src/main/java/net/minecraft/world/entity/animal/MushroomCow.java
@@ -163,7 +163,7 @@ public class MushroomCow extends Cow implements Shearable, VariantHolder<Mushroo
return tryRide(player, hand); // Purpur
}
// CraftBukkit end
- this.shear(SoundSource.PLAYERS);
+ this.shear(SoundSource.PLAYERS, net.minecraft.world.item.enchantment.EnchantmentHelper.getMobLooting(player)); // Purpur
this.gameEvent(GameEvent.SHEAR, player);
if (!this.level().isClientSide) {
itemstack.hurtAndBreak(1, player, (entityhuman1) -> {
@@ -203,7 +203,7 @@ public class MushroomCow extends Cow implements Shearable, VariantHolder<Mushroo
}
@Override
- public void shear(SoundSource shearedSoundCategory) {
+ public void shear(SoundSource shearedSoundCategory, int looting) { // Purpur
this.level().playSound((Player) null, (Entity) this, SoundEvents.MOOSHROOM_SHEAR, shearedSoundCategory, 1.0F, 1.0F);
if (!this.level().isClientSide()) {
Cow entitycow = (Cow) EntityType.COW.create(this.level());
@@ -239,7 +239,7 @@ public class MushroomCow extends Cow implements Shearable, VariantHolder<Mushroo
this.discard(); // CraftBukkit - from above
// CraftBukkit end
- for (int i = 0; i < 5; ++i) {
+ for (int i = 0; i < 5 + (org.purpurmc.purpur.PurpurConfig.allowShearsLooting ? looting : 0); ++i) {
// CraftBukkit start
ItemEntity entityitem = new ItemEntity(this.level(), this.getX(), this.getY(1.0D), this.getZ(), new ItemStack(this.getVariant().blockState.getBlock()));
EntityDropItemEvent event = new EntityDropItemEvent(this.getBukkitEntity(), (org.bukkit.entity.Item) entityitem.getBukkitEntity());
diff --git a/src/main/java/net/minecraft/world/entity/animal/Sheep.java b/src/main/java/net/minecraft/world/entity/animal/Sheep.java
index fb477c3c594bb81e92ae0c606635c309840d0dc5..8502fc1331c2e94992ab39e4e7ea0f36e83b06a5 100644
--- a/src/main/java/net/minecraft/world/entity/animal/Sheep.java
+++ b/src/main/java/net/minecraft/world/entity/animal/Sheep.java
@@ -295,7 +295,7 @@ public class Sheep extends Animal implements Shearable {
return InteractionResult.PASS;
}
// CraftBukkit end
- this.shear(SoundSource.PLAYERS);
+ this.shear(SoundSource.PLAYERS, net.minecraft.world.item.enchantment.EnchantmentHelper.getMobLooting(player)); // Purpur
this.gameEvent(GameEvent.SHEAR, player);
itemstack.hurtAndBreak(1, player, (entityhuman1) -> {
entityhuman1.broadcastBreakEvent(hand);
@@ -310,10 +310,11 @@ public class Sheep extends Animal implements Shearable {
}
@Override
- public void shear(SoundSource shearedSoundCategory) {
+ public void shear(SoundSource shearedSoundCategory, int looting) { // Purpur
this.level().playSound((Player) null, (Entity) this, SoundEvents.SHEEP_SHEAR, shearedSoundCategory, 1.0F, 1.0F);
this.setSheared(true);
int i = 1 + this.random.nextInt(3);
+ if (org.purpurmc.purpur.PurpurConfig.allowShearsLooting) i += looting; // Purpur
for (int j = 0; j < i; ++j) {
this.forceDrops = true; // CraftBukkit
diff --git a/src/main/java/net/minecraft/world/entity/animal/SnowGolem.java b/src/main/java/net/minecraft/world/entity/animal/SnowGolem.java
index fc8526af7e1df15794b4560b58e7f6a47508aa08..8b364fe9f3a3d47ae6daa331b8f16941ca17432a 100644
--- a/src/main/java/net/minecraft/world/entity/animal/SnowGolem.java
+++ b/src/main/java/net/minecraft/world/entity/animal/SnowGolem.java
@@ -199,7 +199,7 @@ public class SnowGolem extends AbstractGolem implements Shearable, RangedAttackM
return tryRide(player, hand); // Purpur
}
// CraftBukkit end
- this.shear(SoundSource.PLAYERS);
+ this.shear(SoundSource.PLAYERS, net.minecraft.world.item.enchantment.EnchantmentHelper.getMobLooting(player)); // Purpur
this.gameEvent(GameEvent.SHEAR, player);
if (!this.level().isClientSide) {
itemstack.hurtAndBreak(1, player, (entityhuman1) -> {
@@ -222,12 +222,13 @@ public class SnowGolem extends AbstractGolem implements Shearable, RangedAttackM
}
@Override
- public void shear(SoundSource shearedSoundCategory) {
+ public void shear(SoundSource shearedSoundCategory, int looting) { // Purpur
this.level().playSound((Player) null, (Entity) this, SoundEvents.SNOW_GOLEM_SHEAR, shearedSoundCategory, 1.0F, 1.0F);
if (!this.level().isClientSide()) {
this.setPumpkin(false);
this.forceDrops = true; // CraftBukkit
if (level().purpurConfig.snowGolemDropsPumpkin) // Purpur
+ for (int i = 0; i < 1 + (org.purpurmc.purpur.PurpurConfig.allowShearsLooting ? looting : 0); i++) // Purpur
this.spawnAtLocation(new ItemStack(Items.CARVED_PUMPKIN), 1.7F);
this.forceDrops = false; // CraftBukkit
}
diff --git a/src/main/java/net/minecraft/world/item/enchantment/EnchantmentCategory.java b/src/main/java/net/minecraft/world/item/enchantment/EnchantmentCategory.java
index 859435f747ceef860cb4e9e825a7353ea3b90798..fc2c35f57436371cb0111aedfd289ac95d506d07 100644
--- a/src/main/java/net/minecraft/world/item/enchantment/EnchantmentCategory.java
+++ b/src/main/java/net/minecraft/world/item/enchantment/EnchantmentCategory.java
@@ -128,6 +128,12 @@ public enum EnchantmentCategory {
public boolean canEnchant(Item item) {
return item instanceof BowItem || item instanceof CrossbowItem;
}
+ },
+ WEAPON_AND_SHEARS {
+ @Override
+ public boolean canEnchant(Item item) {
+ return WEAPON.canEnchant(item) || item instanceof net.minecraft.world.item.ShearsItem;
+ }
// Purpur end
};
diff --git a/src/main/java/net/minecraft/world/item/enchantment/LootBonusEnchantment.java b/src/main/java/net/minecraft/world/item/enchantment/LootBonusEnchantment.java
index 7f1ffc0ac402fcf0ec086986e959ecc9f78dde03..1351d52374d1c2367932e5ecd5f4637955fb14c9 100644
--- a/src/main/java/net/minecraft/world/item/enchantment/LootBonusEnchantment.java
+++ b/src/main/java/net/minecraft/world/item/enchantment/LootBonusEnchantment.java
@@ -7,6 +7,14 @@ public class LootBonusEnchantment extends Enchantment {
super(rarity, target, slotTypes);
}
+ // Purpur start
+ @Override
+ public boolean canEnchant(net.minecraft.world.item.ItemStack stack) {
+ // we have to cheat the system because this class is loaded before purpur's config is loaded
+ return (org.purpurmc.purpur.PurpurConfig.allowShearsLooting && this.category == EnchantmentCategory.WEAPON ? EnchantmentCategory.WEAPON_AND_SHEARS : this.category).canEnchant(stack.getItem());
+ }
+ // Purpur end
+
@Override
public int getMinCost(int level) {
return 15 + (level - 1) * 9;
diff --git a/src/main/java/org/purpurmc/purpur/PurpurConfig.java b/src/main/java/org/purpurmc/purpur/PurpurConfig.java
index d56c2776d08306245618dca04cd39891bb61c1bd..730a4a2e46aeb233d8036e8d7e1749dcb397e6c0 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurConfig.java
@@ -391,6 +391,7 @@ public class PurpurConfig {
public static boolean allowInfinityMending = false;
public static boolean allowCrossbowInfinity = false;
+ public static boolean allowShearsLooting = false;
public static boolean allowUnsafeEnchants = false;
public static boolean allowInapplicableEnchants = true;
public static boolean allowIncompatibleEnchants = true;
@@ -413,6 +414,7 @@ public class PurpurConfig {
}
allowInfinityMending = getBoolean("settings.enchantment.allow-infinity-and-mending-together", allowInfinityMending);
allowCrossbowInfinity = getBoolean("settings.enchantment.allow-infinity-on-crossbow", allowCrossbowInfinity);
+ allowShearsLooting = getBoolean("settings.enchantment.allow-looting-on-shears", allowShearsLooting);
allowUnsafeEnchants = getBoolean("settings.enchantment.anvil.allow-unsafe-enchants", allowUnsafeEnchants);
allowInapplicableEnchants = getBoolean("settings.enchantment.anvil.allow-inapplicable-enchants", allowInapplicableEnchants);
allowIncompatibleEnchants = getBoolean("settings.enchantment.anvil.allow-incompatible-enchants", allowIncompatibleEnchants);

View File

@@ -0,0 +1,38 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: BillyGalbreath <Blake.Galbreath@Gmail.com>
Date: Mon, 3 Jan 2022 01:19:46 -0600
Subject: [PATCH] Stop bees from dying after stinging
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 ac4ca4de2be18a08268b24dfe259cfd136b1a4da..e837500019157129007841c847d807ebae10db04 100644
--- a/src/main/java/net/minecraft/world/entity/animal/Bee.java
+++ b/src/main/java/net/minecraft/world/entity/animal/Bee.java
@@ -439,6 +439,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal {
this.hurt(this.damageSources().drown(), 1.0F);
}
+ if (flag && !this.level().purpurConfig.beeDiesAfterSting) setHasStung(false); else // Purpur
if (flag) {
++this.timeSinceSting;
if (this.timeSinceSting % 5 == 0 && this.random.nextInt(Mth.clamp(1200 - this.timeSinceSting, 1, 1200)) == 0) {
diff --git a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
index a5f86aa5c3cd08dddb147c338a124953cacbf178..60beda5c1f3b7ca562b8ba9ff48e0c6e50e89649 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
@@ -1106,6 +1106,7 @@ public class PurpurWorldConfig {
public boolean beeCanWorkAtNight = false;
public boolean beeCanWorkInRain = false;
public boolean beeAlwaysDropExp = false;
+ public boolean beeDiesAfterSting = true;
private void beeSettings() {
beeRidable = getBoolean("mobs.bee.ridable", beeRidable);
beeRidableInWater = getBoolean("mobs.bee.ridable-in-water", beeRidableInWater);
@@ -1122,6 +1123,7 @@ public class PurpurWorldConfig {
beeCanWorkAtNight = getBoolean("mobs.bee.can-work-at-night", beeCanWorkAtNight);
beeCanWorkInRain = getBoolean("mobs.bee.can-work-in-rain", beeCanWorkInRain);
beeAlwaysDropExp = getBoolean("mobs.bee.always-drop-exp", beeAlwaysDropExp);
+ beeDiesAfterSting = getBoolean("mobs.bee.dies-after-sting", beeDiesAfterSting);
}
public boolean blazeRidable = false;

View File

@@ -0,0 +1,117 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: BillyGalbreath <blake.galbreath@gmail.com>
Date: Thu, 30 Dec 2021 09:56:43 -0600
Subject: [PATCH] Give bee counts in beehives to Purpur clients
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
index 5018f85fd87fe167389706bda04327bbe7d2c17a..ad403421711052faf36cb6b063997cfa90712423 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -1014,6 +1014,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
}
public void safeShutdown(boolean waitForShutdown, boolean isRestarting) {
org.purpurmc.purpur.task.BossBarTask.stopAll(); // Purpur
+ org.purpurmc.purpur.task.BeehiveTask.instance().unregister(); // Purpur
this.isRestarting = isRestarting;
this.hasLoggedStop = true; // Paper
if (isDebugging()) io.papermc.paper.util.TraceUtil.dumpTraceForThread("Server stopped"); // Paper
diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
index 2075f8f6096178930708268d0c4e2862824cbc45..7b1b34566c38d26ababfc5dafe254749ebc075ea 100644
--- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
+++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
@@ -372,6 +372,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface
}
org.purpurmc.purpur.task.BossBarTask.startAll(); // Purpur
+ org.purpurmc.purpur.task.BeehiveTask.instance().register(); // Purpur
return true;
}
}
diff --git a/src/main/java/org/purpurmc/purpur/task/BeehiveTask.java b/src/main/java/org/purpurmc/purpur/task/BeehiveTask.java
new file mode 100644
index 0000000000000000000000000000000000000000..2ebbaf5faa92a88bfb4d61298951e5b74157d1e1
--- /dev/null
+++ b/src/main/java/org/purpurmc/purpur/task/BeehiveTask.java
@@ -0,0 +1,81 @@
+package org.purpurmc.purpur.task;
+
+import com.google.common.io.ByteArrayDataInput;
+import com.google.common.io.ByteArrayDataOutput;
+import com.google.common.io.ByteStreams;
+import io.netty.buffer.Unpooled;
+import net.minecraft.core.BlockPos;
+import net.minecraft.network.FriendlyByteBuf;
+import net.minecraft.network.protocol.game.ClientboundCustomPayloadPacket;
+import net.minecraft.resources.ResourceLocation;
+import net.minecraft.server.level.ServerPlayer;
+import net.minecraft.world.level.block.entity.BeehiveBlockEntity;
+import net.minecraft.world.level.block.entity.BlockEntity;
+import org.bukkit.Bukkit;
+import org.bukkit.craftbukkit.entity.CraftPlayer;
+import org.bukkit.craftbukkit.scheduler.MinecraftInternalPlugin;
+import org.bukkit.entity.Player;
+import org.bukkit.plugin.PluginBase;
+import org.bukkit.plugin.messaging.PluginMessageListener;
+import org.jetbrains.annotations.NotNull;
+
+public class BeehiveTask implements PluginMessageListener {
+ public static final ResourceLocation BEEHIVE_C2S = new ResourceLocation("purpur", "beehive_c2s");
+ public static final ResourceLocation BEEHIVE_S2C = new ResourceLocation("purpur", "beehive_s2c");
+
+ private static BeehiveTask instance;
+
+ public static BeehiveTask instance() {
+ if (instance == null) {
+ instance = new BeehiveTask();
+ }
+ return instance;
+ }
+
+ private final PluginBase plugin = new MinecraftInternalPlugin();
+
+ private BeehiveTask() {
+ }
+
+ public void register() {
+ Bukkit.getMessenger().registerOutgoingPluginChannel(this.plugin, BEEHIVE_S2C.toString());
+ Bukkit.getMessenger().registerIncomingPluginChannel(this.plugin, BEEHIVE_C2S.toString(), this);
+ }
+
+ public void unregister() {
+ Bukkit.getMessenger().unregisterOutgoingPluginChannel(this.plugin, BEEHIVE_S2C.toString());
+ Bukkit.getMessenger().unregisterIncomingPluginChannel(this.plugin, BEEHIVE_C2S.toString());
+ }
+
+ @Override
+ public void onPluginMessageReceived(@NotNull String channel, Player player, byte[] bytes) {
+ ByteArrayDataInput in = in(bytes);
+ long packedPos = in.readLong();
+ BlockPos pos = BlockPos.of(packedPos);
+
+ ServerPlayer serverPlayer = ((CraftPlayer) player).getHandle();
+
+ BlockEntity blockEntity = serverPlayer.level().getBlockEntity(pos);
+ if (!(blockEntity instanceof BeehiveBlockEntity beehive)) {
+ return;
+ }
+
+ ByteArrayDataOutput out = out();
+
+ out.writeInt(beehive.getOccupantCount());
+ out.writeLong(packedPos);
+
+ FriendlyByteBuf buf = new FriendlyByteBuf(Unpooled.wrappedBuffer(out.toByteArray()));
+ serverPlayer.connection.send(new ClientboundCustomPayloadPacket(BEEHIVE_S2C, buf));
+ }
+
+ @SuppressWarnings("UnstableApiUsage")
+ private static ByteArrayDataOutput out() {
+ return ByteStreams.newDataOutput();
+ }
+
+ @SuppressWarnings("UnstableApiUsage")
+ private static ByteArrayDataInput in(byte[] bytes) {
+ return ByteStreams.newDataInput(bytes);
+ }
+}

View File

@@ -0,0 +1,56 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: BillyGalbreath <Blake.Galbreath@Gmail.com>
Date: Tue, 4 Jan 2022 11:56:48 -0600
Subject: [PATCH] Configurable farmland trample height
This is _not_ in block height or an exact science.
During my testing I found very inconsistent values
for the fallDistance variable. Here are the results
of those tests (https://imgur.com/BojltJF):
Value set -> Actual fall distance needed to trample
1.0 -> 1.25
1.5 -> 1.75
2.0 -> 2.25
2.5 -> 2.87
3.0 -> 3.5
3.5 -> 4.25
4.0 -> 4.25
4.5 -> 5.0
5.0 -> 5.87
5.5 -> 5.87
6.0 -> 6.75
diff --git a/src/main/java/net/minecraft/world/level/block/FarmBlock.java b/src/main/java/net/minecraft/world/level/block/FarmBlock.java
index 56e66fcd840d0d3681ba671d1ffc51b232631461..d566f67f8f6f1748023430de4f191881b79e44a1 100644
--- a/src/main/java/net/minecraft/world/level/block/FarmBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/FarmBlock.java
@@ -101,7 +101,7 @@ public class FarmBlock extends Block {
@Override
public void fallOn(Level world, BlockState state, BlockPos pos, Entity entity, float fallDistance) {
super.fallOn(world, state, pos, entity, fallDistance); // CraftBukkit - moved here as game rules / events shouldn't affect fall damage.
- if (!world.isClientSide && world.random.nextFloat() < fallDistance - 0.5F && entity instanceof LivingEntity && (entity instanceof Player || world.purpurConfig.farmlandBypassMobGriefing || world.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) && entity.getBbWidth() * entity.getBbWidth() * entity.getBbHeight() > 0.512F) { // Purpur
+ if (!world.isClientSide && (world.purpurConfig.farmlandTrampleHeight >= 0D ? fallDistance >= world.purpurConfig.farmlandTrampleHeight : world.random.nextFloat() < fallDistance - 0.5F) && entity instanceof LivingEntity && (entity instanceof Player || world.purpurConfig.farmlandBypassMobGriefing || world.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) && entity.getBbWidth() * entity.getBbWidth() * entity.getBbHeight() > 0.512F) { // Purpur
// CraftBukkit start - Interact soil
org.bukkit.event.Cancellable cancellable;
if (entity instanceof Player) {
diff --git a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
index 60beda5c1f3b7ca562b8ba9ff48e0c6e50e89649..3d1107d954d8dd040895908ddadf2c11c437a9ef 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
@@ -889,6 +889,7 @@ public class PurpurWorldConfig {
public boolean farmlandTramplingDisabled = false;
public boolean farmlandTramplingOnlyPlayers = false;
public boolean farmlandTramplingFeatherFalling = false;
+ public double farmlandTrampleHeight = -1D;
private void farmlandSettings() {
farmlandBypassMobGriefing = getBoolean("blocks.farmland.bypass-mob-griefing", farmlandBypassMobGriefing);
farmlandGetsMoistFromBelow = getBoolean("blocks.farmland.gets-moist-from-below", farmlandGetsMoistFromBelow);
@@ -896,6 +897,7 @@ public class PurpurWorldConfig {
farmlandTramplingDisabled = getBoolean("blocks.farmland.disable-trampling", farmlandTramplingDisabled);
farmlandTramplingOnlyPlayers = getBoolean("blocks.farmland.only-players-trample", farmlandTramplingOnlyPlayers);
farmlandTramplingFeatherFalling = getBoolean("blocks.farmland.feather-fall-distance-affects-trampling", farmlandTramplingFeatherFalling);
+ farmlandTrampleHeight = getDouble("blocks.farmland.trample-height", farmlandTrampleHeight);
}
public double floweringAzaleaGrowthChance = 0.0D;

View File

@@ -0,0 +1,56 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: BillyGalbreath <Blake.Galbreath@Gmail.com>
Date: Mon, 10 Jan 2022 10:04:31 -0600
Subject: [PATCH] Configurable player pickup exp delay
Default vanilla value is to delay 2 ticks between picking up exp orbs.
Players only pick up 1 orb at a time, so even with setting this to 0
players still only pick up one orb every tick. However, setting this
to any negative number will pick up all orbs instantly.
diff --git a/src/main/java/net/minecraft/world/entity/ExperienceOrb.java b/src/main/java/net/minecraft/world/entity/ExperienceOrb.java
index 2bd576849403bc2cfae298c2210616192ddc38db..b2233635b6acc35ea3668c36c56e57f15420ac62 100644
--- a/src/main/java/net/minecraft/world/entity/ExperienceOrb.java
+++ b/src/main/java/net/minecraft/world/entity/ExperienceOrb.java
@@ -313,7 +313,7 @@ public class ExperienceOrb extends Entity {
public void playerTouch(Player player) {
if (!this.level().isClientSide) {
if (player.takeXpDelay == 0 && new com.destroystokyo.paper.event.player.PlayerPickupExperienceEvent(((net.minecraft.server.level.ServerPlayer) player).getBukkitEntity(), (org.bukkit.entity.ExperienceOrb) this.getBukkitEntity()).callEvent()) { // Paper
- player.takeXpDelay = CraftEventFactory.callPlayerXpCooldownEvent(player, 2, PlayerExpCooldownChangeEvent.ChangeReason.PICKUP_ORB).getNewCooldown(); // CraftBukkit - entityhuman.takeXpDelay = 2;
+ player.takeXpDelay = CraftEventFactory.callPlayerXpCooldownEvent(player, this.level().purpurConfig.playerExpPickupDelay, PlayerExpCooldownChangeEvent.ChangeReason.PICKUP_ORB).getNewCooldown(); // CraftBukkit - entityhuman.takeXpDelay = 2; // Purpur
player.take(this, 1);
int i = this.repairPlayerItems(player, this.value);
diff --git a/src/main/java/net/minecraft/world/entity/player/Player.java b/src/main/java/net/minecraft/world/entity/player/Player.java
index 52b4ffc17ac913bf64cf6a6b7a37ae6e5af9bd87..20c3d3c9d2150574e9b4761dc1bda11cee04862f 100644
--- a/src/main/java/net/minecraft/world/entity/player/Player.java
+++ b/src/main/java/net/minecraft/world/entity/player/Player.java
@@ -636,7 +636,7 @@ public abstract class Player extends LivingEntity {
while (iterator.hasNext()) {
Entity entity = (Entity) iterator.next();
- if (entity.getType() == EntityType.EXPERIENCE_ORB) {
+ if (entity.getType() == EntityType.EXPERIENCE_ORB && entity.level().purpurConfig.playerExpPickupDelay >= 0) { // Purpur
list1.add(entity);
} else if (!entity.isRemoved()) {
this.touch(entity);
diff --git a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
index 3d1107d954d8dd040895908ddadf2c11c437a9ef..f0f83c4570c79ed88275631ee35aa20e5ef27748 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
@@ -422,6 +422,7 @@ public class PurpurWorldConfig {
public boolean playerRidableInWater = false;
public boolean playerRemoveBindingWithWeakness = false;
public int shiftRightClickRepairsMendingPoints = 0;
+ public int playerExpPickupDelay = 2;
private void playerSettings() {
if (PurpurConfig.version < 19) {
boolean oldVal = getBoolean("gameplay-mechanics.player.idle-timeout.mods-target", idleTimeoutTargetPlayer);
@@ -449,6 +450,7 @@ public class PurpurWorldConfig {
playerRidableInWater = getBoolean("gameplay-mechanics.player.ridable-in-water", playerRidableInWater);
playerRemoveBindingWithWeakness = getBoolean("gameplay-mechanics.player.curse-of-binding.remove-with-weakness", playerRemoveBindingWithWeakness);
shiftRightClickRepairsMendingPoints = getInt("gameplay-mechanics.player.shift-right-click-repairs-mending-points", shiftRightClickRepairsMendingPoints);
+ playerExpPickupDelay = getInt("gameplay-mechanics.player.exp-pickup-delay-ticks", playerExpPickupDelay);
}
private static boolean projectileDespawnRateSettingsMigrated = false;

View File

@@ -0,0 +1,39 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: BillyGalbreath <Blake.Galbreath@Gmail.com>
Date: Sat, 15 Jan 2022 03:27:29 -0600
Subject: [PATCH] Allow void trading
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
index cb35bac1923fe40f172a521ce5892e0dcfd7e305..7ded6820b9b0b493a72e158d7a92d5062d2948ef 100644
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
@@ -2725,7 +2725,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
// Spigot Start
if (entity.getBukkitEntity() instanceof org.bukkit.inventory.InventoryHolder && (!(entity instanceof ServerPlayer) || entity.getRemovalReason() != Entity.RemovalReason.KILLED)) { // SPIGOT-6876: closeInventory clears death message
// Paper start
- if (entity.getBukkitEntity() instanceof org.bukkit.inventory.Merchant merchant && merchant.getTrader() != null) {
+ if (!entity.level().purpurConfig.playerVoidTrading && entity.getBukkitEntity() instanceof org.bukkit.inventory.Merchant merchant && merchant.getTrader() != null) { // Purpur
merchant.getTrader().closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason.UNLOADED);
}
// Paper end
diff --git a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
index f0f83c4570c79ed88275631ee35aa20e5ef27748..6008732a98759ac23daab766ea986162b816945f 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
@@ -423,6 +423,7 @@ public class PurpurWorldConfig {
public boolean playerRemoveBindingWithWeakness = false;
public int shiftRightClickRepairsMendingPoints = 0;
public int playerExpPickupDelay = 2;
+ public boolean playerVoidTrading = false;
private void playerSettings() {
if (PurpurConfig.version < 19) {
boolean oldVal = getBoolean("gameplay-mechanics.player.idle-timeout.mods-target", idleTimeoutTargetPlayer);
@@ -451,6 +452,7 @@ public class PurpurWorldConfig {
playerRemoveBindingWithWeakness = getBoolean("gameplay-mechanics.player.curse-of-binding.remove-with-weakness", playerRemoveBindingWithWeakness);
shiftRightClickRepairsMendingPoints = getInt("gameplay-mechanics.player.shift-right-click-repairs-mending-points", shiftRightClickRepairsMendingPoints);
playerExpPickupDelay = getInt("gameplay-mechanics.player.exp-pickup-delay-ticks", playerExpPickupDelay);
+ playerVoidTrading = getBoolean("gameplay-mechanics.player.allow-void-trading", playerVoidTrading);
}
private static boolean projectileDespawnRateSettingsMigrated = false;

View File

@@ -0,0 +1,50 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: BillyGalbreath <Blake.Galbreath@Gmail.com>
Date: Mon, 17 Jan 2022 21:28:49 -0600
Subject: [PATCH] Configurable phantom size
diff --git a/src/main/java/net/minecraft/world/entity/monster/Phantom.java b/src/main/java/net/minecraft/world/entity/monster/Phantom.java
index ab9ed9acc394dedf2151b83ff5cf998e0e0be21e..355445b7f8972cb789d33f59d03c382f238c294d 100644
--- a/src/main/java/net/minecraft/world/entity/monster/Phantom.java
+++ b/src/main/java/net/minecraft/world/entity/monster/Phantom.java
@@ -272,7 +272,11 @@ public class Phantom extends FlyingMob implements Enemy {
@Override
public SpawnGroupData finalizeSpawn(ServerLevelAccessor world, DifficultyInstance difficulty, MobSpawnType spawnReason, @Nullable SpawnGroupData entityData, @Nullable CompoundTag entityNbt) {
this.anchorPoint = this.blockPosition().above(5);
- this.setPhantomSize(0);
+ // Purpur start
+ int min = world.getLevel().purpurConfig.phantomMinSize;
+ int max = world.getLevel().purpurConfig.phantomMaxSize;
+ this.setPhantomSize(min == max ? min : world.getRandom().nextInt(max + 1 - min) + min);
+ // Purpur end
return super.finalizeSpawn(world, difficulty, spawnReason, entityData, entityNbt);
}
diff --git a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
index 6008732a98759ac23daab766ea986162b816945f..807ca55a5734fccb10b1aae2d99e0b37aeffc614 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
@@ -2048,6 +2048,8 @@ public class PurpurWorldConfig {
public boolean phantomFlamesOnSwoop = false;
public boolean phantomTakeDamageFromWater = false;
public boolean phantomAlwaysDropExp = false;
+ public int phantomMinSize = 0;
+ public int phantomMaxSize = 0;
private void phantomSettings() {
phantomRidable = getBoolean("mobs.phantom.ridable", phantomRidable);
phantomRidableInWater = getBoolean("mobs.phantom.ridable-in-water", phantomRidableInWater);
@@ -2084,6 +2086,13 @@ public class PurpurWorldConfig {
phantomFlamesOnSwoop = getBoolean("mobs.phantom.flames-on-swoop", phantomFlamesOnSwoop);
phantomTakeDamageFromWater = getBoolean("mobs.phantom.takes-damage-from-water", phantomTakeDamageFromWater);
phantomAlwaysDropExp = getBoolean("mobs.phantom.always-drop-exp", phantomAlwaysDropExp);
+ phantomMinSize = Mth.clamp(getInt("mobs.phantom.size.min", phantomMinSize), 0, 64);
+ phantomMaxSize = Mth.clamp(getInt("mobs.phantom.size.max", phantomMaxSize), 0, 64);
+ if (phantomMinSize > phantomMaxSize) {
+ phantomMinSize = phantomMinSize ^ phantomMaxSize;
+ phantomMaxSize = phantomMinSize ^ phantomMaxSize;
+ phantomMinSize = phantomMinSize ^ phantomMaxSize;
+ }
}
public boolean pigRidable = false;

View File

@@ -0,0 +1,150 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: BillyGalbreath <Blake.Galbreath@Gmail.com>
Date: Tue, 18 Jan 2022 04:51:51 -0600
Subject: [PATCH] Configurable food attributes
diff --git a/src/main/java/net/minecraft/world/food/FoodProperties.java b/src/main/java/net/minecraft/world/food/FoodProperties.java
index 9967ba762567631f2bdb1e4f8fe16a13ea927b46..6c945ae8fe8b1517e312c688f829fab41f12d9f4 100644
--- a/src/main/java/net/minecraft/world/food/FoodProperties.java
+++ b/src/main/java/net/minecraft/world/food/FoodProperties.java
@@ -2,15 +2,22 @@ package net.minecraft.world.food;
import com.google.common.collect.Lists;
import com.mojang.datafixers.util.Pair;
+
+import java.util.ArrayList;
import java.util.List;
import net.minecraft.world.effect.MobEffectInstance;
public class FoodProperties {
- private final int nutrition;
- private final float saturationModifier;
- private final boolean isMeat;
- private final boolean canAlwaysEat;
- private final boolean fastFood;
+ // Purpur start
+ private int nutrition; public void setNutrition(int nutrition) { this.nutrition = nutrition; }
+ private float saturationModifier; public void setSaturationModifier(float saturation) { this.saturationModifier = saturation; }
+ private boolean isMeat; public void setIsMeat(boolean isMeat) { this.isMeat = isMeat; }
+ private boolean canAlwaysEat; public void setCanAlwaysEat(boolean canAlwaysEat) { this.canAlwaysEat = canAlwaysEat; }
+ private boolean fastFood; public void setFastFood(boolean isFastFood) { this.fastFood = isFastFood; }
+ public FoodProperties copy() {
+ return new FoodProperties(this.nutrition, this.saturationModifier, this.isMeat, this.canAlwaysEat, this.fastFood, new ArrayList<>(this.effects));
+ }
+ // Purpur end
private final List<Pair<MobEffectInstance, Float>> effects;
FoodProperties(int hunger, float saturationModifier, boolean meat, boolean alwaysEdible, boolean snack, List<Pair<MobEffectInstance, Float>> statusEffects) {
diff --git a/src/main/java/net/minecraft/world/food/Foods.java b/src/main/java/net/minecraft/world/food/Foods.java
index b16d9e2eaa589f19c563ee70b1a56d67dbcdecb0..71beab673f04cd051c46ea37f8c847316885d38d 100644
--- a/src/main/java/net/minecraft/world/food/Foods.java
+++ b/src/main/java/net/minecraft/world/food/Foods.java
@@ -4,6 +4,9 @@ import net.minecraft.world.effect.MobEffectInstance;
import net.minecraft.world.effect.MobEffects;
public class Foods {
+ public static final java.util.Map<String, FoodProperties> ALL_PROPERTIES = new java.util.HashMap<>(); // Purpur
+ public static final java.util.Map<String, FoodProperties> DEFAULT_PROPERTIES = new java.util.HashMap<>(); // Purpur
+
public static final FoodProperties APPLE = (new FoodProperties.Builder()).nutrition(4).saturationMod(0.3F).build();
public static final FoodProperties BAKED_POTATO = (new FoodProperties.Builder()).nutrition(5).saturationMod(0.6F).build();
public static final FoodProperties BEEF = (new FoodProperties.Builder()).nutrition(3).saturationMod(0.3F).meat().build();
diff --git a/src/main/java/net/minecraft/world/item/Items.java b/src/main/java/net/minecraft/world/item/Items.java
index 31f5ed9dd1727eee24804a384817d2b76a45676b..5fbb13ebef0ca66419f3e5006d19e4a5918a038a 100644
--- a/src/main/java/net/minecraft/world/item/Items.java
+++ b/src/main/java/net/minecraft/world/item/Items.java
@@ -1309,6 +1309,13 @@ public class Items {
((BlockItem)item).registerBlocks(Item.BY_BLOCK, item);
}
+ // Purpur start
+ if (item.getFoodProperties() != null) {
+ Foods.ALL_PROPERTIES.put(key.location().getPath(), item.getFoodProperties());
+ Foods.DEFAULT_PROPERTIES.put(key.location().getPath(), item.getFoodProperties().copy());
+ }
+ // Purpur end
+
return Registry.register(BuiltInRegistries.ITEM, key, item);
}
}
diff --git a/src/main/java/org/purpurmc/purpur/PurpurConfig.java b/src/main/java/org/purpurmc/purpur/PurpurConfig.java
index 730a4a2e46aeb233d8036e8d7e1749dcb397e6c0..fa81039056af14c37426a508b7b2da77e8b50737 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurConfig.java
@@ -461,4 +461,75 @@ 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 foodSettings() {
+ ConfigurationSection properties = config.getConfigurationSection("settings.food-properties");
+ if (properties == null) {
+ config.addDefault("settings.food-properties", new HashMap<>());
+ return;
+ }
+
+ Map<MobEffect, Map<String, Object>> effectDefaults = new HashMap<>();
+ Map<String, Object> EFFECT_DEFAULT = Map.of(
+ "chance", 0.0F,
+ "duration", 0,
+ "amplifier", 0,
+ "ambient", false,
+ "visible", true,
+ "show-icon", true
+ );
+
+ properties.getKeys(false).forEach(foodKey -> {
+ FoodProperties food = Foods.ALL_PROPERTIES.get(foodKey);
+ if (food == null) {
+ PurpurConfig.log(Level.SEVERE, "Invalid food property: " + foodKey);
+ return;
+ }
+ FoodProperties foodDefaults = Foods.DEFAULT_PROPERTIES.get(foodKey);
+ food.setNutrition(properties.getInt(foodKey + ".nutrition", foodDefaults.getNutrition()));
+ food.setSaturationModifier((float) properties.getDouble(foodKey + ".saturation-modifier", foodDefaults.getSaturationModifier()));
+ food.setIsMeat(properties.getBoolean(foodKey + ".is-meat", foodDefaults.isMeat()));
+ food.setCanAlwaysEat(properties.getBoolean(foodKey + ".can-always-eat", foodDefaults.canAlwaysEat()));
+ food.setFastFood(properties.getBoolean(foodKey + ".fast-food", foodDefaults.isFastFood()));
+ ConfigurationSection effects = properties.getConfigurationSection(foodKey + ".effects");
+ if (effects != null) {
+ effectDefaults.clear();
+ foodDefaults.getEffects().forEach(pair -> {
+ MobEffectInstance effect = pair.getFirst();
+ effectDefaults.put(effect.getEffect(), Map.of(
+ "chance", pair.getSecond(),
+ "duration", effect.getDuration(),
+ "amplifier", effect.getAmplifier(),
+ "ambient", effect.isAmbient(),
+ "visible", effect.isVisible(),
+ "show-icon", effect.showIcon()
+ ));
+ });
+ effects.getKeys(false).forEach(effectKey -> {
+ MobEffect effect = BuiltInRegistries.MOB_EFFECT.get(new ResourceLocation(effectKey));
+ if (effect == null) {
+ PurpurConfig.log(Level.SEVERE, "Invalid food property effect for " + foodKey + ": " + effectKey);
+ return;
+ }
+
+ Map<String, Object> effectDefault = effectDefaults.get(effect);
+ if (effectDefault == null) {
+ effectDefault = EFFECT_DEFAULT;
+ }
+
+ food.getEffects().removeIf(pair -> pair.getFirst().getEffect() == effect);
+ float chance = (float) effects.getDouble(effectKey + ".chance", ((Float) effectDefault.get("chance")).doubleValue());
+ int duration = effects.getInt(effectKey + ".duration", (int) effectDefault.get("duration"));
+ if (chance <= 0.0F || duration < 0) {
+ return;
+ }
+ int amplifier = effects.getInt(effectKey + ".amplifier", (int) effectDefault.get("amplifier"));
+ boolean ambient = effects.getBoolean(effectKey + ".ambient", (boolean) effectDefault.get("ambient"));
+ boolean visible = effects.getBoolean(effectKey + ".visible", (boolean) effectDefault.get("visible"));
+ boolean showIcon = effects.getBoolean(effectKey + ".show-icon", (boolean) effectDefault.get("show-icon"));
+ food.getEffects().add(Pair.of(new MobEffectInstance(effect, duration, amplifier, ambient, visible, showIcon), chance));
+ });
+ }
+ });
+ }
}

View File

@@ -0,0 +1,47 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: BillyGalbreath <Blake.Galbreath@Gmail.com>
Date: Tue, 18 Jan 2022 06:35:54 -0600
Subject: [PATCH] Max joins per second
When this option is set to true the `max-joins-per-tick` setting in paper.yml will be used per second instead of per tick
diff --git a/src/main/java/net/minecraft/network/Connection.java b/src/main/java/net/minecraft/network/Connection.java
index 91fcb63835b0b725c53bc75be782b5c5bcc870e7..52639268f0db741e0eb67dc02f9d6e74aeccae6c 100644
--- a/src/main/java/net/minecraft/network/Connection.java
+++ b/src/main/java/net/minecraft/network/Connection.java
@@ -569,11 +569,20 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
private static final int MAX_PER_TICK = io.papermc.paper.configuration.GlobalConfiguration.get().misc.maxJoinsPerTick; // Paper
private static int joinAttemptsThisTick; // Paper
private static int currTick; // Paper
+ private static int tickSecond; // Purpur
public void tick() {
this.flushQueue();
// Paper start
if (Connection.currTick != net.minecraft.server.MinecraftServer.currentTick) {
Connection.currTick = net.minecraft.server.MinecraftServer.currentTick;
+ // Purpur start
+ if (org.purpurmc.purpur.PurpurConfig.maxJoinsPerSecond) {
+ if (++Connection.tickSecond > 20) {
+ Connection.tickSecond = 0;
+ Connection.joinAttemptsThisTick = 0;
+ }
+ } else
+ // Purpur end
Connection.joinAttemptsThisTick = 0;
}
// Paper end
diff --git a/src/main/java/org/purpurmc/purpur/PurpurConfig.java b/src/main/java/org/purpurmc/purpur/PurpurConfig.java
index fa81039056af14c37426a508b7b2da77e8b50737..44e8822dae170c07e48ae016826a6710b7d7e29a 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurConfig.java
@@ -451,8 +451,10 @@ public class PurpurConfig {
}
public static boolean useUPnP = false;
+ public static boolean maxJoinsPerSecond = false;
private static void networkSettings() {
useUPnP = getBoolean("settings.network.upnp-port-forwarding", useUPnP);
+ maxJoinsPerSecond = getBoolean("settings.network.max-joins-per-second", maxJoinsPerSecond);
}
public static java.util.regex.Pattern usernameValidCharactersPattern;

View File

@@ -0,0 +1,61 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Totorewa <76272501+totorewa@users.noreply.github.com>
Date: Fri, 7 Jan 2022 21:34:57 +1300
Subject: [PATCH] Configurable minimum demand for trades
Addresses MC-163962 where villager demand decreases indefinitely. Paper
adds a patch to fix this by preventing demand from going below zero.
This patch adds a config option to allow the minimum demand to instead
be configurable.
diff --git a/src/main/java/net/minecraft/world/entity/npc/Villager.java b/src/main/java/net/minecraft/world/entity/npc/Villager.java
index 1e054e727243b9d47cc913f82cf8e026a9f4af44..46a3f321e4673401ee597f779d5f61441e7c3598 100644
--- a/src/main/java/net/minecraft/world/entity/npc/Villager.java
+++ b/src/main/java/net/minecraft/world/entity/npc/Villager.java
@@ -540,7 +540,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler
while (iterator.hasNext()) {
MerchantOffer merchantrecipe = (MerchantOffer) iterator.next();
- merchantrecipe.updateDemand();
+ merchantrecipe.updateDemand(this.level().purpurConfig.villagerMinimumDemand); // Purpur
}
}
diff --git a/src/main/java/net/minecraft/world/item/trading/MerchantOffer.java b/src/main/java/net/minecraft/world/item/trading/MerchantOffer.java
index 4f7457578ab3118d10e0d5dfc23d79c9b20c2f44..e03ce53b93d1b9366f2a7f14f341750a163ae0db 100644
--- a/src/main/java/net/minecraft/world/item/trading/MerchantOffer.java
+++ b/src/main/java/net/minecraft/world/item/trading/MerchantOffer.java
@@ -149,7 +149,12 @@ public class MerchantOffer {
}
public void updateDemand() {
- this.demand = Math.max(0, this.demand + this.uses - (this.maxUses - this.uses)); // Paper
+ // Purpur start
+ this.updateDemand(0);
+ }
+ public void updateDemand(int minimumDemand) {
+ this.demand = Math.max(minimumDemand, this.demand + this.uses - (this.maxUses - this.uses));
+ // Purpur end
}
public ItemStack assemble() {
diff --git a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
index 807ca55a5734fccb10b1aae2d99e0b37aeffc614..321c625b1374e1a5676459d33f071d62ad45437b 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
@@ -2731,6 +2731,7 @@ public class PurpurWorldConfig {
public boolean villagerTakeDamageFromWater = false;
public boolean villagerAllowTrading = true;
public boolean villagerAlwaysDropExp = false;
+ public int villagerMinimumDemand = 0;
private void villagerSettings() {
villagerRidable = getBoolean("mobs.villager.ridable", villagerRidable);
villagerRidableInWater = getBoolean("mobs.villager.ridable-in-water", villagerRidableInWater);
@@ -2751,6 +2752,7 @@ public class PurpurWorldConfig {
villagerTakeDamageFromWater = getBoolean("mobs.villager.takes-damage-from-water", villagerTakeDamageFromWater);
villagerAllowTrading = getBoolean("mobs.villager.allow-trading", villagerAllowTrading);
villagerAlwaysDropExp = getBoolean("mobs.villager.always-drop-exp", villagerAlwaysDropExp);
+ villagerMinimumDemand = getInt("mobs.villager.minimum-demand", villagerMinimumDemand);
}
public boolean vindicatorRidable = false;

View File

@@ -0,0 +1,138 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: William Blake Galbreath <Blake.Galbreath@GMail.com>
Date: Thu, 3 Dec 2020 17:56:18 -0600
Subject: [PATCH] Lobotomize stuck villagers
diff --git a/src/main/java/net/minecraft/world/entity/npc/Villager.java b/src/main/java/net/minecraft/world/entity/npc/Villager.java
index 46a3f321e4673401ee597f779d5f61441e7c3598..d70639fef24b6a8a3b504723992a050edbc16f61 100644
--- a/src/main/java/net/minecraft/world/entity/npc/Villager.java
+++ b/src/main/java/net/minecraft/world/entity/npc/Villager.java
@@ -141,6 +141,8 @@ public class Villager extends AbstractVillager implements ReputationEventHandler
}, MemoryModuleType.MEETING_POINT, (entityvillager, holder) -> {
return holder.is(PoiTypes.MEETING);
});
+ private boolean isLobotomized = false; public boolean isLobotomized() { return this.isLobotomized; } // Purpur
+ private int notLobotomizedCount = 0; // Purpur
public Villager(EntityType<? extends Villager> entityType, Level world) {
this(entityType, world, VillagerType.PLAINS);
@@ -198,6 +200,47 @@ public class Villager extends AbstractVillager implements ReputationEventHandler
return this.level().purpurConfig.villagerAlwaysDropExp;
}
+ private boolean checkLobotomized() {
+ int interval = this.level().purpurConfig.villagerLobotomizeCheckInterval;
+ if (this.notLobotomizedCount > 3) {
+ // check half as often if not lobotomized for the last 3+ consecutive checks
+ interval *= 2;
+ }
+ if (this.level().getGameTime() % interval == 0) {
+ // offset Y for short blocks like dirt_path/farmland
+ this.isLobotomized = !canTravelFrom(BlockPos.containing(this.position().x, this.getBoundingBox().minY + 0.0625D, this.position().z));
+
+ if (this.isLobotomized) {
+ this.notLobotomizedCount = 0;
+ } else {
+ this.notLobotomizedCount++;
+ }
+ }
+ return this.isLobotomized;
+ }
+
+ private boolean canTravelFrom(BlockPos pos) {
+ return canTravelTo(pos.east()) || canTravelTo(pos.west()) || canTravelTo(pos.north()) || canTravelTo(pos.south());
+ }
+
+ private boolean canTravelTo(BlockPos pos) {
+ net.minecraft.world.level.block.state.BlockState state = this.level().getBlockStateIfLoaded(pos);
+ if (state == null) {
+ // chunk not loaded
+ return false;
+ }
+ net.minecraft.world.level.block.Block bottom = state.getBlock();
+ if (bottom instanceof net.minecraft.world.level.block.FenceBlock ||
+ bottom instanceof net.minecraft.world.level.block.FenceGateBlock ||
+ bottom instanceof net.minecraft.world.level.block.WallBlock) {
+ // bottom block is too tall to get over
+ return false;
+ }
+ net.minecraft.world.level.block.Block top = level().getBlockState(pos.above()).getBlock();
+ // only if both blocks have no collision
+ return !bottom.hasCollision && !top.hasCollision;
+ }
+
@Override
public Brain<Villager> getBrain() {
return (Brain<Villager>) super.getBrain(); // CraftBukkit - decompile error
@@ -294,10 +337,21 @@ public class Villager extends AbstractVillager implements ReputationEventHandler
// Paper start
this.customServerAiStep(false);
}
- protected void customServerAiStep(final boolean inactive) {
+ protected void customServerAiStep(boolean inactive) { // Purpur - not final
// Paper end
this.level().getProfiler().push("villagerBrain");
- //if (!inactive && (getRider() == null || !this.isControllable()) && this.behaviorTick++ % this.activatedPriority == 0) { // Purpur - only use brain if no rider // Purpur - TODO: Pufferfish
+ // Purpur start
+ if (this.level().purpurConfig.villagerLobotomizeEnabled) {
+ // treat as inactive if lobotomized
+ inactive = inactive || checkLobotomized();
+ } else {
+ // clean up state for API
+ this.isLobotomized = false;
+ }
+ /*if (!inactive && (getRider() == null || !this.isControllable()) && this.behaviorTick++ % this.activatedPriority == 0) // Purpur - only use brain if no rider // Purpur - TODO: Pufferfish
+ this.getBrain().tick((ServerLevel) this.level(), this); // Paper
+ else */if (this.isLobotomized && shouldRestock()) restock();
+ // Purpur end
if (!inactive) this.getBrain().tick((ServerLevel) this.level(), this); // Paper
this.level().getProfiler().pop();
if (this.assignProfessionWhenSpawned) {
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java
index a67b5d20b956e0bf801c9eeb9330567c21927010..15c7dd5ae4ea040b91b665e5ce05c0d35ab1604e 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java
@@ -252,4 +252,11 @@ public class CraftVillager extends CraftAbstractVillager implements Villager {
getHandle().getGossips().gossips.clear();
}
// Paper end
+
+ // Purpur start
+ @Override
+ public boolean isLobotomized() {
+ return getHandle().isLobotomized();
+ }
+ // Purpur end
}
diff --git a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
index 321c625b1374e1a5676459d33f071d62ad45437b..3fa481c71331a19b58511392a840f47915639ce2 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
@@ -2732,6 +2732,8 @@ public class PurpurWorldConfig {
public boolean villagerAllowTrading = true;
public boolean villagerAlwaysDropExp = false;
public int villagerMinimumDemand = 0;
+ public boolean villagerLobotomizeEnabled = false;
+ public int villagerLobotomizeCheckInterval = 100;
private void villagerSettings() {
villagerRidable = getBoolean("mobs.villager.ridable", villagerRidable);
villagerRidableInWater = getBoolean("mobs.villager.ridable-in-water", villagerRidableInWater);
@@ -2753,6 +2755,17 @@ public class PurpurWorldConfig {
villagerAllowTrading = getBoolean("mobs.villager.allow-trading", villagerAllowTrading);
villagerAlwaysDropExp = getBoolean("mobs.villager.always-drop-exp", villagerAlwaysDropExp);
villagerMinimumDemand = getInt("mobs.villager.minimum-demand", villagerMinimumDemand);
+ if (PurpurConfig.version < 9) {
+ boolean oldValue = getBoolean("mobs.villager.lobotomize-1x1", villagerLobotomizeEnabled);
+ set("mobs.villager.lobotomize.enabled", oldValue);
+ set("mobs.villager.lobotomize-1x1", null);
+ }
+ if (PurpurConfig.version < 27) {
+ int oldValue = getInt("mobs.villager.lobotomize.check-interval", villagerLobotomizeCheckInterval);
+ set("mobs.villager.lobotomize.check-interval", oldValue == 60 ? 100 : oldValue);
+ }
+ villagerLobotomizeEnabled = getBoolean("mobs.villager.lobotomize.enabled", villagerLobotomizeEnabled);
+ villagerLobotomizeCheckInterval = getInt("mobs.villager.lobotomize.check-interval", villagerLobotomizeCheckInterval);
}
public boolean vindicatorRidable = false;

View File

@@ -0,0 +1,38 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: BillyGalbreath <Blake.Galbreath@Gmail.com>
Date: Tue, 25 Jan 2022 15:03:48 -0600
Subject: [PATCH] Option for villager display trade item
diff --git a/src/main/java/net/minecraft/world/entity/ai/behavior/ShowTradesToPlayer.java b/src/main/java/net/minecraft/world/entity/ai/behavior/ShowTradesToPlayer.java
index c3e0b1f11b58668f9f24eb421abc340e1b49dfac..d809fa4f96e2c528075f544355397903996ecaf6 100644
--- a/src/main/java/net/minecraft/world/entity/ai/behavior/ShowTradesToPlayer.java
+++ b/src/main/java/net/minecraft/world/entity/ai/behavior/ShowTradesToPlayer.java
@@ -42,6 +42,7 @@ public class ShowTradesToPlayer extends Behavior<Villager> {
@Override
public boolean canStillUse(ServerLevel world, Villager entity, long time) {
+ if (!entity.level().purpurConfig.villagerDisplayTradeItem) return false; // Purpur
return this.checkExtraStartConditions(world, entity) && this.lookTime > 0 && entity.getBrain().getMemory(MemoryModuleType.INTERACTION_TARGET).isPresent();
}
diff --git a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
index 3fa481c71331a19b58511392a840f47915639ce2..38d13eb230cfb33a450b8a9a1a3c6aa2efe5b053 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
@@ -2734,6 +2734,7 @@ public class PurpurWorldConfig {
public int villagerMinimumDemand = 0;
public boolean villagerLobotomizeEnabled = false;
public int villagerLobotomizeCheckInterval = 100;
+ public boolean villagerDisplayTradeItem = true;
private void villagerSettings() {
villagerRidable = getBoolean("mobs.villager.ridable", villagerRidable);
villagerRidableInWater = getBoolean("mobs.villager.ridable-in-water", villagerRidableInWater);
@@ -2766,6 +2767,7 @@ public class PurpurWorldConfig {
}
villagerLobotomizeEnabled = getBoolean("mobs.villager.lobotomize.enabled", villagerLobotomizeEnabled);
villagerLobotomizeCheckInterval = getInt("mobs.villager.lobotomize.check-interval", villagerLobotomizeCheckInterval);
+ villagerDisplayTradeItem = getBoolean("mobs.villager.display-trade-item", villagerDisplayTradeItem);
}
public boolean vindicatorRidable = false;

View File

@@ -0,0 +1,33 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: BillyGalbreath <Blake.Galbreath@Gmail.com>
Date: Sun, 30 Jan 2022 02:03:34 -0600
Subject: [PATCH] MC-238526 - Fix spawner not spawning water animals correctly
diff --git a/src/main/java/net/minecraft/world/entity/animal/WaterAnimal.java b/src/main/java/net/minecraft/world/entity/animal/WaterAnimal.java
index cd2ce5bcb8c30e4657cd0e340d80544c7e805905..c8c6fed3f93903bb5c6145930538d415f6f59738 100644
--- a/src/main/java/net/minecraft/world/entity/animal/WaterAnimal.java
+++ b/src/main/java/net/minecraft/world/entity/animal/WaterAnimal.java
@@ -82,6 +82,6 @@ public abstract class WaterAnimal extends PathfinderMob {
i = world.getMinecraftWorld().paperConfig().entities.spawning.wateranimalSpawnHeight.maximum.or(i);
j = world.getMinecraftWorld().paperConfig().entities.spawning.wateranimalSpawnHeight.minimum.or(j);
// Paper end
- return pos.getY() >= j && pos.getY() <= i && world.getFluidState(pos.below()).is(FluidTags.WATER) && world.getBlockState(pos.above()).is(Blocks.WATER);
+ return ((reason == MobSpawnType.SPAWNER && world.getMinecraftWorld().purpurConfig.spawnerFixMC238526) || (pos.getY() >= j && pos.getY() <= i)) && world.getFluidState(pos.below()).is(FluidTags.WATER) && world.getBlockState(pos.above()).is(Blocks.WATER); // Purpur
}
}
diff --git a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
index 38d13eb230cfb33a450b8a9a1a3c6aa2efe5b053..db1e6276243ee849757bed15f8308474afe56790 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
@@ -998,8 +998,10 @@ public class PurpurWorldConfig {
}
public boolean spawnerDeactivateByRedstone = false;
+ public boolean spawnerFixMC238526 = false;
private void spawnerSettings() {
spawnerDeactivateByRedstone = getBoolean("blocks.spawner.deactivate-by-redstone", spawnerDeactivateByRedstone);
+ spawnerFixMC238526 = getBoolean("blocks.spawner.fix-mc-238526", spawnerFixMC238526);
}
public int spongeAbsorptionArea = 65;

View File

@@ -0,0 +1,59 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: BillyGalbreath <Blake.Galbreath@Gmail.com>
Date: Tue, 8 Feb 2022 13:35:48 -0600
Subject: [PATCH] Config for mob last hurt by player time
diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java
index 11761085514d54e23fece41a408b74a2bde3effc..9e07866c6597b62eb02985770c1fcffe6fb3f601 100644
--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java
+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java
@@ -1526,13 +1526,13 @@ public abstract class LivingEntity extends Entity implements Attackable {
if (entity1 instanceof net.minecraft.world.entity.player.Player) {
net.minecraft.world.entity.player.Player entityhuman = (net.minecraft.world.entity.player.Player) entity1;
- this.lastHurtByPlayerTime = 100;
+ this.lastHurtByPlayerTime = this.level().purpurConfig.mobLastHurtByPlayerTime; // Purpur
this.lastHurtByPlayer = entityhuman;
} else if (entity1 instanceof Wolf) {
Wolf entitywolf = (Wolf) entity1;
if (entitywolf.isTame()) {
- this.lastHurtByPlayerTime = 100;
+ this.lastHurtByPlayerTime = this.level().purpurConfig.mobLastHurtByPlayerTime; // Purpur
LivingEntity entityliving2 = entitywolf.getOwner();
if (entityliving2 instanceof net.minecraft.world.entity.player.Player) {
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
index 5ca34447926510f1d4c5c5ba9eb3c7c6369a85de..4e11a5eb37998deba9eea2663ac2c7fb92de8acc 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
@@ -453,7 +453,7 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity {
net.minecraft.server.level.ServerPlayer entityPlayer = killer == null ? null : ((CraftPlayer) killer).getHandle();
getHandle().lastHurtByPlayer = entityPlayer;
getHandle().lastHurtByMob = entityPlayer;
- getHandle().lastHurtByPlayerTime = entityPlayer == null ? 0 : 100; // 100 value taken from EntityLiving#damageEntity
+ getHandle().lastHurtByPlayerTime = entityPlayer == null ? 0 : getHandle().level().purpurConfig.mobLastHurtByPlayerTime; // 100 value taken from EntityLiving#damageEntity // Purpur
}
// Paper end
diff --git a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
index db1e6276243ee849757bed15f8308474afe56790..a5e9e56c86de0ae3b8053367dac777c94a990a30 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
@@ -142,6 +142,7 @@ public class PurpurWorldConfig {
public boolean mobsIgnoreRails = false;
public boolean rainStopsAfterSleep = true;
public boolean thunderStopsAfterSleep = true;
+ public int mobLastHurtByPlayerTime = 100;
private void miscGameplayMechanicsSettings() {
useBetterMending = getBoolean("gameplay-mechanics.use-better-mending", useBetterMending);
alwaysTameInCreative = getBoolean("gameplay-mechanics.always-tame-in-creative", alwaysTameInCreative);
@@ -167,6 +168,7 @@ public class PurpurWorldConfig {
mobsIgnoreRails = getBoolean("gameplay-mechanics.mobs-ignore-rails", mobsIgnoreRails);
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);
}
public int daytimeTicks = 12000;

View File

@@ -0,0 +1,83 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: 12emin34 <macanovic.emin@gmail.com>
Date: Sat, 12 Feb 2022 01:08:18 +0100
Subject: [PATCH] Anvil repair/damage options
diff --git a/src/main/java/net/minecraft/world/level/block/AnvilBlock.java b/src/main/java/net/minecraft/world/level/block/AnvilBlock.java
index 5c5a3b169795bf8a527b316c666cbc2105c66622..020afeca950d2c7fb6c7b179d424548fd90f8b0d 100644
--- a/src/main/java/net/minecraft/world/level/block/AnvilBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/AnvilBlock.java
@@ -55,6 +55,54 @@ public class AnvilBlock extends FallingBlock {
@Override
public InteractionResult use(BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) {
+ // Purpur start - repairable/damageable anvils
+ if (world.purpurConfig.anvilRepairIngotsAmount > 0) {
+ net.minecraft.world.item.ItemStack itemstack = player.getItemInHand(hand);
+ if (itemstack.is(net.minecraft.world.item.Items.IRON_INGOT)) {
+ if (itemstack.getCount() < world.purpurConfig.anvilRepairIngotsAmount) {
+ // not enough iron ingots, play "error" sound and consume
+ world.playSound(null, pos, net.minecraft.sounds.SoundEvents.ANVIL_HIT, net.minecraft.sounds.SoundSource.BLOCKS, 1.0F, 1.0F);
+ return InteractionResult.CONSUME;
+ }
+ if (state.is(Blocks.DAMAGED_ANVIL)) {
+ world.setBlock(pos, Blocks.CHIPPED_ANVIL.defaultBlockState().setValue(FACING, state.getValue(FACING)), 3);
+ } else if (state.is(Blocks.CHIPPED_ANVIL)) {
+ world.setBlock(pos, Blocks.ANVIL.defaultBlockState().setValue(FACING, state.getValue(FACING)), 3);
+ } else if (state.is(Blocks.ANVIL)) {
+ // anvil is already fully repaired, play "error" sound and consume
+ world.playSound(null, pos, net.minecraft.sounds.SoundEvents.ANVIL_HIT, net.minecraft.sounds.SoundSource.BLOCKS, 1.0F, 1.0F);
+ return InteractionResult.CONSUME;
+ }
+ if (!player.getAbilities().instabuild) {
+ itemstack.shrink(world.purpurConfig.anvilRepairIngotsAmount);
+ }
+ world.playSound(null, pos, net.minecraft.sounds.SoundEvents.ANVIL_PLACE, net.minecraft.sounds.SoundSource.BLOCKS, 1.0F, 1.0F);
+ return InteractionResult.CONSUME;
+ }
+ }
+ if (world.purpurConfig.anvilDamageObsidianAmount > 0) {
+ net.minecraft.world.item.ItemStack itemstack = player.getItemInHand(hand);
+ if (itemstack.is(net.minecraft.world.item.Items.OBSIDIAN)) {
+ if (itemstack.getCount() < world.purpurConfig.anvilDamageObsidianAmount) {
+ // not enough obsidian, play "error" sound and consume
+ world.playSound(null, pos, net.minecraft.sounds.SoundEvents.ANVIL_HIT, net.minecraft.sounds.SoundSource.BLOCKS, 1.0F, 1.0F);
+ return InteractionResult.CONSUME;
+ }
+ if (state.is(Blocks.DAMAGED_ANVIL)) {
+ world.destroyBlock(pos, false);
+ } else if (state.is(Blocks.CHIPPED_ANVIL)) {
+ world.setBlock(pos, Blocks.DAMAGED_ANVIL.defaultBlockState().setValue(FACING, state.getValue(FACING)), 3);
+ } else if (state.is(Blocks.ANVIL)) {
+ world.setBlock(pos, Blocks.CHIPPED_ANVIL.defaultBlockState().setValue(FACING, state.getValue(FACING)), 3);
+ }
+ if (!player.getAbilities().instabuild) {
+ itemstack.shrink(world.purpurConfig.anvilDamageObsidianAmount);
+ }
+ world.playSound(null, pos, net.minecraft.sounds.SoundEvents.ANVIL_LAND, net.minecraft.sounds.SoundSource.BLOCKS, 1.0F, 1.0F);
+ return InteractionResult.CONSUME;
+ }
+ }
+ // Purpur end
if (world.isClientSide) {
return InteractionResult.SUCCESS;
} else {
diff --git a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
index a5e9e56c86de0ae3b8053367dac777c94a990a30..6ae50abd3d1bb4e5ff6f8865ca6f4303c8144b0e 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
@@ -750,9 +750,13 @@ public class PurpurWorldConfig {
public boolean anvilAllowColors = false;
public boolean anvilColorsUseMiniMessage;
+ public int anvilRepairIngotsAmount = 0;
+ public int anvilDamageObsidianAmount = 0;
private void anvilSettings() {
anvilAllowColors = getBoolean("blocks.anvil.allow-colors", anvilAllowColors);
anvilColorsUseMiniMessage = getBoolean("blocks.anvil.use-mini-message", anvilColorsUseMiniMessage);
+ anvilRepairIngotsAmount = getInt("blocks.anvil.iron-ingots-used-for-repair", anvilRepairIngotsAmount);
+ anvilDamageObsidianAmount = getInt("blocks.anvil.obsidian-used-for-damage", anvilDamageObsidianAmount);
}
public double azaleaGrowthChance = 0.0D;

View File

@@ -0,0 +1,44 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: 12emin34 <macanovic.emin@gmail.com>
Date: Mon, 9 May 2022 23:18:09 +0200
Subject: [PATCH] Option to disable turtle egg trampling with feather falling
diff --git a/src/main/java/net/minecraft/world/level/block/TurtleEggBlock.java b/src/main/java/net/minecraft/world/level/block/TurtleEggBlock.java
index 8e975daca6a50c95d7fb620f2756b8bb2b7c7d6b..e23b920be6702ef6faf97b42fb8a87442707d6be 100644
--- a/src/main/java/net/minecraft/world/level/block/TurtleEggBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/TurtleEggBlock.java
@@ -211,7 +211,13 @@ public class TurtleEggBlock extends Block {
if (!(entity instanceof LivingEntity)) {
return false;
}
- if (entity instanceof Player) return true;
+ if (world.purpurConfig.turtleEggsTramplingFeatherFalling) {
+ java.util.Iterator<ItemStack> armor = entity.getArmorSlots().iterator();
+ return !armor.hasNext() || net.minecraft.world.item.enchantment.EnchantmentHelper.getItemEnchantmentLevel(net.minecraft.world.item.enchantment.Enchantments.FALL_PROTECTION, armor.next()) < (int) entity.fallDistance;
+ }
+ if (entity instanceof Player) {
+ return true;
+ }
return world.purpurConfig.turtleEggsBypassMobGriefing || world.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING);
// Purpur end
diff --git a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
index 6ae50abd3d1bb4e5ff6f8865ca6f4303c8144b0e..ce4f8f9661c6c0d09fa517861aae80559859f09f 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
@@ -1026,12 +1026,14 @@ public class PurpurWorldConfig {
public boolean turtleEggsBreakFromMinecarts = true;
public boolean turtleEggsBypassMobGriefing = false;
public int turtleEggsRandomTickCrackChance = 500;
+ public boolean turtleEggsTramplingFeatherFalling = false;
private void turtleEggSettings() {
turtleEggsBreakFromExpOrbs = getBoolean("blocks.turtle_egg.break-from-exp-orbs", turtleEggsBreakFromExpOrbs);
turtleEggsBreakFromItems = getBoolean("blocks.turtle_egg.break-from-items", turtleEggsBreakFromItems);
turtleEggsBreakFromMinecarts = getBoolean("blocks.turtle_egg.break-from-minecarts", turtleEggsBreakFromMinecarts);
turtleEggsBypassMobGriefing = getBoolean("blocks.turtle_egg.bypass-mob-griefing", turtleEggsBypassMobGriefing);
turtleEggsRandomTickCrackChance = getInt("blocks.turtle_egg.random-tick-crack-chance", turtleEggsRandomTickCrackChance);
+ turtleEggsTramplingFeatherFalling = getBoolean("blocks.turtle_egg.feather-fall-distance-affects-trampling", turtleEggsTramplingFeatherFalling);
}
public int waterInfiniteRequiredSources = 2;

View File

@@ -0,0 +1,52 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: 12emin34 <macanovic.emin@gmail.com>
Date: Sat, 30 Apr 2022 10:32:40 +0200
Subject: [PATCH] Add toggle for enchant level clamping
diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java
index dfb2852a4fa1a8b8ffe7817c3cf63d87abaf1a82..6c7f0db683101e12ae48dc3f28d5d00ac9569e35 100644
--- a/src/main/java/net/minecraft/world/item/ItemStack.java
+++ b/src/main/java/net/minecraft/world/item/ItemStack.java
@@ -1207,7 +1207,7 @@ public final class ItemStack {
ListTag nbttaglist = this.tag.getList("Enchantments", 10);
- nbttaglist.add(EnchantmentHelper.storeEnchantment(EnchantmentHelper.getEnchantmentId(enchantment), (byte) level));
+ nbttaglist.add(EnchantmentHelper.storeEnchantment(EnchantmentHelper.getEnchantmentId(enchantment), (org.purpurmc.purpur.PurpurConfig.clampEnchantLevels) ? (byte) level : (short) level)); // Purpur
processEnchantOrder(this.tag); // Paper
}
diff --git a/src/main/java/net/minecraft/world/item/enchantment/EnchantmentHelper.java b/src/main/java/net/minecraft/world/item/enchantment/EnchantmentHelper.java
index 2048899f8e4c8211e8dde0d11148d647678009fa..1eec84e217f6dc929091fa7451cd235ef3623822 100644
--- a/src/main/java/net/minecraft/world/item/enchantment/EnchantmentHelper.java
+++ b/src/main/java/net/minecraft/world/item/enchantment/EnchantmentHelper.java
@@ -46,7 +46,7 @@ public class EnchantmentHelper {
}
public static int getEnchantmentLevel(CompoundTag nbt) {
- return Mth.clamp(nbt.getInt("lvl"), 0, 255);
+ return Mth.clamp(nbt.getInt("lvl"), 0, (org.purpurmc.purpur.PurpurConfig.clampEnchantLevels) ? 255 : 32767); // Purpur
}
@Nullable
diff --git a/src/main/java/org/purpurmc/purpur/PurpurConfig.java b/src/main/java/org/purpurmc/purpur/PurpurConfig.java
index 44e8822dae170c07e48ae016826a6710b7d7e29a..4d147845402a26957c905dd600bf0657bb7bd714 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurConfig.java
@@ -398,6 +398,7 @@ public class PurpurConfig {
public static boolean allowHigherEnchantsLevels = true;
public static boolean allowUnsafeEnchantCommand = false;
public static boolean replaceIncompatibleEnchants = false;
+ public static boolean clampEnchantLevels = true;
private static void enchantmentSettings() {
if (version < 5) {
boolean oldValue = getBoolean("settings.enchantment.allow-infinite-and-mending-together", false);
@@ -421,6 +422,7 @@ public class PurpurConfig {
allowHigherEnchantsLevels = getBoolean("settings.enchantment.anvil.allow-higher-enchants-levels", allowHigherEnchantsLevels);
allowUnsafeEnchantCommand = getBoolean("settings.enchantment.allow-unsafe-enchant-command", allowUnsafeEnchants); // allowUnsafeEnchants as default for backwards compatability
replaceIncompatibleEnchants = getBoolean("settings.enchantment.anvil.replace-incompatible-enchants", replaceIncompatibleEnchants);
+ clampEnchantLevels = getBoolean("settings.enchantment.clamp-levels", clampEnchantLevels);
}
public static boolean endermanShortHeight = false;

View File

@@ -0,0 +1,44 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: BillyGalbreath <blake.galbreath@gmail.com>
Date: Thu, 8 Dec 2022 19:13:26 -0600
Subject: [PATCH] Skip junit tests for purpur commands
diff --git a/src/test/java/io/papermc/paper/permissions/MinecraftCommandPermissionsTest.java b/src/test/java/io/papermc/paper/permissions/MinecraftCommandPermissionsTest.java
index 4f43882d930ab8816e75b216d9a61a06b79df265..40fc8b6579cc29e68720a99ac12f8adacc1d95be 100644
--- a/src/test/java/io/papermc/paper/permissions/MinecraftCommandPermissionsTest.java
+++ b/src/test/java/io/papermc/paper/permissions/MinecraftCommandPermissionsTest.java
@@ -45,6 +45,7 @@ public class MinecraftCommandPermissionsTest extends AbstractTestingBase {
Set<String> foundPerms = new HashSet<>();
for (CommandNode<CommandSourceStack> child : root.getChildren()) {
final String vanillaPerm = VanillaCommandWrapper.getPermission(child);
+ if (TO_SKIP.contains(vanillaPerm)) continue; // Purpur
if (!perms.contains(vanillaPerm)) {
missing.add("Missing permission for " + child.getName() + " (" + vanillaPerm + ") command");
} else {
@@ -57,6 +58,25 @@ public class MinecraftCommandPermissionsTest extends AbstractTestingBase {
}
private static final List<String> TO_SKIP = List.of(
+ // Purpur start
+ "minecraft.command.compass",
+ "minecraft.command.credits",
+ "minecraft.command.demo",
+ "minecraft.command.ping",
+ "minecraft.command.ram",
+ "minecraft.command.rambar",
+ "minecraft.command.tpsbar",
+ "minecraft.command.uptime",
+ "minecraft.command.debug",
+ "minecraft.command.gamemode.adventure",
+ "minecraft.command.gamemode.adventure.other",
+ "minecraft.command.gamemode.creative",
+ "minecraft.command.gamemode.creative.other",
+ "minecraft.command.gamemode.spectator",
+ "minecraft.command.gamemode.spectator.other",
+ "minecraft.command.gamemode.survival",
+ "minecraft.command.gamemode.survival.other",
+ // Purpur end
"minecraft.command.selector"
);

View File

@@ -0,0 +1,41 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: William Blake Galbreath <blake.galbreath@gmail.com>
Date: Wed, 8 Jun 2022 14:13:39 -0400
Subject: [PATCH] Implement configurable search radius for villagers to spawn
iron golems
diff --git a/src/main/java/net/minecraft/world/entity/npc/Villager.java b/src/main/java/net/minecraft/world/entity/npc/Villager.java
index d70639fef24b6a8a3b504723992a050edbc16f61..99928a3a8954be0d5b1f7736c12dbbb10d4c508c 100644
--- a/src/main/java/net/minecraft/world/entity/npc/Villager.java
+++ b/src/main/java/net/minecraft/world/entity/npc/Villager.java
@@ -1099,6 +1099,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler
}
public void spawnGolemIfNeeded(ServerLevel world, long time, int requiredCount) {
+ if (world.purpurConfig.villagerSpawnIronGolemRadius > 0 && world.getEntitiesOfClass(net.minecraft.world.entity.animal.IronGolem.class, getBoundingBox().inflate(world.purpurConfig.villagerSpawnIronGolemRadius)).size() > world.purpurConfig.villagerSpawnIronGolemLimit) return; // Purpur
if (this.wantsToSpawnGolem(time)) {
AABB axisalignedbb = this.getBoundingBox().inflate(10.0D, 10.0D, 10.0D);
List<Villager> list = world.getEntitiesOfClass(Villager.class, axisalignedbb);
diff --git a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
index ce4f8f9661c6c0d09fa517861aae80559859f09f..b964bad8d599e093ad312a9dedf1a33856ce9ec1 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
@@ -2745,6 +2745,8 @@ public class PurpurWorldConfig {
public boolean villagerLobotomizeEnabled = false;
public int villagerLobotomizeCheckInterval = 100;
public boolean villagerDisplayTradeItem = true;
+ public int villagerSpawnIronGolemRadius = 0;
+ public int villagerSpawnIronGolemLimit = 0;
private void villagerSettings() {
villagerRidable = getBoolean("mobs.villager.ridable", villagerRidable);
villagerRidableInWater = getBoolean("mobs.villager.ridable-in-water", villagerRidableInWater);
@@ -2778,6 +2780,8 @@ public class PurpurWorldConfig {
villagerLobotomizeEnabled = getBoolean("mobs.villager.lobotomize.enabled", villagerLobotomizeEnabled);
villagerLobotomizeCheckInterval = getInt("mobs.villager.lobotomize.check-interval", villagerLobotomizeCheckInterval);
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);
}
public boolean vindicatorRidable = false;

View File

@@ -0,0 +1,122 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: William Blake Galbreath <blake.galbreath@gmail.com>
Date: Wed, 8 Jun 2022 14:19:35 -0400
Subject: [PATCH] Stonecutter damage
diff --git a/src/main/java/net/minecraft/world/damagesource/CombatTracker.java b/src/main/java/net/minecraft/world/damagesource/CombatTracker.java
index 9e3608650c44ef5fa724c3aea86603d7bd02429c..8c2c515f1b5f56bf1d6cf0c35d4f0fa7b593d1a0 100644
--- a/src/main/java/net/minecraft/world/damagesource/CombatTracker.java
+++ b/src/main/java/net/minecraft/world/damagesource/CombatTracker.java
@@ -102,6 +102,8 @@ public class CombatTracker {
// Purpur start
if (damageSource.isScissors) {
return damageSource.getLocalizedDeathMessage(org.purpurmc.purpur.PurpurConfig.deathMsgRunWithScissors, this.mob);
+ } else if (damageSource.isStoneCutter) {
+ return damageSource.getLocalizedDeathMessage(org.purpurmc.purpur.PurpurConfig.deathMsgStonecutter, this.mob);
}
// Purpur end
return damageSource.getLocalizedDeathMessage(this.mob);
diff --git a/src/main/java/net/minecraft/world/damagesource/DamageSource.java b/src/main/java/net/minecraft/world/damagesource/DamageSource.java
index 33210bc66dcc5fdf03fbf438ce8734b31c4e7975..fc1fb63ee0e28b8d1f065bfad716b465cde5a69f 100644
--- a/src/main/java/net/minecraft/world/damagesource/DamageSource.java
+++ b/src/main/java/net/minecraft/world/damagesource/DamageSource.java
@@ -56,6 +56,8 @@ public class DamageSource {
public boolean isScissors; // Purpur
+ public boolean isStoneCutter; // Purpur
+
public String toString() {
return "DamageSource (" + this.type().msgId() + ")";
}
diff --git a/src/main/java/net/minecraft/world/damagesource/DamageSources.java b/src/main/java/net/minecraft/world/damagesource/DamageSources.java
index 813916852774d6482791989252ecb67b945a8f84..4a5d2e263d2bbee96bde7012d3385fa33860bc1b 100644
--- a/src/main/java/net/minecraft/world/damagesource/DamageSources.java
+++ b/src/main/java/net/minecraft/world/damagesource/DamageSources.java
@@ -273,5 +273,11 @@ public class DamageSources {
source.isScissors = true;
return source;
}
+
+ public DamageSource stonecutter() {
+ DamageSource source = new DamageSource(this.damageTypes.getHolderOrThrow(DamageTypes.MAGIC));
+ source.isStoneCutter = true;
+ return source;
+ }
// Purpur end
}
diff --git a/src/main/java/net/minecraft/world/level/block/StonecutterBlock.java b/src/main/java/net/minecraft/world/level/block/StonecutterBlock.java
index 0a95842c53a9d0286c57bcb42db97e468e30fb7d..0882e67c5cf876e0fc58a4ca4accb4be40418983 100644
--- a/src/main/java/net/minecraft/world/level/block/StonecutterBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/StonecutterBlock.java
@@ -92,4 +92,16 @@ public class StonecutterBlock extends Block {
public boolean isPathfindable(BlockState state, BlockGetter world, BlockPos pos, PathComputationType type) {
return false;
}
+
+ // Purpur start
+ @Override
+ public void stepOn(Level level, BlockPos pos, BlockState state, net.minecraft.world.entity.Entity entity) {
+ if (level.purpurConfig.stonecutterDamage > 0.0F && entity instanceof net.minecraft.world.entity.LivingEntity) {
+ org.bukkit.craftbukkit.event.CraftEventFactory.blockDamage = level.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ());
+ entity.hurt(entity.damageSources().stonecutter(), level.purpurConfig.stonecutterDamage);
+ org.bukkit.craftbukkit.event.CraftEventFactory.blockDamage = null;
+ }
+ super.stepOn(level, pos, state, entity);
+ }
+ // Purpur end
}
diff --git a/src/main/java/net/minecraft/world/level/pathfinder/WalkNodeEvaluator.java b/src/main/java/net/minecraft/world/level/pathfinder/WalkNodeEvaluator.java
index d976a6df54c1e817def2d588692abe25a03ee0fa..ba57accc272958da4714896baeadb52c99383561 100644
--- a/src/main/java/net/minecraft/world/level/pathfinder/WalkNodeEvaluator.java
+++ b/src/main/java/net/minecraft/world/level/pathfinder/WalkNodeEvaluator.java
@@ -465,7 +465,7 @@ public class WalkNodeEvaluator extends NodeEvaluator {
return BlockPathTypes.BLOCKED;
} else {
// Paper end
- if (blockState.is(Blocks.CACTUS) || blockState.is(Blocks.SWEET_BERRY_BUSH)) {
+ if (blockState.is(Blocks.CACTUS) || blockState.is(Blocks.SWEET_BERRY_BUSH) || blockState.is(Blocks.STONECUTTER)) { // Purpur
return BlockPathTypes.DANGER_OTHER;
}
@@ -498,7 +498,7 @@ public class WalkNodeEvaluator extends NodeEvaluator {
} else if (!blockState.is(BlockTags.TRAPDOORS) && !blockState.is(Blocks.LILY_PAD) && !blockState.is(Blocks.BIG_DRIPLEAF)) {
if (blockState.is(Blocks.POWDER_SNOW)) {
return BlockPathTypes.POWDER_SNOW;
- } else if (!blockState.is(Blocks.CACTUS) && !blockState.is(Blocks.SWEET_BERRY_BUSH)) {
+ } else if (!blockState.is(Blocks.CACTUS) && !blockState.is(Blocks.SWEET_BERRY_BUSH) && !blockState.is(Blocks.STONECUTTER)) { // Purpur
if (blockState.is(Blocks.HONEY_BLOCK)) {
return BlockPathTypes.STICKY_HONEY;
} else if (blockState.is(Blocks.COCOA)) {
diff --git a/src/main/java/org/purpurmc/purpur/PurpurConfig.java b/src/main/java/org/purpurmc/purpur/PurpurConfig.java
index 4d147845402a26957c905dd600bf0657bb7bd714..e78e809cc7644d5007b149d5940f8cc164a76975 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurConfig.java
@@ -209,8 +209,10 @@ public class PurpurConfig {
}
public static String deathMsgRunWithScissors = "<player> slipped and fell on their shears";
+ public static String deathMsgStonecutter = "<player> has sawed themself in half";
private static void deathMessages() {
deathMsgRunWithScissors = getString("settings.messages.death-message.run-with-scissors", deathMsgRunWithScissors);
+ deathMsgStonecutter = getString("settings.messages.death-message.stonecutter", deathMsgStonecutter);
}
public static boolean advancementOnlyBroadcastToAffectedPlayer = false;
diff --git a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
index b964bad8d599e093ad312a9dedf1a33856ce9ec1..417322e7cf09eb56acf5fc398ce2319b54c4477a 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
@@ -1021,6 +1021,11 @@ public class PurpurWorldConfig {
spongeAbsorbsWaterFromMud = getBoolean("blocks.sponge.absorbs-water-from-mud", spongeAbsorbsWaterFromMud);
}
+ public float stonecutterDamage = 0.0F;
+ private void stonecutterSettings() {
+ stonecutterDamage = (float) getDouble("blocks.stonecutter.damage", stonecutterDamage);
+ }
+
public boolean turtleEggsBreakFromExpOrbs = true;
public boolean turtleEggsBreakFromItems = true;
public boolean turtleEggsBreakFromMinecarts = true;

View File

@@ -0,0 +1,37 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Ben Kerllenevich <ben@omega24.dev>
Date: Wed, 8 Jun 2022 14:32:55 -0400
Subject: [PATCH] Configurable damage settings for magma blocks
diff --git a/src/main/java/net/minecraft/world/level/block/MagmaBlock.java b/src/main/java/net/minecraft/world/level/block/MagmaBlock.java
index 1b766045687e4dcded5cbcc50b746c55b9a34e22..be365914856593bb3c4e1945cc990786072f2953 100644
--- a/src/main/java/net/minecraft/world/level/block/MagmaBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/MagmaBlock.java
@@ -22,7 +22,7 @@ public class MagmaBlock extends Block {
@Override
public void stepOn(Level world, BlockPos pos, BlockState state, Entity entity) {
- if (!entity.isSteppingCarefully() && entity instanceof LivingEntity && !EnchantmentHelper.hasFrostWalker((LivingEntity) entity)) {
+ if ((!entity.isSteppingCarefully() || world.purpurConfig.magmaBlockDamageWhenSneaking) && entity instanceof LivingEntity && (world.purpurConfig.magmaBlockDamageWithFrostWalker || !EnchantmentHelper.hasFrostWalker((LivingEntity) entity))) { // Purpur
org.bukkit.craftbukkit.event.CraftEventFactory.blockDamage = world.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ()); // CraftBukkit
entity.hurt(world.damageSources().hotFloor(), 1.0F);
org.bukkit.craftbukkit.event.CraftEventFactory.blockDamage = null; // CraftBukkit
diff --git a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
index 417322e7cf09eb56acf5fc398ce2319b54c4477a..93e601cad7c26024fe195ee5217c8d65c1b083e4 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
@@ -952,6 +952,13 @@ public class PurpurWorldConfig {
pistonBlockPushLimit = getInt("blocks.piston.block-push-limit", pistonBlockPushLimit);
}
+ public boolean magmaBlockDamageWhenSneaking = false;
+ public boolean magmaBlockDamageWithFrostWalker = false;
+ private void magmaBlockSettings() {
+ magmaBlockDamageWhenSneaking = getBoolean("blocks.magma-block.damage-when-sneaking", magmaBlockDamageWhenSneaking);
+ magmaBlockDamageWithFrostWalker = getBoolean("blocks.magma-block.damage-with-frost-walker", magmaBlockDamageWithFrostWalker);
+ }
+
public boolean powderSnowBypassMobGriefing = false;
private void powderSnowSettings() {
powderSnowBypassMobGriefing = getBoolean("blocks.powder_snow.bypass-mob-griefing", powderSnowBypassMobGriefing);

View File

@@ -0,0 +1,39 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: William Blake Galbreath <Blake.Galbreath@GMail.com>
Date: Wed, 8 Jun 2022 15:19:41 -0400
Subject: [PATCH] Add config for snow on blue ice
diff --git a/src/main/java/net/minecraft/world/level/block/SnowLayerBlock.java b/src/main/java/net/minecraft/world/level/block/SnowLayerBlock.java
index 14e00c7feb1c051d56a3d27cd00dcef072dd771a..4952fb1aaaafb55baa0fddb389f966a120a4786c 100644
--- a/src/main/java/net/minecraft/world/level/block/SnowLayerBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/SnowLayerBlock.java
@@ -81,6 +81,12 @@ public class SnowLayerBlock extends Block {
public boolean canSurvive(BlockState state, LevelReader world, BlockPos pos) {
BlockState iblockdata1 = world.getBlockState(pos.below());
+ // Purpur start
+ if (iblockdata1.is(Blocks.BLUE_ICE) && !world.getWorldBorder().world.purpurConfig.snowOnBlueIce) {
+ return false;
+ }
+ // Purpur end
+
return iblockdata1.is(BlockTags.SNOW_LAYER_CANNOT_SURVIVE_ON) ? false : (iblockdata1.is(BlockTags.SNOW_LAYER_CAN_SURVIVE_ON) ? true : Block.isFaceFull(iblockdata1.getCollisionShape(world, pos.below()), Direction.UP) || iblockdata1.is((Block) this) && (Integer) iblockdata1.getValue(SnowLayerBlock.LAYERS) == 8);
}
diff --git a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
index 93e601cad7c26024fe195ee5217c8d65c1b083e4..ea082eed28b9d63514291a094ebd99b8670e7910 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
@@ -933,9 +933,11 @@ public class PurpurWorldConfig {
public boolean mobsSpawnOnPackedIce = true;
public boolean mobsSpawnOnBlueIce = true;
+ public boolean snowOnBlueIce = true;
private void iceSettings() {
mobsSpawnOnPackedIce = getBoolean("blocks.packed_ice.allow-mob-spawns", mobsSpawnOnPackedIce);
mobsSpawnOnBlueIce = getBoolean("blocks.blue_ice.allow-mob-spawns", mobsSpawnOnBlueIce);
+ snowOnBlueIce = getBoolean("blocks.blue_ice.allow-snow-formation", snowOnBlueIce);
}
public int lavaInfiniteRequiredSources = 2;

View File

@@ -0,0 +1,115 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Ben Kerllenevich <ben@omega24.dev>
Date: Sat, 25 Jun 2022 00:18:33 -0400
Subject: [PATCH] Skeletons eat wither roses
diff --git a/src/main/java/net/minecraft/world/entity/monster/Skeleton.java b/src/main/java/net/minecraft/world/entity/monster/Skeleton.java
index 9b43150a00d7fac85aa69f5a2dbffd0dfdae4b86..f4a47ac2c86cc95178922cce7320ba1ef5121b57 100644
--- a/src/main/java/net/minecraft/world/entity/monster/Skeleton.java
+++ b/src/main/java/net/minecraft/world/entity/monster/Skeleton.java
@@ -14,6 +14,16 @@ import net.minecraft.world.item.Items;
import net.minecraft.world.level.ItemLike;
import net.minecraft.world.level.Level;
+// Purpur start
+import net.minecraft.world.item.ItemStack;
+import net.minecraft.world.level.block.Blocks;
+import org.bukkit.craftbukkit.event.CraftEventFactory;
+import net.minecraft.world.InteractionHand;
+import net.minecraft.world.InteractionResult;
+import net.minecraft.server.level.ServerLevel;
+import net.minecraft.core.particles.ParticleTypes;
+// Purpur end
+
public class Skeleton extends AbstractSkeleton {
private static final int TOTAL_CONVERSION_TIME = 300;
@@ -174,4 +184,67 @@ public class Skeleton extends AbstractSkeleton {
}
}
+
+ // Purpur start
+ private int witherRosesFed = 0;
+
+ @Override
+ public InteractionResult mobInteract(Player player, InteractionHand hand) {
+ ItemStack stack = player.getItemInHand(hand);
+
+ if (level().purpurConfig.skeletonFeedWitherRoses > 0 && this.getType() != EntityType.WITHER_SKELETON && stack.getItem() == Blocks.WITHER_ROSE.asItem()) {
+ return this.feedWitherRose(player, stack);
+ }
+
+ return super.mobInteract(player, hand);
+ }
+
+ private InteractionResult feedWitherRose(Player player, ItemStack stack) {
+ if (++witherRosesFed < level().purpurConfig.skeletonFeedWitherRoses) {
+ if (!player.getAbilities().instabuild) {
+ stack.shrink(1);
+ }
+ return InteractionResult.CONSUME;
+ }
+
+ WitherSkeleton skeleton = EntityType.WITHER_SKELETON.create(level());
+ if (skeleton == null) {
+ return InteractionResult.PASS;
+ }
+
+ skeleton.moveTo(this.getX(), this.getY(), this.getZ(), this.getYRot(), this.getXRot());
+ skeleton.setHealth(this.getHealth());
+ skeleton.setAggressive(this.isAggressive());
+ skeleton.copyPosition(this);
+ skeleton.setYBodyRot(this.yBodyRot);
+ skeleton.setYHeadRot(this.getYHeadRot());
+ skeleton.yRotO = this.yRotO;
+ skeleton.xRotO = this.xRotO;
+
+ if (this.hasCustomName()) {
+ skeleton.setCustomName(this.getCustomName());
+ }
+
+ if (CraftEventFactory.callEntityTransformEvent(this, skeleton, org.bukkit.event.entity.EntityTransformEvent.TransformReason.INFECTION).isCancelled()) {
+ return InteractionResult.PASS;
+ }
+
+ if (!new com.destroystokyo.paper.event.entity.EntityTransformedEvent(this.getBukkitEntity(), skeleton.getBukkitEntity(), com.destroystokyo.paper.event.entity.EntityTransformedEvent.TransformedReason.INFECTED).callEvent()) {
+ return InteractionResult.PASS;
+ }
+
+ this.level().addFreshEntity(skeleton);
+ this.remove(RemovalReason.DISCARDED);
+ if (!player.getAbilities().instabuild) {
+ stack.shrink(1);
+ }
+
+ for (int i = 0; i < 15; ++i) {
+ ((ServerLevel) level()).sendParticles(((ServerLevel) level()).players(), null, ParticleTypes.HAPPY_VILLAGER,
+ getX() + random.nextFloat(), getY() + (random.nextFloat() * 2), getZ() + random.nextFloat(), 1,
+ random.nextGaussian() * 0.05D, random.nextGaussian() * 0.05D, random.nextGaussian() * 0.05D, 0, true);
+ }
+ return InteractionResult.SUCCESS;
+ }
+ // Purpur end
}
diff --git a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
index ea082eed28b9d63514291a094ebd99b8670e7910..40f127476d96b39ac107cb1d18dd08798612c952 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
@@ -2429,6 +2429,7 @@ public class PurpurWorldConfig {
public boolean skeletonTakeDamageFromWater = false;
public boolean skeletonAlwaysDropExp = false;
public double skeletonHeadVisibilityPercent = 0.5D;
+ public int skeletonFeedWitherRoses = 0;
private void skeletonSettings() {
skeletonRidable = getBoolean("mobs.skeleton.ridable", skeletonRidable);
skeletonRidableInWater = getBoolean("mobs.skeleton.ridable-in-water", skeletonRidableInWater);
@@ -2442,6 +2443,7 @@ public class PurpurWorldConfig {
skeletonTakeDamageFromWater = getBoolean("mobs.skeleton.takes-damage-from-water", skeletonTakeDamageFromWater);
skeletonAlwaysDropExp = getBoolean("mobs.skeleton.always-drop-exp", skeletonAlwaysDropExp);
skeletonHeadVisibilityPercent = getDouble("mobs.skeleton.head-visibility-percent", skeletonHeadVisibilityPercent);
+ skeletonFeedWitherRoses = getInt("mobs.skeleton.feed-wither-roses", skeletonFeedWitherRoses);
}
public boolean skeletonHorseRidableInWater = true;

View File

@@ -0,0 +1,163 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Ben Kerllenevich <ben@omega24.dev>
Date: Sat, 25 Jun 2022 08:04:06 -0400
Subject: [PATCH] Enchantment Table Persists Lapis
diff --git a/src/main/java/net/minecraft/world/inventory/EnchantmentMenu.java b/src/main/java/net/minecraft/world/inventory/EnchantmentMenu.java
index c5c509fbb915c60dfa95aac8510684d0b9f8b0ff..d604b7ec46f08993647979ed220a84842e3fe325 100644
--- a/src/main/java/net/minecraft/world/inventory/EnchantmentMenu.java
+++ b/src/main/java/net/minecraft/world/inventory/EnchantmentMenu.java
@@ -40,6 +40,12 @@ import org.bukkit.event.enchantment.PrepareItemEnchantEvent;
import org.bukkit.entity.Player;
// CraftBukkit end
+// Purpur start
+import net.minecraft.world.level.block.entity.BlockEntity;
+import net.minecraft.world.level.block.entity.EnchantmentTableBlockEntity;
+import org.bukkit.craftbukkit.entity.CraftHumanEntity;
+// Purpur end
+
public class EnchantmentMenu extends AbstractContainerMenu {
static final ResourceLocation EMPTY_SLOT_LAPIS_LAZULI = new ResourceLocation("item/empty_slot_lapis_lazuli");
@@ -74,6 +80,22 @@ public class EnchantmentMenu extends AbstractContainerMenu {
return context.getLocation();
}
// CraftBukkit end
+
+ // Purpur start
+ @Override
+ public void onClose(CraftHumanEntity who) {
+ super.onClose(who);
+
+ if (who.getHandle().level().purpurConfig.enchantmentTableLapisPersists) {
+ access.execute((level, pos) -> {
+ BlockEntity blockEntity = level.getBlockEntity(pos);
+ if (blockEntity instanceof EnchantmentTableBlockEntity enchantmentTable) {
+ enchantmentTable.setLapis(this.getItem(1).getCount());
+ }
+ });
+ }
+ }
+ // Purpur end
};
this.random = RandomSource.create();
this.enchantmentSeed = DataSlot.standalone();
@@ -99,6 +121,17 @@ public class EnchantmentMenu extends AbstractContainerMenu {
}
});
+ // Purpur start
+ access.execute((level, pos) -> {
+ if (level.purpurConfig.enchantmentTableLapisPersists) {
+ BlockEntity blockEntity = level.getBlockEntity(pos);
+ if (blockEntity instanceof EnchantmentTableBlockEntity enchantmentTable) {
+ this.getSlot(1).set(new ItemStack(Items.LAPIS_LAZULI, enchantmentTable.getLapis()));
+ }
+ }
+ });
+ // Purpur end
+
int j;
for (j = 0; j < 3; ++j) {
@@ -344,6 +377,7 @@ public class EnchantmentMenu extends AbstractContainerMenu {
public void removed(net.minecraft.world.entity.player.Player player) {
super.removed(player);
this.access.execute((world, blockposition) -> {
+ if (world.purpurConfig.enchantmentTableLapisPersists) this.getSlot(1).set(ItemStack.EMPTY); // Purpur
this.clearContainer(player, this.enchantSlots);
});
}
diff --git a/src/main/java/net/minecraft/world/level/block/EnchantmentTableBlock.java b/src/main/java/net/minecraft/world/level/block/EnchantmentTableBlock.java
index 839b7bc9392906dca384003468746963631fe095..286f34eef22a85be3fe9747dc3c3f9a7d51f437c 100644
--- a/src/main/java/net/minecraft/world/level/block/EnchantmentTableBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/EnchantmentTableBlock.java
@@ -29,6 +29,8 @@ import net.minecraft.world.level.pathfinder.PathComputationType;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.VoxelShape;
+import net.minecraft.world.Containers; // Purpur
+import net.minecraft.world.item.Items; // Purpur
public class EnchantmentTableBlock extends BaseEntityBlock {
protected static final VoxelShape SHAPE = Block.box(0.0D, 0.0D, 0.0D, 16.0D, 12.0D, 16.0D);
@@ -121,4 +123,18 @@ public class EnchantmentTableBlock extends BaseEntityBlock {
public boolean isPathfindable(BlockState state, BlockGetter world, BlockPos pos, PathComputationType type) {
return false;
}
+
+ // Purpur start
+ @Override
+ public void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean moved) {
+ BlockEntity blockEntity = level.getBlockEntity(pos);
+
+ if (level.purpurConfig.enchantmentTableLapisPersists && blockEntity instanceof EnchantmentTableBlockEntity enchantmentTable) {
+ Containers.dropItemStack(level, pos.getX(), pos.getY(), pos.getZ(), new ItemStack(Items.LAPIS_LAZULI, enchantmentTable.getLapis()));
+ level.updateNeighbourForOutputSignal(pos, this);
+ }
+
+ super.onRemove(state, level, pos, newState, moved);
+ }
+ // Purpur end
}
diff --git a/src/main/java/net/minecraft/world/level/block/entity/EnchantmentTableBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/EnchantmentTableBlockEntity.java
index 65e1381bb2d10bd212463feb602c60f8fdb9ade1..b7370e64fd0d50e8725d7d5afc30af2e8bc8455d 100644
--- a/src/main/java/net/minecraft/world/level/block/entity/EnchantmentTableBlockEntity.java
+++ b/src/main/java/net/minecraft/world/level/block/entity/EnchantmentTableBlockEntity.java
@@ -24,6 +24,7 @@ public class EnchantmentTableBlockEntity extends BlockEntity implements Nameable
public float tRot;
private static final RandomSource RANDOM = RandomSource.create();
private Component name;
+ private int lapis = 0; // Purpur
public EnchantmentTableBlockEntity(BlockPos pos, BlockState state) {
super(BlockEntityType.ENCHANTING_TABLE, pos, state);
@@ -35,6 +36,7 @@ public class EnchantmentTableBlockEntity extends BlockEntity implements Nameable
if (this.hasCustomName()) {
nbt.putString("CustomName", Component.Serializer.toJson(this.name));
}
+ nbt.putInt("Purpur.Lapis", this.lapis); // Purpur
}
@@ -44,6 +46,7 @@ public class EnchantmentTableBlockEntity extends BlockEntity implements Nameable
if (nbt.contains("CustomName", 8)) {
this.name = io.papermc.paper.util.MCUtil.getBaseComponentFromNbt("CustomName", nbt); // Paper - Catch ParseException
}
+ this.lapis = nbt.getInt("Purpur.Lapis"); // Purpur
}
@@ -117,4 +120,14 @@ public class EnchantmentTableBlockEntity extends BlockEntity implements Nameable
public Component getCustomName() {
return this.name;
}
+
+ // Purpur start
+ public int getLapis() {
+ return this.lapis;
+ }
+
+ public void setLapis(int lapis) {
+ this.lapis = lapis;
+ }
+ // Purpur
}
diff --git a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
index 40f127476d96b39ac107cb1d18dd08798612c952..9c90c8f1c6697a98049bf044ac061bb93e1a4363 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
@@ -1464,6 +1464,11 @@ public class PurpurWorldConfig {
elderGuardianAlwaysDropExp = getBoolean("mobs.elder_guardian.always-drop-exp", elderGuardianAlwaysDropExp);
}
+ public boolean enchantmentTableLapisPersists = false;
+ private void enchantmentTableSettings() {
+ enchantmentTableLapisPersists = getBoolean("blocks.enchantment-table.lapis-persists", enchantmentTableLapisPersists);
+ }
+
public boolean enderDragonRidable = false;
public boolean enderDragonRidableInWater = true;
public boolean enderDragonControllable = true;

View File

@@ -0,0 +1,127 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Ben Kerllenevich <ben@omega24.dev>
Date: Sat, 25 Jun 2022 19:40:36 -0400
Subject: [PATCH] Spark Profiler
Co-authored-by: granny <granny@purpurmc.org>
diff --git a/src/main/java/io/papermc/paper/plugin/PluginInitializerManager.java b/src/main/java/io/papermc/paper/plugin/PluginInitializerManager.java
index 89bf48fd581ee6580b91e2eb31dd532cb622df5e..e35da199be67e04c34df6bc09afd8d8122cb0487 100644
--- a/src/main/java/io/papermc/paper/plugin/PluginInitializerManager.java
+++ b/src/main/java/io/papermc/paper/plugin/PluginInitializerManager.java
@@ -102,6 +102,7 @@ public class PluginInitializerManager {
java.util.List<File> files = (java.util.List<File>) optionSet.valuesOf("add-plugin");
// Register plugins from the flag
io.papermc.paper.plugin.util.EntrypointUtil.registerProvidersFromSource(io.papermc.paper.plugin.provider.source.PluginFlagProviderSource.INSTANCE, files);
+ io.papermc.paper.plugin.util.EntrypointUtil.registerProvidersFromSource(io.papermc.paper.plugin.provider.source.SparkProviderSource.INSTANCE, new File("cache", "spark.jar").toPath()); // Purpur
}
// This will be the end of me...
diff --git a/src/main/java/io/papermc/paper/plugin/provider/source/SparkProviderSource.java b/src/main/java/io/papermc/paper/plugin/provider/source/SparkProviderSource.java
new file mode 100644
index 0000000000000000000000000000000000000000..a7d1ae53eac94bc2dcf8bc78ef1da0d3b8554736
--- /dev/null
+++ b/src/main/java/io/papermc/paper/plugin/provider/source/SparkProviderSource.java
@@ -0,0 +1,102 @@
+package io.papermc.paper.plugin.provider.source;
+
+import com.mojang.logging.LogUtils;
+import io.papermc.paper.plugin.entrypoint.Entrypoint;
+import io.papermc.paper.plugin.entrypoint.EntrypointHandler;
+import io.papermc.paper.plugin.entrypoint.LaunchEntryPointHandler;
+import io.papermc.paper.plugin.provider.PluginProvider;
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.InputStreamReader;
+import java.math.BigInteger;
+import java.net.URL;
+import java.net.URLConnection;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.StandardCopyOption;
+import java.security.MessageDigest;
+import java.util.stream.Collectors;
+import org.bukkit.plugin.java.JavaPlugin;
+import org.slf4j.Logger;
+
+public class SparkProviderSource extends FileProviderSource {
+ public static final SparkProviderSource INSTANCE = new SparkProviderSource();
+
+ private static final Logger LOGGER = LogUtils.getClassLogger();
+
+ public SparkProviderSource() {
+ super("File '%s' specified by Purpur"::formatted);
+ }
+
+ @Override
+ public void registerProviders(EntrypointHandler entrypointHandler, Path context) throws Exception {
+ // first, check if user doesn't want spark at all
+ if (Boolean.getBoolean("Purpur.IReallyDontWantSpark")) {
+ return; // boo!
+ }
+
+ // second, check if user has their own spark
+ if (hasSpark()) {
+ LOGGER.info("Purpur: Using user-provided spark plugin instead of our own.");
+ return; // let's hope it's at least the modern version :3
+ }
+
+ // you can't have errors in your code if you wrap the entire codebase in a try/catch block
+ try {
+
+ // make sure the directory exists where we want to keep spark
+ File file = context.toFile();
+ file.getParentFile().mkdirs();
+
+ boolean shouldDownload;
+
+ // check if our spark exists
+ if (!file.exists()) {
+ // it does not, so let's download it
+ shouldDownload = true;
+ } else {
+ // we have a spark file, let's see if it's up-to-date by comparing shas
+ String fileSha1 = String.format("%040x", new BigInteger(1, MessageDigest.getInstance("SHA-1").digest(Files.readAllBytes(file.toPath()))));
+ String sparkSha1;
+
+ // luck has a nifty endpoint containing the sha of the newest version
+ URLConnection urlConnection = new URL("https://sparkapi.lucko.me/download/bukkit/sha1").openConnection();
+
+ // set a reasonable timeout to prevent servers without internet from hanging for 60+ seconds on startup
+ urlConnection.setReadTimeout(5000);
+ urlConnection.setConnectTimeout(5000);
+
+ // read it
+ try (BufferedReader reader = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()))) {
+ sparkSha1 = reader.lines().collect(Collectors.joining(""));
+ }
+
+ // compare; we only download a new spark if the shas don't match
+ shouldDownload = !fileSha1.equals(sparkSha1);
+ }
+
+ // ok, finally we can download spark if we need it
+ if (shouldDownload) {
+ URLConnection urlConnection = new URL("https://sparkapi.lucko.me/download/bukkit").openConnection();
+ urlConnection.setReadTimeout(5000);
+ urlConnection.setConnectTimeout(5000);
+ Files.copy(urlConnection.getInputStream(), file.toPath(), StandardCopyOption.REPLACE_EXISTING);
+ }
+
+ // register the spark, newly downloaded or existing
+ super.registerProviders(entrypointHandler, context);
+
+ } catch (Throwable e) {
+ LOGGER.error("Purpur: Failed to download and install spark plugin", e);
+ }
+ }
+
+ private static boolean hasSpark() {
+ for (PluginProvider<JavaPlugin> provider : LaunchEntryPointHandler.INSTANCE.get(Entrypoint.PLUGIN).getRegisteredProviders()) {
+ if (provider.getMeta().getName().equalsIgnoreCase("spark")) {
+ return true;
+ }
+ }
+ return false;
+ }
+}

View File

@@ -0,0 +1,35 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: BillyGalbreath <blake.galbreath@gmail.com>
Date: Sun, 3 Jul 2022 04:13:57 -0500
Subject: [PATCH] Option to disable kick for out of order chat
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
index 70eaf9347d49924841f2cfa23932b3eadfe49c82..87e064670d336f1c3a86cdc524e2686c7ee5af72 100644
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -2336,7 +2336,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
do {
instant1 = (Instant) this.lastChatTimeStamp.get();
if (timestamp.isBefore(instant1)) {
- return false;
+ return !org.purpurmc.purpur.PurpurConfig.kickForOutOfOrderChat; // Purpur
}
} while (!this.lastChatTimeStamp.compareAndSet(instant1, timestamp));
diff --git a/src/main/java/org/purpurmc/purpur/PurpurConfig.java b/src/main/java/org/purpurmc/purpur/PurpurConfig.java
index e78e809cc7644d5007b149d5940f8cc164a76975..ed9b2f0b55229848894d9d6b401d050cb031b893 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurConfig.java
@@ -456,9 +456,11 @@ public class PurpurConfig {
public static boolean useUPnP = false;
public static boolean maxJoinsPerSecond = false;
+ public static boolean kickForOutOfOrderChat = true;
private static void networkSettings() {
useUPnP = getBoolean("settings.network.upnp-port-forwarding", useUPnP);
maxJoinsPerSecond = getBoolean("settings.network.max-joins-per-second", maxJoinsPerSecond);
+ kickForOutOfOrderChat = getBoolean("settings.network.kick-for-out-of-order-chat", kickForOutOfOrderChat);
}
public static java.util.regex.Pattern usernameValidCharactersPattern;

View File

@@ -0,0 +1,35 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Encode42 <me@encode42.dev>
Date: Mon, 4 Jul 2022 13:32:51 -0400
Subject: [PATCH] Config for sculk shrieker can_summon state
diff --git a/src/main/java/net/minecraft/world/level/block/SculkShriekerBlock.java b/src/main/java/net/minecraft/world/level/block/SculkShriekerBlock.java
index 02d01eabb9606ae8c3b76ad9fa4bb9a525e247b1..ce51fec4a874f9466f9966684c535315dbf40b9e 100644
--- a/src/main/java/net/minecraft/world/level/block/SculkShriekerBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/SculkShriekerBlock.java
@@ -130,7 +130,7 @@ public class SculkShriekerBlock extends BaseEntityBlock implements SimpleWaterlo
@Nullable
@Override
public BlockState getStateForPlacement(BlockPlaceContext ctx) {
- return (BlockState) this.defaultBlockState().setValue(SculkShriekerBlock.WATERLOGGED, ctx.getLevel().getFluidState(ctx.getClickedPos()).getType() == Fluids.WATER);
+ return (BlockState) this.defaultBlockState().setValue(SculkShriekerBlock.WATERLOGGED, ctx.getLevel().getFluidState(ctx.getClickedPos()).getType() == Fluids.WATER).setValue(SculkShriekerBlock.CAN_SUMMON, ctx.getLevel().purpurConfig.sculkShriekerCanSummonDefault); // Purpur
}
@Override
diff --git a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
index 9c90c8f1c6697a98049bf044ac061bb93e1a4363..2f7a5fd20ace3f27edc79c0f4a7bb4e4a772b3f8 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
@@ -997,6 +997,11 @@ public class PurpurWorldConfig {
fixSandDuping = getBoolean("blocks.sand.fix-duping", fixSandDuping);
}
+ public boolean sculkShriekerCanSummonDefault = false;
+ private void sculkShriekerSettings() {
+ sculkShriekerCanSummonDefault = getBoolean("blocks.sculk_shrieker.can-summon-default", sculkShriekerCanSummonDefault);
+ }
+
public boolean shulkerBoxAllowOversizedStacks = false;
private void shulkerBoxSettings() {
shulkerBoxAllowOversizedStacks = getBoolean("blocks.shulker_box.allow-oversized-stacks", shulkerBoxAllowOversizedStacks);

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 3d2b34c5a7c9b00c1164b4f89c2cbff81fc460eb..b5505e926e5cdb447de68e8eb8e46c97eb988e27 100644
--- a/src/main/java/net/minecraft/world/level/block/BaseCoralPlantTypeBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/BaseCoralPlantTypeBlock.java
@@ -35,6 +35,7 @@ public class BaseCoralPlantTypeBlock extends Block implements SimpleWaterloggedB
}
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 88faea00be60a519f56f975a5311df5e1eb3e6b8..cbb726ac367be81e27d3a86643baf7c4f0746edf 100644
--- a/src/main/java/net/minecraft/world/level/block/CoralBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/CoralBlock.java
@@ -45,6 +45,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 2f7a5fd20ace3f27edc79c0f4a7bb4e4a772b3f8..4351793923ea16e3c3fe7ed547c1236cae0e952a 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
@@ -834,6 +834,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 7aef2714791674086246ab4b5b92c8965dbfdae0..e55438768a030cdcef433782e55f0fafc4f51db1 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
@@ -2284,6 +2284,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 PersistentDataContainer getPersistentDataContainer() {
return this.persistentDataContainer;

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 e78d85a313f585ec9c7fe9895402591b7b10d6b9..28cac00d496cc6e37648dbe96ba4aea2b834cedd 100644
--- a/src/main/java/net/minecraft/world/entity/Entity.java
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
@@ -555,7 +555,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
this.bb = Entity.INITIAL_AABB;
this.stuckSpeedMultiplier = Vec3.ZERO;
this.nextStep = 1.0F;
- this.random = SHARED_RANDOM; // Paper
+ this.random = world == null || world.purpurConfig.entitySharedRandom ? SHARED_RANDOM : RandomSource.create(); // Paper // 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 88c238e492b1081d1a64a3b6f05d7baa17e5d8c9..dd7f2beabf0edad4143ac2365ac04a22edf1f75e 100644
--- a/src/main/java/net/minecraft/world/entity/animal/Squid.java
+++ b/src/main/java/net/minecraft/world/entity/animal/Squid.java
@@ -44,7 +44,7 @@ public class Squid extends WaterAnimal {
public Squid(EntityType<? extends Squid> type, Level world) {
super(type, world);
- //this.random.setSeed((long)this.getId()); // Paper - we set the random to shared, do not clobber the seed
+ if (!world.purpurConfig.entitySharedRandom) this.random.setSeed((long) this.getId()); // Paper - we set the random to shared, do not clobber the seed // 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 4351793923ea16e3c3fe7ed547c1236cae0e952a..07b8826509d158e60ee6c3c847f7855b7469325f 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
@@ -204,9 +204,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 boolean infinityWorksWithoutArrows = false;

View File

@@ -0,0 +1,35 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Ben Kerllenevich <ben@omega24.dev>
Date: Wed, 13 Jul 2022 16:27:43 -0400
Subject: [PATCH] Send client custom name of BE
diff --git a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java
index 2f19f6ac5de454845f5d13a3ebb93af625b2afc8..3431f1a00ae2918b91a6b7a449e613e6e12ff6d4 100644
--- a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java
+++ b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java
@@ -205,10 +205,24 @@ public abstract class BlockEntity {
@Nullable
public Packet<ClientGamePacketListener> getUpdatePacket() {
+ // Purpur start
+ if (this instanceof net.minecraft.world.Nameable nameable && nameable.hasCustomName()) {
+ CompoundTag nbt = this.saveWithoutMetadata();
+ nbt.remove("Items");
+ return net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket.create(this, $ -> nbt);
+ }
+ // Purpur end
return null;
}
public CompoundTag getUpdateTag() {
+ // Purpur start
+ if (this instanceof net.minecraft.world.Nameable nameable && nameable.hasCustomName()) {
+ CompoundTag nbt = this.saveWithoutMetadata();
+ nbt.remove("Items");
+ return nbt;
+ }
+ // Purpur end
return new CompoundTag();
}

View File

@@ -0,0 +1,129 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Sat, 14 May 2022 15:42:34 -0700
Subject: [PATCH] PaperPR #7822 Fix exact choice recipe book clicks
diff --git a/src/main/java/net/minecraft/world/entity/player/StackedContents.java b/src/main/java/net/minecraft/world/entity/player/StackedContents.java
index 26b236a764177ac16d53f5cbaf83d3e21d015ebc..6bc60ea5249cca9f4c1d029a2b7460fe3476e05a 100644
--- a/src/main/java/net/minecraft/world/entity/player/StackedContents.java
+++ b/src/main/java/net/minecraft/world/entity/player/StackedContents.java
@@ -41,8 +41,62 @@ public class StackedContents {
int j = Math.min(maxCount, stack.getCount());
if (this.extrasMap != null && stack.hasTag() && this.extrasMap.accountStack(stack, j)) return; // Paper - if an exact ingredient, don't include it
this.put(i, j);
+ // PaperPR start
+ if (stack.hasTag()) {
+ this.put(getExactStackingIndex(stack), j);
+ }
+ }
+
+ }
+ private static final net.minecraft.core.IdMap<ItemStack> EXACT_MATCHES_ID_MAP = new net.minecraft.core.IdMap<>() {
+ private final java.util.concurrent.atomic.AtomicInteger idCounter = new java.util.concurrent.atomic.AtomicInteger(BuiltInRegistries.ITEM.size());
+ private final it.unimi.dsi.fastutil.objects.Object2IntMap<ItemStack> itemstackToId = new it.unimi.dsi.fastutil.objects.Object2IntOpenCustomHashMap<>(new it.unimi.dsi.fastutil.Hash.Strategy<>() {
+ @Override
+ public int hashCode(ItemStack o) {
+ return java.util.Objects.hash(o.getItem(), o.getTag());
+ }
+
+ @Override
+ public boolean equals(@Nullable ItemStack a, @Nullable ItemStack b) {
+ if (a == null || b == null) {
+ return false;
+ }
+ return ItemStack.matches(a, b);
+ }
+ });
+ private final it.unimi.dsi.fastutil.ints.Int2ObjectMap<net.minecraft.world.item.ItemStack> idToItemstack = new it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap<>();
+
+ @Override
+ public int getId(ItemStack value) {
+ if (!this.itemstackToId.containsKey(value)) {
+ final int id = this.idCounter.incrementAndGet();
+ final ItemStack copy = value.copy();
+ this.itemstackToId.put(copy, id);
+ this.idToItemstack.put(id, copy);
+ return id;
+ }
+ return this.itemstackToId.getInt(value);
+ }
+
+ @Override
+ public @Nullable ItemStack byId(int index) {
+ return this.idToItemstack.get(index);
+ }
+
+ @Override
+ public int size() {
+ return this.itemstackToId.size();
+ }
+
+ @Override
+ public java.util.Iterator<net.minecraft.world.item.ItemStack> iterator() {
+ return this.idToItemstack.values().iterator();
}
+ };
+ public static int getExactStackingIndex(ItemStack stack) {
+ return EXACT_MATCHES_ID_MAP.getId(stack);
+ // PaperPR end
}
public static int getStackingIndex(ItemStack stack) {
@@ -84,6 +138,12 @@ public class StackedContents {
}
public static ItemStack fromStackingIndex(int itemId) {
+ // PaperPR start
+ if (itemId > BuiltInRegistries.ITEM.size()) {
+ final ItemStack stack = EXACT_MATCHES_ID_MAP.byId(itemId);
+ return stack == null ? ItemStack.EMPTY : stack.copy();
+ }
+ // PaperPR end
return itemId == 0 ? ItemStack.EMPTY : new ItemStack(Item.byId(itemId));
}
diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java
index 6c7f0db683101e12ae48dc3f28d5d00ac9569e35..68035cfe391b0e39a7a5f4b8b6e3275d75686070 100644
--- a/src/main/java/net/minecraft/world/item/ItemStack.java
+++ b/src/main/java/net/minecraft/world/item/ItemStack.java
@@ -114,6 +114,7 @@ import org.bukkit.event.world.StructureGrowEvent;
public final class ItemStack {
+ public boolean isExactRecipeIngredient = false; // PaperPR
public static final Codec<ItemStack> CODEC = RecordCodecBuilder.create((instance) -> {
return instance.group(BuiltInRegistries.ITEM.byNameCodec().fieldOf("id").forGetter(ItemStack::getItem), Codec.INT.fieldOf("Count").forGetter(ItemStack::getCount), CompoundTag.CODEC.optionalFieldOf("tag").forGetter((itemstack) -> {
return Optional.ofNullable(itemstack.getTag());
diff --git a/src/main/java/net/minecraft/world/item/crafting/Ingredient.java b/src/main/java/net/minecraft/world/item/crafting/Ingredient.java
index 3532db21cee82c18f95c540d24b2071585d71c4e..ae98a5b49b5eb7b9b2846d1e41b5665c725198a2 100644
--- a/src/main/java/net/minecraft/world/item/crafting/Ingredient.java
+++ b/src/main/java/net/minecraft/world/item/crafting/Ingredient.java
@@ -57,7 +57,11 @@ public final class Ingredient implements Predicate<ItemStack> {
if (this.itemStacks == null) {
this.itemStacks = (ItemStack[]) Arrays.stream(this.values).flatMap((recipeitemstack_provider) -> {
return recipeitemstack_provider.getItems().stream();
- }).distinct().toArray((i) -> {
+ // PaperPR start
+ }).distinct().peek(stack -> {
+ stack.isExactRecipeIngredient = this.exact;
+ }).toArray((i) -> {
+ // PaperPR end
return new ItemStack[i];
});
}
@@ -112,7 +116,13 @@ public final class Ingredient implements Predicate<ItemStack> {
for (int j = 0; j < i; ++j) {
ItemStack itemstack = aitemstack1[j];
+ // PaperPR start
+ if (itemstack.isExactRecipeIngredient) {
+ this.stackingIds.add(StackedContents.getExactStackingIndex(itemstack));
+ } else {
+ // PaperPR end
this.stackingIds.add(StackedContents.getStackingIndex(itemstack));
+ } // PaperPR
}
this.stackingIds.sort(IntComparators.NATURAL_COMPARATOR);

View File

@@ -0,0 +1,27 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: BillyGalbreath <blake.galbreath@gmail.com>
Date: Mon, 11 Jul 2022 20:44:19 -0500
Subject: [PATCH] Allow custom ChatDecorators
Requires NMS to utilize. I'll write an API for this once our upstreams calm down with the changes.
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
index ad403421711052faf36cb6b063997cfa90712423..e7e2c8115b1f25039965f390c927b004e8b3f630 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -2664,6 +2664,15 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
new com.google.common.util.concurrent.ThreadFactoryBuilder().setDaemon(true).setNameFormat("Async Chat Thread - #%d").setUncaughtExceptionHandler(new net.minecraft.DefaultUncaughtExceptionHandlerWithName(net.minecraft.server.MinecraftServer.LOGGER)).build()); // Paper
public ChatDecorator getChatDecorator() {
+ // Purpur start
+ return this.chatDecorator;
+ }
+ public void setChatDecorator(ChatDecorator chatDecorator) {
+ this.chatDecorator = chatDecorator;
+ }
+ private ChatDecorator chatDecorator = getPaperHardcodedChatDecorator();
+ public ChatDecorator getPaperHardcodedChatDecorator() {
+ // Purpur end
// Paper start - moved to ChatPreviewProcessor
return ChatDecorator.create((sender, commandSourceStack, message) -> {
final io.papermc.paper.adventure.ChatDecorationProcessor processor = new io.papermc.paper.adventure.ChatDecorationProcessor(this, sender, commandSourceStack, message);

View File

@@ -0,0 +1,896 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: BillyGalbreath <blake.galbreath@gmail.com>
Date: Fri, 1 Jul 2022 04:03:37 -0500
Subject: [PATCH] Remove Timings
diff --git a/src/main/java/io/papermc/paper/chunk/system/scheduling/ChunkHolderManager.java b/src/main/java/io/papermc/paper/chunk/system/scheduling/ChunkHolderManager.java
index abd0217cf0bff183c8e262edc173a53403797c1a..2519ad2884b6c09b312432b933c31476b369e599 100644
--- a/src/main/java/io/papermc/paper/chunk/system/scheduling/ChunkHolderManager.java
+++ b/src/main/java/io/papermc/paper/chunk/system/scheduling/ChunkHolderManager.java
@@ -1315,9 +1315,9 @@ public final class ChunkHolderManager {
}
public boolean processTicketUpdates() {
- co.aikar.timings.MinecraftTimings.distanceManagerTick.startTiming(); try { // Paper - add timings for distance manager
+ //co.aikar.timings.MinecraftTimings.distanceManagerTick.startTiming(); try { // Paper - add timings for distance manager // Purpur
return this.processTicketUpdates(true, true, null);
- } finally { co.aikar.timings.MinecraftTimings.distanceManagerTick.stopTiming(); } // Paper - add timings for distance manager
+ //} finally { co.aikar.timings.MinecraftTimings.distanceManagerTick.stopTiming(); } // Paper - add timings for distance manager // Purpur
}
private static final ThreadLocal<List<ChunkProgressionTask>> CURRENT_TICKET_UPDATE_SCHEDULING = new ThreadLocal<>();
diff --git a/src/main/java/io/papermc/paper/chunk/system/scheduling/NewChunkHolder.java b/src/main/java/io/papermc/paper/chunk/system/scheduling/NewChunkHolder.java
index b66a7d4aab887309579154815a0d4abf9de506b0..e6f56bc5b129699bab60db9c97c7f73b6ede2351 100644
--- a/src/main/java/io/papermc/paper/chunk/system/scheduling/NewChunkHolder.java
+++ b/src/main/java/io/papermc/paper/chunk/system/scheduling/NewChunkHolder.java
@@ -1779,7 +1779,7 @@ public final class NewChunkHolder {
boolean canSavePOI = !(chunk instanceof LevelChunk levelChunk && levelChunk.mustNotSave) && (poi != null && poi.isDirty());
boolean canSaveEntities = entities != null;
- try (co.aikar.timings.Timing ignored = this.world.timings.chunkSave.startTiming()) { // Paper
+ //try (co.aikar.timings.Timing ignored = this.world.timings.chunkSave.startTiming()) { // Paper // Purpur
if (canSaveChunk) {
canSaveChunk = this.saveChunk(chunk, unloading);
}
@@ -1793,7 +1793,7 @@ public final class NewChunkHolder {
this.lastEntityUnload = null;
}
}
- }
+ //} // Purpur
return executedUnloadTask | canSaveChunk | canSaveEntities | canSavePOI ? new SaveStat(executedUnloadTask || canSaveChunk, canSaveEntities, canSavePOI): null;
}
diff --git a/src/main/java/net/minecraft/network/protocol/PacketUtils.java b/src/main/java/net/minecraft/network/protocol/PacketUtils.java
index 9a49f5271ec1d9de17632bfffe8309cb1ba0d8b1..0be239c5c78432a6377cd7828cd49f61f8f0ac8f 100644
--- a/src/main/java/net/minecraft/network/protocol/PacketUtils.java
+++ b/src/main/java/net/minecraft/network/protocol/PacketUtils.java
@@ -49,7 +49,7 @@ public class PacketUtils {
if (MinecraftServer.getServer().hasStopped() || (listener instanceof ServerCommonPacketListenerImpl && ((ServerCommonPacketListenerImpl) listener).processedDisconnect)) return; // CraftBukkit, MC-142590
if (listener.shouldHandleMessage(packet)) {
co.aikar.timings.Timing timing = co.aikar.timings.MinecraftTimings.getPacketTiming(packet); // Paper - timings
- try (co.aikar.timings.Timing ignored = timing.startTiming()) { // Paper - timings
+ try { // Paper - timings // Purpur
packet.handle(listener);
} catch (Exception exception) {
if (exception instanceof ReportedException) {
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
index e7e2c8115b1f25039965f390c927b004e8b3f630..d4aad1e62e2473c48c35b2e4238c4f5709b2352a 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -1385,15 +1385,15 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
public void onServerExit() {}
public void tickServer(BooleanSupplier shouldKeepTicking) {
- co.aikar.timings.TimingsManager.FULL_SERVER_TICK.startTiming(); // Paper
+ //co.aikar.timings.TimingsManager.FULL_SERVER_TICK.startTiming(); // Paper // Purpur
long i = Util.getNanos();
// Paper start - move oversleep into full server tick
- isOversleep = true;MinecraftTimings.serverOversleep.startTiming();
+ //isOversleep = true;MinecraftTimings.serverOversleep.startTiming(); // Purpur
this.managedBlock(() -> {
return !this.canOversleep();
});
- isOversleep = false;MinecraftTimings.serverOversleep.stopTiming();
+ //isOversleep = false;MinecraftTimings.serverOversleep.stopTiming(); // Purpur
// Paper end
new com.destroystokyo.paper.event.server.ServerTickStartEvent(this.tickCount+1).callEvent(); // Paper
@@ -1428,9 +1428,9 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
// Paper end
io.papermc.paper.util.CachedLists.reset(); // Paper
// Paper start - move executeAll() into full server tick timing
- try (co.aikar.timings.Timing ignored = MinecraftTimings.processTasksTimer.startTiming()) {
+ //try (co.aikar.timings.Timing ignored = MinecraftTimings.processTasksTimer.startTiming()) { // Purpur
this.runAllTasks();
- }
+ //} // Purpur
// Paper end
// Paper start
long endTime = System.nanoTime();
@@ -1451,7 +1451,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
this.logTickTime(k - i);
this.profiler.pop();
org.spigotmc.WatchdogThread.tick(); // Spigot
- co.aikar.timings.TimingsManager.FULL_SERVER_TICK.stopTiming(); // Paper
+ //co.aikar.timings.TimingsManager.FULL_SERVER_TICK.stopTiming(); // Paper // Purpur
}
protected void logTickTime(long nanos) {}
@@ -1488,9 +1488,9 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
this.getPlayerList().getPlayers().forEach((entityplayer) -> {
entityplayer.connection.suspendFlushing();
});
- MinecraftTimings.bukkitSchedulerTimer.startTiming(); // Spigot // Paper
+ //MinecraftTimings.bukkitSchedulerTimer.startTiming(); // Spigot // Paper // Purpur
this.server.getScheduler().mainThreadHeartbeat(this.tickCount); // CraftBukkit
- MinecraftTimings.bukkitSchedulerTimer.stopTiming(); // Spigot // Paper
+ //MinecraftTimings.bukkitSchedulerTimer.stopTiming(); // Spigot // Paper // Purpur
// Paper start - Folia scheduler API
((io.papermc.paper.threadedregions.scheduler.FoliaGlobalRegionScheduler) Bukkit.getGlobalRegionScheduler()).tick();
getAllLevels().forEach(level -> {
@@ -1507,21 +1507,21 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
// Paper end - Folia scheduler API
io.papermc.paper.adventure.providers.ClickCallbackProviderImpl.CALLBACK_MANAGER.handleQueue(this.tickCount); // Paper
this.profiler.push("commandFunctions");
- MinecraftTimings.commandFunctionsTimer.startTiming(); // Spigot // Paper
+ //MinecraftTimings.commandFunctionsTimer.startTiming(); // Spigot // Paper // Purpur
this.getFunctions().tick();
- MinecraftTimings.commandFunctionsTimer.stopTiming(); // Spigot // Paper
+ //MinecraftTimings.commandFunctionsTimer.stopTiming(); // Spigot // Paper // Purpur
this.profiler.popPush("levels");
//Iterator iterator = this.getAllLevels().iterator(); // Paper - moved down
// CraftBukkit start
// Run tasks that are waiting on processing
- MinecraftTimings.processQueueTimer.startTiming(); // Spigot
+ //MinecraftTimings.processQueueTimer.startTiming(); // Spigot // Purpur
while (!this.processQueue.isEmpty()) {
this.processQueue.remove().run();
}
- MinecraftTimings.processQueueTimer.stopTiming(); // Spigot
+ //MinecraftTimings.processQueueTimer.stopTiming(); // Spigot // Purpur
- MinecraftTimings.timeUpdateTimer.startTiming(); // Spigot // Paper
+ //MinecraftTimings.timeUpdateTimer.startTiming(); // Spigot // Paper // Purpur
// Send time updates to everyone, it will get the right time from the world the player is in.
// Paper start - optimize time updates
for (final ServerLevel level : this.getAllLevels()) {
@@ -1541,7 +1541,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
}
}
// Paper end
- MinecraftTimings.timeUpdateTimer.stopTiming(); // Spigot // Paper
+ //MinecraftTimings.timeUpdateTimer.stopTiming(); // Spigot // Paper // Purpur
this.isIteratingOverLevels = true; // Paper
Iterator iterator = this.getAllLevels().iterator(); // Paper - move down
@@ -1566,14 +1566,14 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
this.profiler.push("tick");
try {
- worldserver.timings.doTick.startTiming(); // Spigot
+ //worldserver.timings.doTick.startTiming(); // Spigot // Purpur
worldserver.tick(shouldKeepTicking);
// Paper start
for (final io.papermc.paper.chunk.SingleThreadChunkRegionManager regionManager : worldserver.getChunkSource().chunkMap.regionManagers) {
regionManager.recalculateRegions();
}
// Paper end
- worldserver.timings.doTick.stopTiming(); // Spigot
+ //worldserver.timings.doTick.stopTiming(); // Spigot // Purpur
} catch (Throwable throwable) {
// Spigot Start
CrashReport crashreport;
@@ -1596,24 +1596,24 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
this.isIteratingOverLevels = false; // Paper
this.profiler.popPush("connection");
- MinecraftTimings.connectionTimer.startTiming(); // Spigot
+ //MinecraftTimings.connectionTimer.startTiming(); // Spigot // Purpur
this.getConnection().tick();
- MinecraftTimings.connectionTimer.stopTiming(); // Spigot
+ //MinecraftTimings.connectionTimer.stopTiming(); // Spigot // Purpur
this.profiler.popPush("players");
- MinecraftTimings.playerListTimer.startTiming(); // Spigot // Paper
+ //MinecraftTimings.playerListTimer.startTiming(); // Spigot // Paper // Purpur
this.playerList.tick();
- MinecraftTimings.playerListTimer.stopTiming(); // Spigot // Paper
+ //MinecraftTimings.playerListTimer.stopTiming(); // Spigot // Paper // Purpur
if (SharedConstants.IS_RUNNING_IN_IDE) {
GameTestTicker.SINGLETON.tick();
}
this.profiler.popPush("server gui refresh");
- MinecraftTimings.tickablesTimer.startTiming(); // Spigot // Paper
+ //MinecraftTimings.tickablesTimer.startTiming(); // Spigot // Paper // Purpur
for (int i = 0; i < this.tickables.size(); ++i) {
((Runnable) this.tickables.get(i)).run();
}
- MinecraftTimings.tickablesTimer.stopTiming(); // Spigot // Paper
+ //MinecraftTimings.tickablesTimer.stopTiming(); // Spigot // Paper // Purpur
this.profiler.popPush("send chunks");
iterator = this.playerList.getPlayers().iterator();
@@ -2810,7 +2810,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
return;
}
- co.aikar.timings.MinecraftTimings.midTickChunkTasks.startTiming();
+ //co.aikar.timings.MinecraftTimings.midTickChunkTasks.startTiming(); // Purpur
try {
for (;;) {
boolean moreTasks = this.tickMidTickTasks();
@@ -2837,7 +2837,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
}
}
} finally {
- co.aikar.timings.MinecraftTimings.midTickChunkTasks.stopTiming();
+ //co.aikar.timings.MinecraftTimings.midTickChunkTasks.stopTiming(); // Purpur
}
}
// Paper end - execute chunk tasks mid tick
diff --git a/src/main/java/net/minecraft/server/ServerFunctionManager.java b/src/main/java/net/minecraft/server/ServerFunctionManager.java
index d10abd28c522612934aada8124e5bb67a9b4e9da..a6a1b57b4327f5710e9ec5ebca35a47c11751d11 100644
--- a/src/main/java/net/minecraft/server/ServerFunctionManager.java
+++ b/src/main/java/net/minecraft/server/ServerFunctionManager.java
@@ -97,7 +97,7 @@ public class ServerFunctionManager {
} else {
int i;
- try (co.aikar.timings.Timing timing = function.getTiming().startTiming()) { // Paper
+ try /*(co.aikar.timings.Timing timing = function.getTiming().startTiming())*/ { // Paper // Purpur
this.context = new ServerFunctionManager.ExecutionContext(tracer);
i = this.context.runTopCommand(customfunction1, source);
} finally {
diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
index 7b1b34566c38d26ababfc5dafe254749ebc075ea..6656a3f4dd78270690479639c738fdd0ec7e588d 100644
--- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
+++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
@@ -519,7 +519,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface
}
public void handleConsoleInputs() {
- MinecraftTimings.serverCommandTimer.startTiming(); // Spigot
+ //MinecraftTimings.serverCommandTimer.startTiming(); // Spigot // Purpur
// Paper start - use proper queue
ConsoleInput servercommand;
while ((servercommand = this.serverCommandQueue.poll()) != null) {
@@ -536,7 +536,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface
// CraftBukkit end
}
- MinecraftTimings.serverCommandTimer.stopTiming(); // Spigot
+ //MinecraftTimings.serverCommandTimer.stopTiming(); // Spigot // Purpur
}
@Override
diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java
index dcf12bea1759d851d663896938ea101303ab63a5..3f0799cf3d9c5b9bfe3f29b1bf6cbdc9ca0fd38e 100644
--- a/src/main/java/net/minecraft/server/level/ChunkMap.java
+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
@@ -470,15 +470,15 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
protected void tick(BooleanSupplier shouldKeepTicking) {
ProfilerFiller gameprofilerfiller = this.level.getProfiler();
- try (Timing ignored = this.level.timings.poiUnload.startTiming()) { // Paper
+ //try (Timing ignored = this.level.timings.poiUnload.startTiming()) { // Paper // Purpur
gameprofilerfiller.push("poi");
this.poiManager.tick(shouldKeepTicking);
- } // Paper
+ //} // Paper // Purpur
gameprofilerfiller.popPush("chunk_unload");
if (!this.level.noSave()) {
- try (Timing ignored = this.level.timings.chunkUnload.startTiming()) { // Paper
+ //try (Timing ignored = this.level.timings.chunkUnload.startTiming()) { // Paper // Purpur
this.processUnloads(shouldKeepTicking);
- } // Paper
+ //} // Paper // Purpur
}
gameprofilerfiller.pop();
@@ -1092,7 +1092,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
List<ServerPlayer> list = Lists.newArrayList();
List<ServerPlayer> list1 = this.level.players();
ObjectIterator objectiterator = this.entityMap.values().iterator();
- level.timings.tracker1.startTiming(); // Paper
+ //level.timings.tracker1.startTiming(); // Paper // Purpur
ChunkMap.TrackedEntity playerchunkmap_entitytracker;
@@ -1117,17 +1117,17 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
playerchunkmap_entitytracker.serverEntity.sendChanges();
}
}
- level.timings.tracker1.stopTiming(); // Paper
+ //level.timings.tracker1.stopTiming(); // Paper // Purpur
if (!list.isEmpty()) {
objectiterator = this.entityMap.values().iterator();
- level.timings.tracker2.startTiming(); // Paper
+ //level.timings.tracker2.startTiming(); // Paper // Purpur
while (objectiterator.hasNext()) {
playerchunkmap_entitytracker = (ChunkMap.TrackedEntity) objectiterator.next();
playerchunkmap_entitytracker.updatePlayers(list);
}
- level.timings.tracker2.stopTiming(); // Paper
+ //level.timings.tracker2.stopTiming(); // Paper // Purpur
}
}
diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
index 2ab16e10323982e193e647246bd116e31f17bad2..ead4d70df7f33ff984d288d14d774a4156abb4fd 100644
--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java
+++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
@@ -295,10 +295,10 @@ public class ServerChunkCache extends ChunkSource {
io.papermc.paper.chunk.system.scheduling.ChunkTaskScheduler.pushChunkWait(this.level, x1, z1); // Paper - rewrite chunk system
// Paper end
com.destroystokyo.paper.io.SyncLoadFinder.logSyncLoad(this.level, x1, z1); // Paper - sync load info
- this.level.timings.syncChunkLoad.startTiming(); // Paper
+ //this.level.timings.syncChunkLoad.startTiming(); // Paper // Purpur
chunkproviderserver_b.managedBlock(completablefuture::isDone);
io.papermc.paper.chunk.system.scheduling.ChunkTaskScheduler.popChunkWait(); // Paper - async chunk debug // Paper - rewrite chunk system
- this.level.timings.syncChunkLoad.stopTiming(); // Paper
+ //this.level.timings.syncChunkLoad.stopTiming(); // Paper // Purpur
} // Paper
ichunkaccess = (ChunkAccess) ((Either) completablefuture.join()).map((ichunkaccess1) -> {
return ichunkaccess1;
@@ -447,17 +447,17 @@ public class ServerChunkCache extends ChunkSource {
public void save(boolean flush) {
this.runDistanceManagerUpdates();
- try (co.aikar.timings.Timing timed = level.timings.chunkSaveData.startTiming()) { // Paper - Timings
+ //try (co.aikar.timings.Timing timed = level.timings.chunkSaveData.startTiming()) { // Paper - Timings // Purpur
this.chunkMap.saveAllChunks(flush);
- } // Paper - Timings
+ //} // Paper - Timings // Purpur
}
// Paper start - duplicate save, but call incremental
public void saveIncrementally() {
this.runDistanceManagerUpdates();
- try (co.aikar.timings.Timing timed = level.timings.chunkSaveData.startTiming()) { // Paper - Timings
+ //try (co.aikar.timings.Timing timed = level.timings.chunkSaveData.startTiming()) { // Paper - Timings // Purpur
this.chunkMap.saveIncrementally();
- } // Paper - Timings
+ //} // Paper - Timings // Purpur
}
// Paper end
@@ -487,22 +487,22 @@ public class ServerChunkCache extends ChunkSource {
@Override
public void tick(BooleanSupplier shouldKeepTicking, boolean tickChunks) {
this.level.getProfiler().push("purge");
- this.level.timings.doChunkMap.startTiming(); // Spigot
+ //this.level.timings.doChunkMap.startTiming(); // Spigot // Purpur
this.distanceManager.purgeStaleTickets();
this.runDistanceManagerUpdates();
- this.level.timings.doChunkMap.stopTiming(); // Spigot
+ //this.level.timings.doChunkMap.stopTiming(); // Spigot // Purpur
this.level.getProfiler().popPush("chunks");
if (tickChunks) {
- this.level.timings.chunks.startTiming(); // Paper - timings
+ //this.level.timings.chunks.startTiming(); // Paper - timings // Purpur
this.chunkMap.level.playerChunkLoader.tick(); // Paper - replace player chunk loader - this is mostly required to account for view distance changes
this.tickChunks();
- this.level.timings.chunks.stopTiming(); // Paper - timings
+ //this.level.timings.chunks.stopTiming(); // Paper - timings // Purpur
}
- this.level.timings.doChunkUnload.startTiming(); // Spigot
+ //this.level.timings.doChunkUnload.startTiming(); // Spigot // Purpur
this.level.getProfiler().popPush("unload");
this.chunkMap.tick(shouldKeepTicking);
- this.level.timings.doChunkUnload.stopTiming(); // Spigot
+ //this.level.timings.doChunkUnload.stopTiming(); // Spigot // Purpur
this.level.getProfiler().pop();
this.clearCache();
}
@@ -525,7 +525,7 @@ public class ServerChunkCache extends ChunkSource {
boolean flag1 = level.ticksPerSpawnCategory.getLong(org.bukkit.entity.SpawnCategory.ANIMAL) != 0L && worlddata.getGameTime() % level.ticksPerSpawnCategory.getLong(org.bukkit.entity.SpawnCategory.ANIMAL) == 0L; // CraftBukkit
gameprofilerfiller.push("naturalSpawnCount");
- this.level.timings.countNaturalMobs.startTiming(); // Paper - timings
+ //this.level.timings.countNaturalMobs.startTiming(); // Paper - timings // Purpur
int l = this.distanceManager.getNaturalSpawnChunkCount();
// Paper start - per player mob spawning
NaturalSpawner.SpawnState spawnercreature_d; // moved down
@@ -549,13 +549,13 @@ public class ServerChunkCache extends ChunkSource {
spawnercreature_d = NaturalSpawner.createState(l, this.level.getAllEntities(), this::getFullChunk, this.chunkMap.playerMobDistanceMap == null ? new LocalMobCapCalculator(this.chunkMap) : null, false);
}
// Paper end
- this.level.timings.countNaturalMobs.stopTiming(); // Paper - timings
+ //this.level.timings.countNaturalMobs.stopTiming(); // Paper - timings // Purpur
this.lastSpawnState = spawnercreature_d;
gameprofilerfiller.popPush("filteringLoadedChunks");
List<ServerChunkCache.ChunkAndHolder> list = Lists.newArrayListWithCapacity(l);
Iterator iterator = this.chunkMap.getChunks().iterator();
- this.level.timings.chunkTicks.startTiming(); // Paper
+ //this.level.timings.chunkTicks.startTiming(); // Paper // Purpur
while (iterator.hasNext()) {
ChunkHolder playerchunk = (ChunkHolder) iterator.next();
@@ -599,19 +599,19 @@ public class ServerChunkCache extends ChunkSource {
}
}
}
- this.level.timings.chunkTicks.stopTiming(); // Paper
+ //this.level.timings.chunkTicks.stopTiming(); // Paper // Purpur
gameprofilerfiller.popPush("customSpawners");
if (flag2) {
- try (co.aikar.timings.Timing ignored = this.level.timings.miscMobSpawning.startTiming()) { // Paper - timings
+ //try (co.aikar.timings.Timing ignored = this.level.timings.miscMobSpawning.startTiming()) { // Paper - timings // Purpur
this.level.tickCustomSpawners(this.spawnEnemies, this.spawnFriendlies);
- } // Paper - timings
+ //} // Paper - timings // Purpur
}
gameprofilerfiller.popPush("broadcast");
list.forEach((chunkproviderserver_a1) -> {
- this.level.timings.broadcastChunkUpdates.startTiming(); // Paper - timing
+ //this.level.timings.broadcastChunkUpdates.startTiming(); // Paper - timing // Purpur
chunkproviderserver_a1.holder.broadcastChanges(chunkproviderserver_a1.chunk);
- this.level.timings.broadcastChunkUpdates.stopTiming(); // Paper - timing
+ //this.level.timings.broadcastChunkUpdates.stopTiming(); // Paper - timing // Purpur
});
gameprofilerfiller.pop();
gameprofilerfiller.pop();
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
index 7ded6820b9b0b493a72e158d7a92d5062d2948ef..4cc1f2fa4453e2ba160bfd42717bd7c8c68541fe 100644
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
@@ -736,7 +736,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
this.updateSkyBrightness();
this.tickTime();
gameprofilerfiller.popPush("tickPending");
- timings.scheduledBlocks.startTiming(); // Paper
+ //timings.scheduledBlocks.startTiming(); // Paper // Purpur
if (!this.isDebug()) {
j = this.getGameTime();
gameprofilerfiller.push("blockTicks");
@@ -745,20 +745,20 @@ public class ServerLevel extends Level implements WorldGenLevel {
this.fluidTicks.tick(j, 65536, this::tickFluid);
gameprofilerfiller.pop();
}
- timings.scheduledBlocks.stopTiming(); // Paper
+ //timings.scheduledBlocks.stopTiming(); // Paper // Purpur
gameprofilerfiller.popPush("raid");
- this.timings.raids.startTiming(); // Paper - timings
+ //this.timings.raids.startTiming(); // Paper - timings // Purpur
this.raids.tick();
- this.timings.raids.stopTiming(); // Paper - timings
+ //this.timings.raids.stopTiming(); // Paper - timings // Purpur
gameprofilerfiller.popPush("chunkSource");
- this.timings.chunkProviderTick.startTiming(); // Paper - timings
+ //this.timings.chunkProviderTick.startTiming(); // Paper - timings // Purpur
this.getChunkSource().tick(shouldKeepTicking, true);
- this.timings.chunkProviderTick.stopTiming(); // Paper - timings
+ //this.timings.chunkProviderTick.stopTiming(); // Paper - timings // Purpur
gameprofilerfiller.popPush("blockEvents");
- timings.doSounds.startTiming(); // Spigot
+ //timings.doSounds.startTiming(); // Spigot // Purpur
this.runBlockEvents();
- timings.doSounds.stopTiming(); // Spigot
+ //timings.doSounds.stopTiming(); // Spigot // Purpur
this.handlingTick = false;
gameprofilerfiller.pop();
boolean flag = true || !this.players.isEmpty() || !this.getForcedChunks().isEmpty(); // CraftBukkit - this prevents entity cleanup, other issues on servers with no players
@@ -769,7 +769,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
if (flag || this.emptyTime++ < 300) {
gameprofilerfiller.push("entities");
- timings.tickEntities.startTiming(); // Spigot
+ //timings.tickEntities.startTiming(); // Spigot // Purpur
if (this.dragonFight != null) {
gameprofilerfiller.push("dragonFight");
this.dragonFight.tick();
@@ -777,7 +777,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
}
org.spigotmc.ActivationRange.activateEntities(this); // Spigot
- timings.entityTick.startTiming(); // Spigot
+ //timings.entityTick.startTiming(); // Spigot // Purpur
this.entityTickList.forEach((entity) -> {
if (!entity.isRemoved()) {
if (false && this.shouldDiscardEntity(entity)) { // CraftBukkit - We prevent spawning in general, so this butchering is not needed
@@ -804,8 +804,8 @@ public class ServerLevel extends Level implements WorldGenLevel {
}
}
});
- timings.entityTick.stopTiming(); // Spigot
- timings.tickEntities.stopTiming(); // Spigot
+ //timings.entityTick.stopTiming(); // Spigot // Purpur
+ //timings.tickEntities.stopTiming(); // Spigot // Purpur
gameprofilerfiller.pop();
this.tickBlockEntities();
}
@@ -946,7 +946,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
// Paper start - optimise random block ticking
gameprofilerfiller.popPush("tickBlocks");
- timings.chunkTicksBlocks.startTiming(); // Paper
+ //timings.chunkTicksBlocks.startTiming(); // Paper // Purpur
if (randomTickSpeed > 0) {
LevelChunkSection[] sections = chunk.getSections();
final int minSection = io.papermc.paper.util.WorldUtil.getMinSection(this);
@@ -979,7 +979,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
}
// Paper end - optimise random block ticking
- timings.chunkTicksBlocks.stopTiming(); // Paper
+ //timings.chunkTicksBlocks.stopTiming(); // Paper // Purpur
gameprofilerfiller.pop();
}
@@ -1317,8 +1317,8 @@ public class ServerLevel extends Level implements WorldGenLevel {
// Spigot end
// Paper start- timings
final boolean isActive = org.spigotmc.ActivationRange.checkIfActive(entity);
- timer = isActive ? entity.getType().tickTimer.startTiming() : entity.getType().inactiveTickTimer.startTiming(); // Paper
- try {
+ //timer = isActive ? entity.getType().tickTimer.startTiming() : entity.getType().inactiveTickTimer.startTiming(); // Paper // Purpur
+ //try { // Purpur
// Paper end - timings
entity.setOldPosAndRot();
ProfilerFiller gameprofilerfiller = this.getProfiler();
@@ -1334,7 +1334,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
entity.postTick(); // CraftBukkit
} else { entity.inactiveTick(); } // Paper - EAR 2
this.getProfiler().pop();
- } finally { timer.stopTiming(); } // Paper - timings
+ //} finally { timer.stopTiming(); } // Paper - timings // Purpur
Iterator iterator = entity.getPassengers().iterator();
while (iterator.hasNext()) {
@@ -1357,8 +1357,8 @@ public class ServerLevel extends Level implements WorldGenLevel {
if (passenger instanceof Player || this.entityTickList.contains(passenger)) {
// Paper - EAR 2
final boolean isActive = org.spigotmc.ActivationRange.checkIfActive(passenger);
- co.aikar.timings.Timing timer = isActive ? passenger.getType().passengerTickTimer.startTiming() : passenger.getType().passengerInactiveTickTimer.startTiming(); // Paper
- try {
+ //co.aikar.timings.Timing timer = isActive ? passenger.getType().passengerTickTimer.startTiming() : passenger.getType().passengerInactiveTickTimer.startTiming(); // Paper // Purpur
+ //try { // Purpur
// Paper end
passenger.setOldPosAndRot();
++passenger.tickCount;
@@ -1388,7 +1388,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
this.tickPassenger(passenger, entity2);
}
- } finally { timer.stopTiming(); }// Paper - EAR2 timings
+ //} finally { timer.stopTiming(); }// Paper - EAR2 timings // Purpur
}
} else {
passenger.stopRiding();
@@ -1408,14 +1408,14 @@ public class ServerLevel extends Level implements WorldGenLevel {
org.bukkit.Bukkit.getPluginManager().callEvent(new org.bukkit.event.world.WorldSaveEvent(getWorld()));
}
- try (co.aikar.timings.Timing ignored = this.timings.worldSave.startTiming()) {
+ //try (co.aikar.timings.Timing ignored = this.timings.worldSave.startTiming()) { // Purpur
if (doFull) {
this.saveLevelData();
}
- this.timings.worldSaveChunks.startTiming(); // Paper
+ //this.timings.worldSaveChunks.startTiming(); // Paper // Purpur
if (!this.noSave()) chunkproviderserver.saveIncrementally();
- this.timings.worldSaveChunks.stopTiming(); // Paper
+ //this.timings.worldSaveChunks.stopTiming(); // Paper // Purpur
// Copied from save()
// CraftBukkit start - moved from MinecraftServer.saveChunks
@@ -1427,7 +1427,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
this.convertable.saveDataTag(this.server.registryAccess(), this.serverLevelData, this.server.getPlayerList().getSingleplayerData());
}
// CraftBukkit end
- }
+ //} // Purpur
}
// Paper end
@@ -1441,7 +1441,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
if (!savingDisabled) {
org.bukkit.Bukkit.getPluginManager().callEvent(new org.bukkit.event.world.WorldSaveEvent(getWorld())); // CraftBukkit
- try (co.aikar.timings.Timing ignored = timings.worldSave.startTiming()) { // Paper
+ //try (co.aikar.timings.Timing ignored = timings.worldSave.startTiming()) { // Paper // Purpur // Purpur
if (progressListener != null) {
progressListener.progressStartNoAbort(Component.translatable("menu.savingLevel"));
}
@@ -1451,11 +1451,11 @@ public class ServerLevel extends Level implements WorldGenLevel {
progressListener.progressStage(Component.translatable("menu.savingChunks"));
}
- timings.worldSaveChunks.startTiming(); // Paper
+ //timings.worldSaveChunks.startTiming(); // Paper // Purpur
if (!close) chunkproviderserver.save(flush); // Paper - rewrite chunk system
if (close) chunkproviderserver.close(true); // Paper - rewrite chunk system
- timings.worldSaveChunks.stopTiming(); // Paper
- }// Paper
+ //timings.worldSaveChunks.stopTiming(); // Paper // Purpur
+ //}// Paper // Purpur
// Paper - rewrite chunk system - entity saving moved into ChunkHolder
} else if (close) { chunkproviderserver.close(false); } // Paper - rewrite chunk system
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
index 87e064670d336f1c3a86cdc524e2686c7ee5af72..9fa25455dd264ea0b58d5e1825fd88475021dea9 100644
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -2446,7 +2446,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
public void handleCommand(String s) { // Paper - private -> public
org.spigotmc.AsyncCatcher.catchOp("Command Dispatched Async: " + s); // Paper - Add async catcher
- co.aikar.timings.MinecraftTimings.playerCommandTimer.startTiming(); // Paper
+ //co.aikar.timings.MinecraftTimings.playerCommandTimer.startTiming(); // Paper // Purpur
if ( org.spigotmc.SpigotConfig.logCommands ) // Spigot
this.LOGGER.info(this.player.getScoreboardName() + " issued server command: " + s);
@@ -2456,7 +2456,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
this.cserver.getPluginManager().callEvent(event);
if (event.isCancelled()) {
- co.aikar.timings.MinecraftTimings.playerCommandTimer.stopTiming(); // Paper
+ //co.aikar.timings.MinecraftTimings.playerCommandTimer.stopTiming(); // Paper // Purpur
return;
}
@@ -2469,7 +2469,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
java.util.logging.Logger.getLogger(ServerGamePacketListenerImpl.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
return;
} finally {
- co.aikar.timings.MinecraftTimings.playerCommandTimer.stopTiming(); // Paper
+ //co.aikar.timings.MinecraftTimings.playerCommandTimer.stopTiming(); // Paper // Purpur
}
}
// CraftBukkit end
diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java
index ad4f678de4aeeb7bb3d624f44dacc2c1d5200b1e..9942ab57f883f79719dff20f666912face27d5c4 100644
--- a/src/main/java/net/minecraft/server/players/PlayerList.java
+++ b/src/main/java/net/minecraft/server/players/PlayerList.java
@@ -1249,7 +1249,7 @@ public abstract class PlayerList {
public void saveAll(int interval) {
io.papermc.paper.util.MCUtil.ensureMain("Save Players" , () -> { // Paper - Ensure main
- MinecraftTimings.savePlayers.startTiming(); // Paper
+ //MinecraftTimings.savePlayers.startTiming(); // Paper // Purpur
int numSaved = 0;
long now = MinecraftServer.currentTick;
for (int i = 0; i < this.players.size(); ++i) {
@@ -1260,7 +1260,7 @@ public abstract class PlayerList {
}
// Paper end
}
- MinecraftTimings.savePlayers.stopTiming(); // Paper
+ //MinecraftTimings.savePlayers.stopTiming(); // Paper // Purpur
return null; }); // Paper - ensure main
}
diff --git a/src/main/java/net/minecraft/world/entity/ai/behavior/Behavior.java b/src/main/java/net/minecraft/world/entity/ai/behavior/Behavior.java
index 57ef7fbba3028c28231abf7b7ae78aa019323536..651c156dc8a5aad04d461add02e22147af657d07 100644
--- a/src/main/java/net/minecraft/world/entity/ai/behavior/Behavior.java
+++ b/src/main/java/net/minecraft/world/entity/ai/behavior/Behavior.java
@@ -58,9 +58,9 @@ public abstract class Behavior<E extends LivingEntity> implements BehaviorContro
this.status = Behavior.Status.RUNNING;
int i = this.minDuration + world.getRandom().nextInt(this.maxDuration + 1 - this.minDuration);
this.endTimestamp = time + (long)i;
- this.timing.startTiming(); // Paper - behavior timings
+ //this.timing.startTiming(); // Paper - behavior timings // Purpur
this.start(world, entity, time);
- this.timing.stopTiming(); // Paper - behavior timings
+ //this.timing.stopTiming(); // Paper - behavior timings // Purpur
return true;
} else {
return false;
@@ -72,13 +72,13 @@ public abstract class Behavior<E extends LivingEntity> implements BehaviorContro
@Override
public final void tickOrStop(ServerLevel world, E entity, long time) {
- this.timing.startTiming(); // Paper - behavior timings
+ //this.timing.startTiming(); // Paper - behavior timings // Purpur
if (!this.timedOut(time) && this.canStillUse(world, entity, time)) {
this.tick(world, entity, time);
} else {
this.doStop(world, entity, time);
}
- this.timing.stopTiming(); // Paper - behavior timings
+ //this.timing.stopTiming(); // Paper - behavior timings // Purpur
}
diff --git a/src/main/java/net/minecraft/world/entity/ai/sensing/Sensor.java b/src/main/java/net/minecraft/world/entity/ai/sensing/Sensor.java
index fcdb9bde8e1605e30dde3e580491522d4b62cdc0..7094701d213c73ba47ace806962244c10fdf4dda 100644
--- a/src/main/java/net/minecraft/world/entity/ai/sensing/Sensor.java
+++ b/src/main/java/net/minecraft/world/entity/ai/sensing/Sensor.java
@@ -46,10 +46,10 @@ public abstract class Sensor<E extends LivingEntity> {
if (--this.timeToTick <= 0L) {
// Paper start - configurable sensor tick rate and timings
this.timeToTick = java.util.Objects.requireNonNullElse(world.paperConfig().tickRates.sensor.get(entity.getType(), this.configKey), this.scanRate);
- this.timing.startTiming();
+ //this.timing.startTiming(); // Purpur
// Paper end
this.doTick(world, entity);
- this.timing.stopTiming(); // Paper - sensor timings
+ //this.timing.stopTiming(); // Paper - sensor timings // Purpur
}
}
diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java
index 282ec5085a8076790d2a24e7979b36c06a9bcba0..f9db7dde74ce1277a792497d078ed272e8b23d10 100644
--- a/src/main/java/net/minecraft/world/level/Level.java
+++ b/src/main/java/net/minecraft/world/level/Level.java
@@ -1299,15 +1299,15 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
ProfilerFiller gameprofilerfiller = this.getProfiler();
gameprofilerfiller.push("blockEntities");
- timings.tileEntityPending.startTiming(); // Spigot
+ //timings.tileEntityPending.startTiming(); // Spigot // Purpur
this.tickingBlockEntities = true;
if (!this.pendingBlockEntityTickers.isEmpty()) {
this.blockEntityTickers.addAll(this.pendingBlockEntityTickers);
this.pendingBlockEntityTickers.clear();
}
- timings.tileEntityPending.stopTiming(); // Spigot
+ //timings.tileEntityPending.stopTiming(); // Spigot // Purpur
- timings.tileEntityTick.startTiming(); // Spigot
+ //timings.tileEntityTick.startTiming(); // Spigot // Purpur
// Spigot start
// Iterator iterator = this.blockEntityTickers.iterator();
int tilesThisCycle = 0;
@@ -1340,7 +1340,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
}
this.blockEntityTickers.removeAll(toRemove);
- timings.tileEntityTick.stopTiming(); // Spigot
+ //timings.tileEntityTick.stopTiming(); // Spigot // Purpur
this.tickingBlockEntities = false;
co.aikar.timings.TimingHistory.tileEntityTicks += this.blockEntityTickers.size(); // Paper
gameprofilerfiller.pop();
diff --git a/src/main/java/net/minecraft/world/level/NaturalSpawner.java b/src/main/java/net/minecraft/world/level/NaturalSpawner.java
index 64656c384863a6430e933e506d965ee628f08669..93af6e1a041a514e9b7198e0e510fa88b043439d 100644
--- a/src/main/java/net/minecraft/world/level/NaturalSpawner.java
+++ b/src/main/java/net/minecraft/world/level/NaturalSpawner.java
@@ -133,7 +133,7 @@ public final class NaturalSpawner {
public static void spawnForChunk(ServerLevel world, LevelChunk chunk, NaturalSpawner.SpawnState info, boolean spawnAnimals, boolean spawnMonsters, boolean rareSpawn) {
world.getProfiler().push("spawner");
- world.timings.mobSpawn.startTiming(); // Spigot
+ //world.timings.mobSpawn.startTiming(); // Spigot // Purpur
MobCategory[] aenumcreaturetype = NaturalSpawner.SPAWNING_CATEGORIES;
int i = aenumcreaturetype.length;
@@ -188,7 +188,7 @@ public final class NaturalSpawner {
}
}
- world.timings.mobSpawn.stopTiming(); // Spigot
+ //world.timings.mobSpawn.stopTiming(); // Spigot // Purpur
world.getProfiler().pop();
}
diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
index 7fccb874ca2de82cc652a440bd250d0d1295397d..b27e2e187f9edebdf53cfad3d410154c0751ac86 100644
--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
+++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
@@ -789,7 +789,7 @@ public class LevelChunk extends ChunkAccess {
this.chunkHolder.getEntityChunk().callEntitiesLoadEvent(); // Paper - rewrite chunk system
if (this.needsDecoration) {
- try (co.aikar.timings.Timing ignored = this.level.timings.chunkLoadPopulate.startTiming()) { // Paper
+ //try (co.aikar.timings.Timing ignored = this.level.timings.chunkLoadPopulate.startTiming()) { // Paper // Purpur
this.needsDecoration = false;
java.util.Random random = new java.util.Random();
random.setSeed(this.level.getSeed());
@@ -809,7 +809,7 @@ public class LevelChunk extends ChunkAccess {
}
}
server.getPluginManager().callEvent(new org.bukkit.event.world.ChunkPopulateEvent(bukkitChunk));
- } // Paper
+ //} // Paper // Purpur
}
}
}
@@ -1167,7 +1167,7 @@ public class LevelChunk extends ChunkAccess {
ProfilerFiller gameprofilerfiller = LevelChunk.this.level.getProfiler();
gameprofilerfiller.push(this::getType);
- this.blockEntity.tickTimer.startTiming(); // Spigot
+ //this.blockEntity.tickTimer.startTiming(); // Spigot // Purpur
BlockState iblockdata = LevelChunk.this.getBlockState(blockposition);
if (this.blockEntity.getType().isValid(iblockdata)) {
@@ -1189,7 +1189,7 @@ public class LevelChunk extends ChunkAccess {
// Paper end
// Spigot start
} finally {
- this.blockEntity.tickTimer.stopTiming();
+ //this.blockEntity.tickTimer.stopTiming(); // Purpur
// Spigot end
}
}
diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java
index 5a47a8785bc2e251d041f80a79295c43459de3bc..a4567188e2fe3f922bb6aeb71a2845d1a1be536f 100644
--- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java
+++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java
@@ -513,10 +513,10 @@ public class CraftScheduler implements BukkitScheduler {
this.runners.remove(task.getTaskId());
}
}
- MinecraftTimings.bukkitSchedulerFinishTimer.startTiming(); // Paper
+ //MinecraftTimings.bukkitSchedulerFinishTimer.startTiming(); // Paper // Purpur
this.pending.addAll(temp);
temp.clear();
- MinecraftTimings.bukkitSchedulerFinishTimer.stopTiming(); // Paper
+ //MinecraftTimings.bukkitSchedulerFinishTimer.stopTiming(); // Paper // Purpur
//this.debugHead = this.debugHead.getNextHead(currentTick); // Paper
}
@@ -559,7 +559,7 @@ public class CraftScheduler implements BukkitScheduler {
}
void parsePending() { // Paper
- if (!this.isAsyncScheduler) MinecraftTimings.bukkitSchedulerPendingTimer.startTiming(); // Paper
+ //if (!this.isAsyncScheduler) MinecraftTimings.bukkitSchedulerPendingTimer.startTiming(); // Paper // Purpur
CraftTask head = this.head;
CraftTask task = head.getNext();
CraftTask lastTask = head;
@@ -578,7 +578,7 @@ public class CraftScheduler implements BukkitScheduler {
task.setNext(null);
}
this.head = lastTask;
- if (!this.isAsyncScheduler) MinecraftTimings.bukkitSchedulerPendingTimer.stopTiming(); // Paper
+ //if (!this.isAsyncScheduler) MinecraftTimings.bukkitSchedulerPendingTimer.stopTiming(); // Paper // Purpur
}
private boolean isReady(final int currentTick) {
diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftTask.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftTask.java
index 3f45bab0e9f7b3697e6d9d1092a1e6e579f7066f..4f1cf281c4bf68c37982d390da8779dea78dab18 100644
--- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftTask.java
+++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftTask.java
@@ -96,13 +96,13 @@ public class CraftTask implements BukkitTask, Runnable { // Spigot
@Override
public void run() {
- try (Timing ignored = timings.startTiming()) { // Paper
+ //try (Timing ignored = timings.startTiming()) { // Paper // Purpur
if (this.rTask != null) {
this.rTask.run();
} else {
this.cTask.accept(this);
}
- } // Paper
+ //} // Paper // Purpur
}
long getCreatedAt() {
diff --git a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboardManager.java b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboardManager.java
index 628951be16da8f19f0e1a974a0b4efa86e873b99..af1717fe7be06e4828febc0d5737f086b9c08e08 100644
--- a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboardManager.java
+++ b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboardManager.java
@@ -115,7 +115,7 @@ public final class CraftScoreboardManager implements ScoreboardManager {
public void getScoreboardScores(ObjectiveCriteria criteria, String name, Consumer<Score> consumer) {
// Paper start - add timings for scoreboard search
// plugins leaking scoreboards will make this very expensive, let server owners debug it easily
- co.aikar.timings.MinecraftTimings.scoreboardScoreSearch.startTimingIfSync();
+ //co.aikar.timings.MinecraftTimings.scoreboardScoreSearch.startTimingIfSync(); // Purpur
try {
// Paper end - add timings for scoreboard search
for (CraftScoreboard scoreboard : this.scoreboards) {
@@ -123,7 +123,7 @@ public final class CraftScoreboardManager implements ScoreboardManager {
board.forAllObjectives(criteria, name, (score) -> consumer.accept(score));
}
} finally { // Paper start - add timings for scoreboard search
- co.aikar.timings.MinecraftTimings.scoreboardScoreSearch.stopTimingIfSync();
+ //co.aikar.timings.MinecraftTimings.scoreboardScoreSearch.stopTimingIfSync(); // Purpur
}
// Paper end - add timings for scoreboard search
}
diff --git a/src/main/java/org/spigotmc/ActivationRange.java b/src/main/java/org/spigotmc/ActivationRange.java
index bc98504b9eacd41994c234e6385f37c5d681383b..f2e7e3501ca9d1664039468b5e7dece47986fd29 100644
--- a/src/main/java/org/spigotmc/ActivationRange.java
+++ b/src/main/java/org/spigotmc/ActivationRange.java
@@ -166,7 +166,7 @@ public class ActivationRange
*/
public static void activateEntities(Level world)
{
- MinecraftTimings.entityActivationCheckTimer.startTiming();
+ //MinecraftTimings.entityActivationCheckTimer.startTiming(); // Purpur
final int miscActivationRange = world.spigotConfig.miscActivationRange;
final int raiderActivationRange = world.spigotConfig.raiderActivationRange;
final int animalActivationRange = world.spigotConfig.animalActivationRange;
@@ -227,7 +227,7 @@ public class ActivationRange
}
// Paper end
}
- MinecraftTimings.entityActivationCheckTimer.stopTiming();
+ //MinecraftTimings.entityActivationCheckTimer.stopTiming(); // Purpur
}
/**

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,36 @@
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 9fa25455dd264ea0b58d5e1825fd88475021dea9..0d79a045ae1f28f07f1b052ba014bbf372217dba 100644
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -736,6 +736,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
if (packet.getId() == this.awaitingTeleport) {
if (this.awaitingPositionFromClient == null) {
this.disconnect(Component.translatable("multiplayer.disconnect.invalid_player_movement"), org.bukkit.event.player.PlayerKickEvent.Cause.INVALID_PLAYER_MOVEMENT); // Paper - kick event cause
+ ServerGamePacketListenerImpl.LOGGER.warn("Disconnected on accept teleport packet. Was not expecting position data from client at this time"); // Purpur
return;
}
@@ -1323,8 +1324,16 @@ 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) {
this.disconnect(Component.translatable("multiplayer.disconnect.invalid_player_movement"), org.bukkit.event.player.PlayerKickEvent.Cause.INVALID_PLAYER_MOVEMENT); // Paper - kick event cause
+ ServerGamePacketListenerImpl.LOGGER.warn(String.format("Disconnected on move player packet. Invalid data: x=%b, y=%b, z=%b, yaw=%b, pitch=%b", invalidX, invalidY, invalidZ, invalidYaw, invalidPitch));
+ // Purpur end
} 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 e837500019157129007841c847d807ebae10db04..6c04c8e7776b2830ac368229da834532e8ce163e 100644
--- a/src/main/java/net/minecraft/world/entity/animal/Bee.java
+++ b/src/main/java/net/minecraft/world/entity/animal/Bee.java
@@ -807,6 +807,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);
@@ -863,6 +864,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
@@ -909,6 +911,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,153 @@
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 cb912efba182aff9e8f080aa473f78115eae8a47..8632e9cab6563b9ea0a01c2e5248ad658129d5ce 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
@@ -1543,6 +1543,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 e55438768a030cdcef433782e55f0fafc4f51db1..2b87e25c1b6627d4ccfb11f4c20c1796c897867f 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
@@ -2288,6 +2288,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 19f6bad1b81c5a5c249631b43e1f6c159dc994e0..5c23c28955ef0fc3168cf98cd625681bd896ea5f 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
@@ -3335,5 +3335,48 @@ 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;
+ FriendlyByteBuf buf = new FriendlyByteBuf(Unpooled.buffer());
+ buf.writeBlockPos(io.papermc.paper.util.MCUtil.toBlockPosition(location));
+ buf.writeInt(argb);
+ buf.writeUtf(text);
+ buf.writeInt(duration);
+ this.getHandle().connection.send(new net.minecraft.network.protocol.game.ClientboundCustomPayloadPacket(ClientboundCustomPayloadPacket.DEBUG_GAME_TEST_ADD_MARKER, buf));
+ }
+
+ @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.game.ClientboundCustomPayloadPacket(ClientboundCustomPayloadPacket.DEBUG_GAME_TEST_CLEAR, new FriendlyByteBuf(io.netty.buffer.Unpooled.buffer())));
+ }
// Purpur end
}

View File

@@ -0,0 +1,40 @@
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 ec95678e5fb3f36a35cd0e03c65184a8ee4c8609..a32ac7796c8cba94b02d854d47395cc1a513f770 100644
--- a/src/main/java/net/minecraft/world/level/NaturalSpawner.java
+++ b/src/main/java/net/minecraft/world/level/NaturalSpawner.java
@@ -260,7 +260,8 @@ 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 - diff on change
+ //Player entityhuman = (chunk instanceof LevelChunk) ? ((LevelChunk)chunk).findNearestPlayer(d0, i, d1, 576.0D, world.purpurConfig.mobSpawningIgnoreCreativePlayers ? net.minecraft.world.entity.EntitySelector.NO_CREATIVE_OR_SPECTATOR : net.minecraft.world.entity.EntitySelector.NO_SPECTATORS) : world.getNearestPlayer(d0, (double) i, d1, -1.0D, world.purpurConfig.mobSpawningIgnoreCreativePlayers); // Paper - use chunk's player cache to optimize search in range // Purpur // Purpur - TODO: Paper
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 07b8826509d158e60ee6c3c847f7855b7469325f..71d2da21e1dcf5991f9161b3fcad66247a5a4991 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
@@ -377,6 +377,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);
@@ -385,6 +386,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 f3e1fa62d9f067c0fe8aacb88bf30b01ee0562c1..28eb98d383d6846a25c29f8cd8ff211c360a56dc 100644
--- a/src/main/java/net/minecraft/world/entity/monster/AbstractSkeleton.java
+++ b/src/main/java/net/minecraft/world/entity/monster/AbstractSkeleton.java
@@ -182,7 +182,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 71d2da21e1dcf5991f9161b3fcad66247a5a4991..86340e782bbc125ec672eea855de29f90ac127de 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
@@ -2449,6 +2449,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);
@@ -2463,6 +2465,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 skeletonHorseRidableInWater = true;

View File

@@ -0,0 +1,63 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: BillyGalbreath <blake.galbreath@gmail.com>
Date: Tue, 20 Sep 2022 17:56:21 -0500
Subject: [PATCH] Allay respect item NBT
diff --git a/src/main/java/net/minecraft/world/entity/animal/allay/Allay.java b/src/main/java/net/minecraft/world/entity/animal/allay/Allay.java
index f9af021350df28f286028099d857f034bc03913b..b3e92d3fb6fbadfc6df236754123bc12ad9bc7e7 100644
--- a/src/main/java/net/minecraft/world/entity/animal/allay/Allay.java
+++ b/src/main/java/net/minecraft/world/entity/animal/allay/Allay.java
@@ -405,9 +405,31 @@ public class Allay extends PathfinderMob implements InventoryCarrier, VibrationS
@Override
public boolean wantsToPickUp(ItemStack stack) {
- ItemStack itemstack1 = this.getItemInHand(InteractionHand.MAIN_HAND);
-
- return !itemstack1.isEmpty() && this.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) && this.inventory.canAddItem(stack) && this.allayConsidersItemEqual(itemstack1, stack);
+ // Purpur start
+ if (!this.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) {
+ return false;
+ }
+ ItemStack itemStack = this.getItemInHand(InteractionHand.MAIN_HAND);
+ if (itemStack.isEmpty()) {
+ return false;
+ }
+ if (!allayConsidersItemEqual(itemStack, stack)) {
+ return false;
+ }
+ if (!this.inventory.canAddItem(stack)) {
+ return false;
+ }
+ for (String tag : this.level().purpurConfig.allayRespectNBT) {
+ if (stack.hasTag() && itemStack.hasTag()) {
+ Tag tag1 = stack.getTag().get(tag);
+ Tag tag2 = itemStack.getTag().get(tag);
+ if (!Objects.equals(tag1, tag2)) {
+ return false;
+ }
+ }
+ }
+ return true;
+ // Purpur end
}
private boolean allayConsidersItemEqual(ItemStack stack, ItemStack stack2) {
diff --git a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
index 86340e782bbc125ec672eea855de29f90ac127de..1a8a1a9bca5c2f92b87fb1a21bdff194718caa8e 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
@@ -1083,10 +1083,13 @@ public class PurpurWorldConfig {
public boolean allayRidable = false;
public boolean allayRidableInWater = true;
public boolean allayControllable = true;
+ public List<String> allayRespectNBT = new ArrayList<>();
private void allaySettings() {
allayRidable = getBoolean("mobs.allay.ridable", allayRidable);
allayRidableInWater = getBoolean("mobs.allay.ridable-in-water", allayRidableInWater);
allayControllable = getBoolean("mobs.allay.controllable", allayControllable);
+ allayRespectNBT.clear();
+ getList("mobs.allay.respect-nbt", new ArrayList<>()).forEach(key -> allayRespectNBT.add(key.toString()));
}
public boolean axolotlRidable = 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 5c23c28955ef0fc3168cf98cd625681bd896ea5f..c9c8e66fd044a7c75994eaf38ff14f94f9c5e3ae 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
@@ -3378,5 +3378,11 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
if (this.getHandle().connection == null) return;
this.getHandle().connection.send(new net.minecraft.network.protocol.game.ClientboundCustomPayloadPacket(ClientboundCustomPayloadPacket.DEBUG_GAME_TEST_CLEAR, new FriendlyByteBuf(io.netty.buffer.Unpooled.buffer())));
}
+
+ @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 9caab6541a224dc8f729a7d720eccda7bd83ed53..2fd376789bb24b14101e289733631a9a4b68fa1c 100644
--- a/src/main/java/net/minecraft/commands/Commands.java
+++ b/src/main/java/net/minecraft/commands/Commands.java
@@ -236,6 +236,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 3c44249e782d0e98689a58c719030dea2f007644..1b8325dfa185cf35bcb02e5e2485a78ef6f8c014 100644
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
@@ -277,6 +277,7 @@ public class ServerPlayer extends Player {
public boolean purpurClient = false; // Purpur
private boolean tpsBar = false; // Purpur
private boolean compassBar = false; // Purpur
+ private boolean ramBar = false; // Purpur
// Paper start - replace player chunk loader
private final java.util.concurrent.atomic.AtomicReference<io.papermc.paper.chunk.system.RegionizedPlayerChunkLoader.ViewDistances> viewDistances = new java.util.concurrent.atomic.AtomicReference<>(new io.papermc.paper.chunk.system.RegionizedPlayerChunkLoader.ViewDistances(-1, -1, -1));
@@ -562,6 +563,7 @@ public class ServerPlayer extends Player {
}
}
+ if (nbt.contains("Purpur.RamBar")) { this.ramBar = nbt.getBoolean("Purpur.RamBar"); } // Purpur
if (nbt.contains("Purpur.TPSBar")) { this.tpsBar = nbt.getBoolean("Purpur.TPSBar"); } // Purpur
if (nbt.contains("Purpur.CompassBar")) { this.compassBar = nbt.getBoolean("Purpur.CompassBar"); } // Purpur
}
@@ -630,6 +632,7 @@ public class ServerPlayer extends Player {
}
this.getBukkitEntity().setExtraData(nbt); // CraftBukkit
+ nbt.putBoolean("Purpur.RamBar", this.ramBar); // Purpur
nbt.putBoolean("Purpur.TPSBar", this.tpsBar); // Purpur
nbt.putBoolean("Purpur.CompassBar", this.compassBar); // Purpur
}
@@ -2804,5 +2807,13 @@ public class ServerPlayer extends 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 ed9b2f0b55229848894d9d6b401d050cb031b893..568bb53e91dda4804cd328a81ba12ce735c52603 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,80 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: MelnCat <melncatuwu@gmail.com>
Date: Sat, 24 Sep 2022 09:56:28 -0700
Subject: [PATCH] Add item packet serialize event
diff --git a/src/main/java/net/minecraft/network/FriendlyByteBuf.java b/src/main/java/net/minecraft/network/FriendlyByteBuf.java
index 2e395962b555bef0ce1a98e1d768e7738f011535..40f51062624161892c780ddae05e22859e2cd021 100644
--- a/src/main/java/net/minecraft/network/FriendlyByteBuf.java
+++ b/src/main/java/net/minecraft/network/FriendlyByteBuf.java
@@ -94,6 +94,8 @@ public class FriendlyByteBuf extends ByteBuf {
private static final int MAX_PUBLIC_KEY_LENGTH = 512;
private static final Gson GSON = new Gson();
+ public static boolean hasItemSerializeEvent = false; // Purpur
+
public FriendlyByteBuf(ByteBuf parent) {
this.source = parent;
}
@@ -632,6 +634,17 @@ public class FriendlyByteBuf extends ByteBuf {
this.writeBoolean(false);
} else {
this.writeBoolean(true);
+ // Purpur start
+ if (hasItemSerializeEvent) {
+ var event = new org.purpurmc.purpur.event.packet.NetworkItemSerializeEvent(stack.asBukkitCopy());
+ event.callEvent();
+ ItemStack newStack = ItemStack.fromBukkitCopy(event.getItemStack());
+ if (org.purpurmc.purpur.PurpurConfig.fixNetworkSerializedItemsInCreative && !ItemStack.matches(stack, newStack)) {
+ stack.save(newStack.getOrCreateTagElement("Purpur.OriginalItem"));
+ }
+ stack = newStack;
+ }
+ // Purpur end
Item item = stack.getItem();
this.writeId(BuiltInRegistries.ITEM, item);
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
index 94b9a2f72dbdf85a95a9b99c45a66e7044f69f2a..d20aea388a568657f233d9e8b34b208d0d2ab01e 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -1544,6 +1544,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
//MinecraftTimings.timeUpdateTimer.stopTiming(); // Spigot // Paper // Purpur
this.isIteratingOverLevels = true; // Paper
+ net.minecraft.network.FriendlyByteBuf.hasItemSerializeEvent = org.purpurmc.purpur.event.packet.NetworkItemSerializeEvent.getHandlerList().getRegisteredListeners().length > 0; // Purpur
Iterator iterator = this.getAllLevels().iterator(); // Paper - move down
while (iterator.hasNext()) {
ServerLevel worldserver = (ServerLevel) iterator.next();
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
index 0d79a045ae1f28f07f1b052ba014bbf372217dba..ee9845804d2ad59bdde78e778c28690746877541 100644
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -3361,6 +3361,12 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
}
}
}
+ // Purpur start
+ if (org.purpurmc.purpur.PurpurConfig.fixNetworkSerializedItemsInCreative) {
+ var tag = itemstack.getTagElement("Purpur.OriginalItem");
+ if (tag != null) itemstack = ItemStack.of(tag);
+ }
+ // Purpur end
boolean flag1 = packet.getSlotNum() >= 1 && packet.getSlotNum() <= 45;
boolean flag2 = itemstack.isEmpty() || itemstack.getDamageValue() >= 0 && itemstack.getCount() <= 64 && !itemstack.isEmpty();
diff --git a/src/main/java/org/purpurmc/purpur/PurpurConfig.java b/src/main/java/org/purpurmc/purpur/PurpurConfig.java
index 568bb53e91dda4804cd328a81ba12ce735c52603..62aabfc021fa3349b0ab46744a9ec78d57f058b0 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurConfig.java
@@ -563,4 +563,9 @@ public class PurpurConfig {
}
});
}
+
+ public static boolean fixNetworkSerializedItemsInCreative = false;
+ private static void fixNetworkSerializedCreativeItems() {
+ fixNetworkSerializedItemsInCreative = getBoolean("settings.fix-network-serialized-items-in-creative", fixNetworkSerializedItemsInCreative);
+ }
}

View File

@@ -0,0 +1,119 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: MelnCat <melncatuwu@gmail.com>
Date: Sat, 1 Oct 2022 11:33:15 -0700
Subject: [PATCH] Add an option to fix MC-3304 (projectile looting)
diff --git a/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java b/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java
index 9710d1cd31d263b29c80923c56134b1f8f6702b0..4063aed1a3f0bfd7351c1ec2e9684e4991cb5285 100644
--- a/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java
+++ b/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java
@@ -72,6 +72,7 @@ public abstract class AbstractArrow extends Projectile {
private IntOpenHashSet piercingIgnoreEntityIds;
@Nullable
private List<Entity> piercedAndKilledEntities;
+ public int lootingLevel; // Purpur
// Spigot Start
@Override
@@ -612,6 +613,12 @@ public abstract class AbstractArrow extends Projectile {
this.knockback = punch;
}
+ // Purpur start
+ public void setLootingLevel(int looting) {
+ this.lootingLevel = looting;
+ }
+ // Purpur end
+
public int getKnockback() {
return this.knockback;
}
diff --git a/src/main/java/net/minecraft/world/item/BowItem.java b/src/main/java/net/minecraft/world/item/BowItem.java
index 220513d3fd5645322886522ea4f6b8c55d043b3c..d45a2f49c82d00801578c34e5f5277fc5e82be87 100644
--- a/src/main/java/net/minecraft/world/item/BowItem.java
+++ b/src/main/java/net/minecraft/world/item/BowItem.java
@@ -64,6 +64,13 @@ public class BowItem extends ProjectileWeaponItem implements Vanishable {
if (EnchantmentHelper.getItemEnchantmentLevel(Enchantments.FLAMING_ARROWS, stack) > 0) {
entityarrow.setSecondsOnFire(100);
}
+ // Purpur start
+ int lootingLevel = EnchantmentHelper.getItemEnchantmentLevel(Enchantments.MOB_LOOTING, stack);
+
+ if (lootingLevel > 0) {
+ entityarrow.setLootingLevel(lootingLevel);
+ }
+ // Purpur end
// CraftBukkit start
org.bukkit.event.entity.EntityShootBowEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityShootBowEvent(entityhuman, stack, itemstack1, entityarrow, entityhuman.getUsedItemHand(), f, !flag1);
if (event.isCancelled()) {
diff --git a/src/main/java/net/minecraft/world/item/CrossbowItem.java b/src/main/java/net/minecraft/world/item/CrossbowItem.java
index 0a0f19f73a6a4e5aece7c17089dc4d31ed2a5299..2c51a73ebfd05af21b0f5d731fc9f1df77fed1a1 100644
--- a/src/main/java/net/minecraft/world/item/CrossbowItem.java
+++ b/src/main/java/net/minecraft/world/item/CrossbowItem.java
@@ -291,6 +291,14 @@ public class CrossbowItem extends ProjectileWeaponItem implements Vanishable {
entityarrow.setPierceLevel((byte) i);
}
+ // Purpur start
+ int lootingLevel = EnchantmentHelper.getItemEnchantmentLevel(Enchantments.MOB_LOOTING, crossbow);
+
+ if (lootingLevel > 0) {
+ entityarrow.setLootingLevel(lootingLevel);
+ }
+ // Purpur end
+
return entityarrow;
}
diff --git a/src/main/java/net/minecraft/world/item/TridentItem.java b/src/main/java/net/minecraft/world/item/TridentItem.java
index 6d1573161f0d8c7999f84925ba7bbf536ee9583a..c32cbe6065ecb6810f352b8a3598c21e42e60e1d 100644
--- a/src/main/java/net/minecraft/world/item/TridentItem.java
+++ b/src/main/java/net/minecraft/world/item/TridentItem.java
@@ -82,6 +82,14 @@ public class TridentItem extends Item implements Vanishable {
entitythrowntrident.pickup = AbstractArrow.Pickup.CREATIVE_ONLY;
}
+ // Purpur start
+ int lootingLevel = EnchantmentHelper.getItemEnchantmentLevel(net.minecraft.world.item.enchantment.Enchantments.MOB_LOOTING, stack);
+
+ if (lootingLevel > 0) {
+ entitythrowntrident.setLootingLevel(lootingLevel);
+ }
+ // Purpur end
+
// CraftBukkit start
// Paper start
com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent event = new com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent((org.bukkit.entity.Player) entityhuman.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(stack), (org.bukkit.entity.Projectile) entitythrowntrident.getBukkitEntity());
diff --git a/src/main/java/net/minecraft/world/level/storage/loot/functions/LootingEnchantFunction.java b/src/main/java/net/minecraft/world/level/storage/loot/functions/LootingEnchantFunction.java
index 3fb1e558c3510243c94981211f9a0e5e0ef1895b..e5177e5ffcac360f935f2139db4554c6586b551e 100644
--- a/src/main/java/net/minecraft/world/level/storage/loot/functions/LootingEnchantFunction.java
+++ b/src/main/java/net/minecraft/world/level/storage/loot/functions/LootingEnchantFunction.java
@@ -57,6 +57,13 @@ public class LootingEnchantFunction extends LootItemConditionalFunction {
if (entity instanceof LivingEntity) {
int i = EnchantmentHelper.getMobLooting((LivingEntity) entity);
+ // Purpur start
+ if (org.purpurmc.purpur.PurpurConfig.fixProjectileLootingTransfer &&
+ context.getParamOrNull(LootContextParams.DIRECT_KILLER_ENTITY)
+ instanceof net.minecraft.world.entity.projectile.AbstractArrow arrow) {
+ i = arrow.lootingLevel;
+ }
+ // Purpur end
// CraftBukkit start - use lootingModifier if set by plugin
if (context.hasParam(LootContextParams.LOOTING_MOD)) {
i = context.getParamOrNull(LootContextParams.LOOTING_MOD);
diff --git a/src/main/java/org/purpurmc/purpur/PurpurConfig.java b/src/main/java/org/purpurmc/purpur/PurpurConfig.java
index 62aabfc021fa3349b0ab46744a9ec78d57f058b0..32aaa66acc35950caec1a0b0dac9413e950b37a6 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurConfig.java
@@ -568,4 +568,9 @@ public class PurpurConfig {
private static void fixNetworkSerializedCreativeItems() {
fixNetworkSerializedItemsInCreative = getBoolean("settings.fix-network-serialized-items-in-creative", fixNetworkSerializedItemsInCreative);
}
+
+ public static boolean fixProjectileLootingTransfer = false;
+ private static void fixProjectileLootingTransfer() {
+ fixProjectileLootingTransfer = getBoolean("settings.fix-projectile-looting-transfer", fixProjectileLootingTransfer);
+ }
}

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 443bed339884f78ecda8abdbcdc9b57ea9768cc9..e46a097dc134672720bc753ec0da0a9102737d2c 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
@@ -81,7 +81,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 32aaa66acc35950caec1a0b0dac9413e950b37a6..8426be7906cd0f4df8c274aa1d113388965d8d8b 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurConfig.java
@@ -573,4 +573,19 @@ public class PurpurConfig {
private static void fixProjectileLootingTransfer() {
fixProjectileLootingTransfer = getBoolean("settings.fix-projectile-looting-transfer", fixProjectileLootingTransfer);
}
+
+ private static void blastResistanceSettings() {
+ getMap("settings.blast-resistance-overrides", Collections.emptyMap()).forEach((blockId, value) -> {
+ Block block = BuiltInRegistries.BLOCK.get(new ResourceLocation(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 e8405a57fb88e63b63baaf00645c417633bdc0f2..2b66ddafaaca17f64d1e7502dfa4d7576e3e032f 100644
--- a/src/main/java/net/minecraft/world/level/block/BedBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/BedBlock.java
@@ -173,7 +173,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 cee9e07a250ed61570cf9787236308f91724f02f..65504432a13df45e895cf6ca885627014444563a 100644
--- a/src/main/java/net/minecraft/world/level/block/Block.java
+++ b/src/main/java/net/minecraft/world/level/block/Block.java
@@ -94,6 +94,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 ||
@@ -506,7 +510,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 cfbe1dae76db76cf54a4f5d72aca72d5e893859e..74cb10230d459ac9f300a9d59af504d233ac663e 100644
--- a/src/main/java/net/minecraft/world/level/block/HayBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/HayBlock.java
@@ -15,6 +15,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 8426be7906cd0f4df8c274aa1d113388965d8d8b..29dd74f28c66cce2c25dc9aa916f230cdfbe2da3 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurConfig.java
@@ -588,4 +588,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 8632e9cab6563b9ea0a01c2e5248ad658129d5ce..aea87307b318ed34e60835ba1d9420e9a0fd4d8e 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
@@ -399,6 +399,20 @@ public final class CraftServer implements Server {
this.dataPackManager = new CraftDataPackManager(this.getServer().getPackRepository());
Bukkit.setServer(this);
+ // 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 7bace36fb2c447cc2c7d07777a910c5867bbfe99..4604e63cec3c25a1257892d4c1ea9db098815b93 100644
--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java
+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java
@@ -1125,6 +1125,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().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 6986fcbe67e55c4942d13b2af39bd6293bf993a9..d8a4b1aaa180fc0c837bc0d8efab781a578898a5 100644
--- a/src/main/java/net/minecraft/world/entity/npc/WanderingTrader.java
+++ b/src/main/java/net/minecraft/world/entity/npc/WanderingTrader.java
@@ -114,7 +114,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 1a8a1a9bca5c2f92b87fb1a21bdff194718caa8e..1bec2760e6ae3022dbcef1bb40d7749cf3b0609e 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
@@ -128,6 +128,7 @@ public class PurpurWorldConfig {
public boolean fireballsBypassMobGriefing = false;
public boolean imposeTeleportRestrictionsOnGateways = false;
public boolean milkCuresBadOmen = true;
+ public boolean milkClearsBeneficialEffects = true;
public boolean noteBlockIgnoreAbove = false;
public boolean persistentDroppableEntityDisplayNames = true;
public boolean persistentTileEntityDisplayNames = false;
@@ -154,6 +155,7 @@ public class PurpurWorldConfig {
fireballsBypassMobGriefing = getBoolean("gameplay-mechanics.fireballs-bypass-mob-griefing", fireballsBypassMobGriefing);
imposeTeleportRestrictionsOnGateways = getBoolean("gameplay-mechanics.impose-teleport-restrictions-on-gateways", imposeTeleportRestrictionsOnGateways);
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);
persistentTileEntityDisplayNames = getBoolean("gameplay-mechanics.persistent-tileentity-display-names-and-lore", persistentTileEntityDisplayNames);
persistentDroppableEntityDisplayNames = getBoolean("gameplay-mechanics.persistent-droppable-entity-display-names", persistentDroppableEntityDisplayNames);

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 87fb10096fc9dade33c663234b1cecc34d3d77bb..874c7b29a261b1b5ad6e86ca219ff935870aecb0 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
@@ -119,9 +119,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 29dd74f28c66cce2c25dc9aa916f230cdfbe2da3..cf0a52a037ac255c3f9e36dbff3cedda0fd8f49e 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurConfig.java
@@ -465,11 +465,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 e241ae250f4f04a17ef2c583d00b065a4ca56a4c..7b99c3446b50939241d3e220d93e05649f72a6df 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 1bec2760e6ae3022dbcef1bb40d7749cf3b0609e..c04befc0e4d97497087bc8961daefe814e199a84 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
@@ -1357,6 +1357,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);
@@ -1375,6 +1376,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 6e0331818ef68fa355e3c27dc3e362b82d1c6e3a..5fa044b03f0a08d1e17b9002255e2e6438fa79c8 100644
--- a/src/main/java/net/minecraft/world/entity/Entity.java
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
@@ -417,6 +417,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
public boolean freezeLocked = false; // Paper - Freeze Tick Lock API
public boolean collidingWithWorldBorder; // Paper
public boolean fixedPose = false; // Paper
+ public @Nullable Boolean immuneToFire = null; // Purpur - Fire immune API
public void setOrigin(@javax.annotation.Nonnull Location location) {
this.origin = location.toVector();
@@ -1767,7 +1768,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
}
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) {
@@ -2441,6 +2442,11 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
nbt.putBoolean("Paper.FreezeLock", true);
}
// Paper end
+ // Purpur start
+ if (immuneToFire != null) {
+ nbt.putBoolean("Purpur.FireImmune", immuneToFire);
+ }
+ // Purpur end
return nbt;
} catch (Throwable throwable) {
CrashReport crashreport = CrashReport.forThrowable(throwable, "Saving entity NBT");
@@ -2609,6 +2615,11 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
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 431e3cedde33b33202be1d44bf066323997f21f8..236d753266943d8c64e1329336d28c50109d0886 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
@@ -223,6 +223,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 8fcee0e426cd598ddfd7e12df4382d57d2016780..4ffb4046b63cbc140c76721f51c9a7a09e81844d 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java
@@ -176,9 +176,14 @@ public class CraftItem extends CraftEntity implements Item {
return item.immuneToExplosion;
}
+ @Override
+ public void setImmuneToFire(@org.jetbrains.annotations.Nullable Boolean immuneToFire) {
+ item.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 5fa044b03f0a08d1e17b9002255e2e6438fa79c8..84643f0dd71530a5f18557f299d7725a8f53666e 100644
--- a/src/main/java/net/minecraft/world/entity/Entity.java
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
@@ -872,6 +872,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
&& this.level.paperConfig().environment.netherCeilingVoidDamageHeight.test(v -> this.getY() >= v)
&& (!(this instanceof Player player) || !player.getAbilities().invulnerable))) {
// Paper end
+ 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 c04befc0e4d97497087bc8961daefe814e199a84..443871290764e6863509acd0847f8c4c8f8566b6 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
@@ -417,6 +417,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 playerFixStuckPortal = false;
public boolean creativeOnePunch = false;
@@ -446,6 +447,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);
playerFixStuckPortal = getBoolean("gameplay-mechanics.player.fix-stuck-in-portal", playerFixStuckPortal);
creativeOnePunch = getBoolean("gameplay-mechanics.player.one-punch-in-creative", creativeOnePunch);

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 976834b381a629b026e42ac0dcb3a8885d24b113..7e36739ce44656f859bf63d0a07f10c8090d0839 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 55fced3e70c7bc49306af00dcc1d92ffb83a799b..a9f69e4f880711c21ef28bd079960ef8f12da25c 100644
--- a/src/main/java/net/minecraft/world/entity/EntityType.java
+++ b/src/main/java/net/minecraft/world/entity/EntityType.java
@@ -611,6 +611,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 564d17bc460e2a04947ff9676fbf4c8b1569659c..440add62fcfa62d483409e1aecfc91591ba476c3 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
@@ -99,6 +99,7 @@ public class EndCrystal extends Entity {
}
}
// Paper end
+ 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 443871290764e6863509acd0847f8c4c8f8566b6..829f3a7542460ef71bd934ff3dea0321168a9fac 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
@@ -877,6 +877,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()))) {
@@ -904,6 +905,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 a5f9747be5503dd24abd98f11cfa8229448ca3bf..99ef8d7e3ee0ee9777d12ad825e728c38d886114 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
@@ -174,6 +174,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;
@@ -207,6 +208,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;
@@ -226,7 +230,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
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 829f3a7542460ef71bd934ff3dea0321168a9fac..78e8043f85f65e81db0d4192fbe93df952849490 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
@@ -776,11 +776,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,58 @@
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 ccbfcef3e83b1bef364447657bfd08a92d615cf6..aa2331c6df4e79d4bb0add071a0b11d2a3a08b88 100644
--- a/src/main/java/net/minecraft/world/damagesource/CombatRules.java
+++ b/src/main/java/net/minecraft/world/damagesource/CombatRules.java
@@ -11,12 +11,12 @@ public class CombatRules {
public static float getDamageAfterAbsorb(float damage, float armor, float armorToughness) {
float f = 2.0F + armorToughness / 4.0F;
- float g = Mth.clamp(armor - damage / f, armor * 0.2F, 20.0F);
+ float g = Mth.clamp(armor - damage / f, armor * 0.2F, org.purpurmc.purpur.PurpurConfig.limitArmor ? 20F : Float.MAX_VALUE); // Purpur
return damage * (1.0F - g / 25.0F);
}
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 cf0a52a037ac255c3f9e36dbff3cedda0fd8f49e..f10679ef2cbd73397b64eb69516c8a46e4d35a4e 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurConfig.java
@@ -577,6 +577,16 @@ public class PurpurConfig {
fixProjectileLootingTransfer = getBoolean("settings.fix-projectile-looting-transfer", fixProjectileLootingTransfer);
}
+ 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(new ResourceLocation(blockId));

View File

@@ -0,0 +1,56 @@
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/entity/boss/enderdragon/EnderDragon.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java
index 82d81fd2edff9df0bb4ff116d9274887a316d0a8..823f0e36119079eb827767c08391f18d75b66610 100644
--- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java
+++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java
@@ -111,6 +111,7 @@ public class EnderDragon extends Mob implements Enemy {
public EnderDragon(EntityType<? extends EnderDragon> entitytypes, Level world) {
super(EntityType.ENDER_DRAGON, world);
+ this.explosionSource = new Explosion(world, this, null, null, Double.NaN, Double.NaN, Double.NaN, Float.NaN, true, Explosion.BlockInteraction.DESTROY); // Purpur - moved instantiation from field
this.fightOrigin = BlockPos.ZERO;
this.growlTime = 100;
this.nodes = new Node[24];
diff --git a/src/main/java/net/minecraft/world/level/Explosion.java b/src/main/java/net/minecraft/world/level/Explosion.java
index b26cea981a876fd42c9ab91923d507b3c11a0425..b6c8f19a7d919fc56deb3518a28d725e9afbc82b 100644
--- a/src/main/java/net/minecraft/world/level/Explosion.java
+++ b/src/main/java/net/minecraft/world/level/Explosion.java
@@ -87,7 +87,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;
@@ -403,7 +403,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 78e8043f85f65e81db0d4192fbe93df952849490..ba7fa9386b494c38e44717529f20c9341e26d9c2 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
@@ -213,6 +213,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 boolean infinityWorksWithoutArrows = false;
public boolean infinityWorksWithNormalArrows = true;
public boolean infinityWorksWithSpectralArrows = false;

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 c2ca3432a47124d02e1aaf8ffb621f9a2c7d7a62..0d5f87d24231f6d2b8639825bcd62dd2f8791c8e 100644
--- a/src/main/java/net/minecraft/world/level/block/CactusBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/CactusBlock.java
@@ -22,7 +22,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 IntegerProperty AGE = BlockStateProperties.AGE_15;
public static final int MAX_AGE = 15;
@@ -129,4 +129,34 @@ public class CactusBlock extends Block {
public boolean isPathfindable(BlockState state, BlockGetter world, BlockPos pos, PathComputationType type) {
return false;
}
+
+ // Purpur start
+ @Override
+ public boolean isValidBonemealTarget(LevelReader world, BlockPos pos, BlockState state, boolean isClient) {
+ 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 74fedd3e401c6d58c03c0579f4b919114404fd78..4310d62c45c776eea81987809309da08c242c7b0 100644
--- a/src/main/java/net/minecraft/world/level/block/NetherWartBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/NetherWartBlock.java
@@ -14,7 +14,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 int MAX_AGE = 3;
public static final IntegerProperty AGE = BlockStateProperties.AGE_3;
@@ -70,5 +70,22 @@ public class NetherWartBlock extends BushBlock {
super.playerDestroy(world, player, pos, state, blockEntity, itemInHand, includeDrops);
}
}
+
+ @Override
+ public boolean isValidBonemealTarget(net.minecraft.world.level.LevelReader world, BlockPos pos, BlockState state, boolean isClient) {
+ 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 c3f500580d257e1397f2eb7c47b063a6fe6bb405..0d5c6bdfd4aeda472804b493315bf21ac3067e9d 100644
--- a/src/main/java/net/minecraft/world/level/block/SugarCaneBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/SugarCaneBlock.java
@@ -19,7 +19,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 IntegerProperty AGE = BlockStateProperties.AGE_15;
protected static final float AABB_OFFSET = 6.0F;
@@ -106,4 +106,34 @@ public class SugarCaneBlock extends Block {
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
builder.add(SugarCaneBlock.AGE);
}
+
+ // Purpur start
+ @Override
+ public boolean isValidBonemealTarget(LevelReader world, BlockPos pos, BlockState state, boolean isClient) {
+ 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 ba7fa9386b494c38e44717529f20c9341e26d9c2..2870a23c01ab5bdb45e355b2f1fd277395ef4771 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
@@ -830,8 +830,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,34 @@
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 b6c8f19a7d919fc56deb3518a28d725e9afbc82b..ef9b1687dd2dfda5398523140aecc678b4690642 100644
--- a/src/main/java/net/minecraft/world/level/Explosion.java
+++ b/src/main/java/net/minecraft/world/level/Explosion.java
@@ -407,6 +407,23 @@ 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);
+ if(!new org.purpurmc.purpur.event.PreBlockExplodeEvent(location.getBlock(), this.blockInteraction == Explosion.BlockInteraction.DESTROY_WITH_DECAY ? 1.0F / this.radius : 1.0F, this.damageSource.explodedBlockState).callEvent()) {
+ this.wasCanceled = true;
+ return;
+ }
+ }
+ //Purpur end
+
this.level.gameEvent(this.source, 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,48 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: rafaelflromao <12960698+rafaelflromao@users.noreply.github.com>
Date: Mon, 8 May 2023 20:43:29 +0100
Subject: [PATCH] Add mending multiplier
diff --git a/src/main/java/net/minecraft/world/entity/ExperienceOrb.java b/src/main/java/net/minecraft/world/entity/ExperienceOrb.java
index b2233635b6acc35ea3668c36c56e57f15420ac62..724bf857bf1b89cb0947b8a82e0ce09a0bec0335 100644
--- a/src/main/java/net/minecraft/world/entity/ExperienceOrb.java
+++ b/src/main/java/net/minecraft/world/entity/ExperienceOrb.java
@@ -359,13 +359,15 @@ public class ExperienceOrb extends Entity {
}
}
+ // Purpur start
public int durabilityToXp(int repairAmount) {
- return repairAmount / 2;
+ return (int) (repairAmount / (2 * level().purpurConfig.mendingMultiplier));
}
public int xpToDurability(int experienceAmount) {
- return experienceAmount * 2;
+ return (int) ((experienceAmount * 2) * level().purpurConfig.mendingMultiplier);
}
+ // Purpur end
public int getValue() {
return this.value;
diff --git a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
index 2870a23c01ab5bdb45e355b2f1fd277395ef4771..e7a794ce230c481e39436506facdb77726f96199 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
@@ -119,6 +119,7 @@ public class PurpurWorldConfig {
}
public boolean useBetterMending = false;
+ public double mendingMultiplier = 1.0;
public boolean alwaysTameInCreative = false;
public boolean boatEjectPlayersOnLand = false;
public boolean boatsDoFallDamage = false;
@@ -146,6 +147,7 @@ public class PurpurWorldConfig {
public int mobLastHurtByPlayerTime = 100;
private void miscGameplayMechanicsSettings() {
useBetterMending = getBoolean("gameplay-mechanics.use-better-mending", useBetterMending);
+ mendingMultiplier = getDouble("gameplay-mechanics.mending-multiplier", mendingMultiplier);
alwaysTameInCreative = getBoolean("gameplay-mechanics.always-tame-in-creative", alwaysTameInCreative);
boatEjectPlayersOnLand = getBoolean("gameplay-mechanics.boat.eject-players-on-land", boatEjectPlayersOnLand);
boatsDoFallDamage = getBoolean("gameplay-mechanics.boat.do-fall-damage", boatsDoFallDamage);

View File

@@ -0,0 +1,412 @@
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 6656a3f4dd78270690479639c738fdd0ec7e588d..6e9061dd6d5fd35d74d02c25a5985ffc5bc8e5ac 100644
--- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
+++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
@@ -99,6 +99,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 = reader;
diff --git a/src/main/java/net/minecraft/server/gui/MinecraftServerGui.java b/src/main/java/net/minecraft/server/gui/MinecraftServerGui.java
index dd9f611efc95f7d06fd3011fedd5d0317b1d0a85..be7b3fe2dc84493dcde9e185717b0b7c7c2e9822 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
+ jframe.setName("Purpur Minecraft server"); // Paper // Purpur
// Paper start - Add logo as frame image
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();
}
@@ -125,7 +130,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);
@@ -137,10 +142,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() {
public void focusGained(FocusEvent focusevent) {}
});
@@ -176,7 +214,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);
@@ -190,11 +228,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);
@@ -202,4 +243,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..0f2e7e0b81620c8581949bd5f0bdb567cd93c17e
--- /dev/null
+++ b/src/main/java/org/purpurmc/purpur/gui/GUIColor.java
@@ -0,0 +1,54 @@
+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 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..33e89b4c00fa8318506b36cbe49fe4e412e0a9a1
--- /dev/null
+++ b/src/main/java/org/purpurmc/purpur/gui/JColorTextPane.java
@@ -0,0 +1,78 @@
+package org.purpurmc.purpur.gui;
+
+import com.google.common.collect.Sets;
+import net.md_5.bungee.api.ChatColor;
+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 = GUIColor.BLACK;
+
+ public void append(String msg) {
+ // TODO: update to use adventure instead
+ BaseComponent[] components = TextComponent.fromLegacyText(DEFAULT_COLOR.getCode() + msg, ChatColor.BLACK);
+ 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 675cd61221e807aadf28322b46c3daa1370241b5..0769f5c4711a3b7f59489e611ed01ad8367e5db1 100644
--- a/src/main/resources/log4j2.xml
+++ b/src/main/resources/log4j2.xml
@@ -2,7 +2,16 @@
<Configuration status="WARN" packages="com.mojang.util" shutdownHook="disable">
<Appenders>
<Queue name="ServerGuiConsole">
- <PatternLayout pattern="[%d{HH:mm:ss} %level]: %msg%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,271 @@
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 7b82842b97ce795745cf6ee6399f618c55acbbf3..5344393f62af19c3591f54a6ebc40b2e4c3b6226 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
@@ -130,6 +130,36 @@ public class BeehiveBlockEntity extends BlockEntity {
return list;
}
+ // Purpur start
+ public List<Entity> releaseBees(BlockState iblockdata, Level level, BeehiveBlockEntity.BeeReleaseStatus tileentitybeehive_releasestatus, boolean force) {
+ List<Entity> list = Lists.newArrayList();
+
+ this.stored.removeIf((tileentitybeehive_hivebee) -> {
+ return BeehiveBlockEntity.releaseBee(level, this.worldPosition, iblockdata, tileentitybeehive_hivebee, list, tileentitybeehive_releasestatus, this.savedFlowerPos, force);
+ });
+
+ if (!list.isEmpty()) {
+ super.setChanged();
+ }
+
+ return list;
+ }
+
+ public List<Entity> releaseBee(BlockState iblockdata, Level level, BeeData data, BeehiveBlockEntity.BeeReleaseStatus tileentitybeehive_releasestatus, boolean force) {
+ List<Entity> list = Lists.newArrayList();
+
+ BeehiveBlockEntity.releaseBee(level, this.worldPosition, iblockdata, data, list, tileentitybeehive_releasestatus, this.savedFlowerPos, force);
+
+ if (!list.isEmpty()) {
+ stored.remove(data);
+
+ super.setChanged();
+ }
+
+ return list;
+ }
+ // Purpur end
+
public void addOccupant(Entity entity, boolean hasNectar) {
this.addOccupantWithPresetTicks(entity, hasNectar, 0);
}
@@ -139,6 +169,12 @@ public class BeehiveBlockEntity extends BlockEntity {
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();
@@ -425,9 +461,9 @@ public class BeehiveBlockEntity extends BlockEntity {
private BeeReleaseStatus() {}
}
- private static class BeeData {
+ public static class BeeData { // Purpur - change from private to public
- final CompoundTag entityData;
+ public final CompoundTag entityData; // Purpur - make public
int ticksInHive;
int exitTickCounter; // Paper - separate counter for checking if bee should exit to reduce exit attempts
final int minOccupationTicks;
diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBeehive.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBeehive.java
index 380897c010521f368848a3e6986d307cf47ff319..3c5eae31dc229b8c5f15215be9462410bcb41f07 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 : getSnapshot().getStored()) {
+ storage.add(new org.purpurmc.purpur.entity.PurpurStoredBee(data, this));
+ }
+ // Purpur end
}
@Override
@@ -66,25 +73,67 @@ public class CraftBeehive extends CraftBlockEntityState<BeehiveBlockEntity> impl
List<Bee> bees = new ArrayList<>();
if (isPlaced()) {
- BeehiveBlockEntity beehive = ((BeehiveBlockEntity) this.getTileEntityFromWorld());
- for (Entity bee : beehive.releaseBees(this.getHandle(), BeeReleaseStatus.BEE_RELEASED, true)) {
+ // Purpur start - change which releaseBees method is called, and use beehive snapshot
+ BeehiveBlockEntity beehive = ((BeehiveBlockEntity) this.getSnapshot());
+ for (Entity bee : beehive.releaseBees(this.getHandle(), getWorldHandle().getMinecraftWorld(), BeeReleaseStatus.BEE_RELEASED, true)) {
+ // Purpur end
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 = this.getSnapshot();
+ BeehiveBlockEntity.BeeData data = ((org.purpurmc.purpur.entity.PurpurStoredBee) entity).getHandle();
+
+ List<Entity> list = beehive.releaseBee(getHandle(), getWorldHandle().getMinecraftWorld(), 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");
+ int length = getSnapshot().getStored().size(); // Purpur
getSnapshot().addOccupant(((CraftBee) entity).getHandle(), false);
+
+ // Purpur start - check if new bee was added, and if yes, add to stored bees
+ List<BeehiveBlockEntity.BeeData> s = getSnapshot().getStored();
+ if(length < s.size()) {
+ storage.add(new org.purpurmc.purpur.entity.PurpurStoredBee(s.get(s.size() - 1), this));
+ }
+ // Purpur end
}
// Paper start - Add EntityBlockStorage clearEntities
@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..8efca1d91188ac4db911a8eb0fa9ea2cc3c48e28
--- /dev/null
+++ b/src/main/java/org/purpurmc/purpur/entity/PurpurStoredBee.java
@@ -0,0 +1,102 @@
+package org.purpurmc.purpur.entity;
+
+import io.papermc.paper.adventure.PaperAdventure;
+import net.kyori.adventure.text.Component;
+import net.minecraft.nbt.Tag;
+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;
+
+ this.customName = handle.entityData.contains("CustomName", Tag.TAG_STRING)
+ ? PaperAdventure.asAdventure(net.minecraft.network.chat.Component.Serializer.fromJson(handle.entityData.getString("CustomName")))
+ : null;
+
+ if(handle.entityData.contains("BukkitValues", Tag.TAG_COMPOUND)) {
+ this.persistentDataContainer.putAll(handle.entityData.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.entityData.put("BukkitValues", this.persistentDataContainer.toTagCompound());
+ if(customName == null) {
+ handle.entityData.remove("CustomName");
+ } else {
+ handle.entityData.putString("CustomName", net.minecraft.network.chat.Component.Serializer.toJson(PaperAdventure.asVanilla(customName)));
+ }
+ }
+}

Some files were not shown because too many files have changed in this diff Show More