Initial 26.2 port

This commit is contained in:
granny
2026-06-03 16:22:25 -07:00
parent bb69e15257
commit 1638c22046
144 changed files with 1133 additions and 830 deletions

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/level/BaseSpawner.java
+++ b/net/minecraft/world/level/BaseSpawner.java
@@ -60,6 +_,7 @@
@@ -66,6 +_,7 @@
}
public boolean isNearPlayer(final Level level, final BlockPos pos) {

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/level/EntityGetter.java
+++ b/net/minecraft/world/level/EntityGetter.java
@@ -183,7 +_,7 @@
@@ -142,7 +_,7 @@
default boolean hasNearbyAlivePlayer(final double x, final double y, final double z, final double range) {
for (Player player : this.players()) {

View File

@@ -55,7 +55,7 @@
public CraftWorld getWorld() {
return this.world;
}
@@ -852,6 +_,8 @@
@@ -220,6 +_,8 @@
final org.bukkit.NamespacedKey worldKey = CraftNamespacedKey.fromMinecraft(dimension.identifier()); // Paper
this.spigotConfig = new org.spigotmc.SpigotWorldConfig(bukkitName, worldKey); // Spigot
this.paperConfig = paperWorldConfigCreator.apply(this.spigotConfig); // Paper - create paper world config
@@ -64,8 +64,8 @@
this.generator = generator;
this.world = new CraftWorld((ServerLevel) this, worldKey, biomeProvider, environment);
@@ -2197,4 +_,14 @@
return this.moonrise$getEntityLookup().getEntityCount(); // Paper - rewrite chunk system
@@ -1504,4 +_,14 @@
return ret;
}
// Paper end - allow patching this logic
+

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/level/NaturalSpawner.java
+++ b/net/minecraft/world/level/NaturalSpawner.java
@@ -289,7 +_,7 @@
@@ -213,7 +_,7 @@
pos.set(x, yStart, z);
double xx = x + 0.5;
double zz = z + 0.5;

View File

@@ -1,26 +0,0 @@
--- a/net/minecraft/world/level/ServerExplosion.java
+++ b/net/minecraft/world/level/ServerExplosion.java
@@ -623,6 +_,23 @@
}
public int explode() {
+ // Purpur start - add PreExplodeEvents
+ if (this.source != null) {
+ org.bukkit.Location location = new org.bukkit.Location(this.level.getWorld(), this.center.x, this.center.y, this.center.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, org.bukkit.craftbukkit.CraftExplosionResult.toExplosionResult(getBlockInteraction())).callEvent()) {
+ this.wasCanceled = true;
+ return 0;
+ }
+ } else {
+ org.bukkit.Location location = new org.bukkit.Location(this.level.getWorld(), this.center.x, this.center.y, this.center.z);
+ org.bukkit.block.Block block = location.getBlock();
+ org.bukkit.block.BlockState blockState = (this.damageSource.causingBlockSnapshot() != null) ? this.damageSource.causingBlockSnapshot() : block.getState();
+ if(!new org.purpurmc.purpur.event.PreBlockExplodeEvent(location.getBlock(), this.blockInteraction == Explosion.BlockInteraction.DESTROY_WITH_DECAY ? 1.0F / this.radius : 1.0F, blockState, org.bukkit.craftbukkit.CraftExplosionResult.toExplosionResult(getBlockInteraction())).callEvent()) {
+ this.wasCanceled = true;
+ return 0;
+ }
+ }
+ // Purpur end - Add PreExplodeEvents
// Paper start - collision optimisations
this.blockCache = new it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap<>();
this.chunkPosCache = new long[CHUNK_CACHE_WIDTH * CHUNK_CACHE_WIDTH];

View File

@@ -1,29 +0,0 @@
--- a/net/minecraft/world/level/block/BedBlock.java
+++ b/net/minecraft/world/level/block/BedBlock.java
@@ -101,7 +_,7 @@
}
Vec3 boomPos = pos.getCenter();
- level.explode(null, level.damageSources().badRespawnPointExplosion(boomPos), null, boomPos, 5.0F, true, Level.ExplosionInteraction.BLOCK);
+ if (level.purpurConfig.bedExplode) level.explode(null, level.damageSources().badRespawnPointExplosion(boomPos), null, boomPos, (float) level.purpurConfig.bedExplosionPower, level.purpurConfig.bedExplosionFire, level.purpurConfig.bedExplosionEffect); // Purpur - Implement bed explosion options
return InteractionResult.SUCCESS_SERVER;
} else if (state.getValue(OCCUPIED)) {
if (bedRule.explodes()) return this.explodeBed(state, level, pos); // Paper - check explode first
@@ -153,7 +_,7 @@
}
Vec3 boomPos = pos.getCenter();
- level.explode(null, level.damageSources().badRespawnPointExplosion(boomPos).causingBlockSnapshot(blockState), null, boomPos, 5.0F, true, Level.ExplosionInteraction.BLOCK); // CraftBukkit - add state
+ if (level.purpurConfig.bedExplode) level.explode(null, level.damageSources().badRespawnPointExplosion(boomPos).causingBlockSnapshot(blockState), null, boomPos, (float) level.purpurConfig.bedExplosionPower, level.purpurConfig.bedExplosionFire, level.purpurConfig.bedExplosionEffect); // CraftBukkit - add state // Purpur - Implement bed explosion options
return InteractionResult.SUCCESS_SERVER;
}
// CraftBukkit end
@@ -170,7 +_,7 @@
@Override
public void fallOn(final Level level, final BlockState state, final BlockPos pos, final Entity entity, final double fallDistance) {
- super.fallOn(level, state, pos, entity, fallDistance * 0.5);
+ super.fallOn(level, state, pos, entity, fallDistance); // Purpur - Configurable block fall damage modifiers
}
@Override

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/level/block/Block.java
+++ b/net/minecraft/world/level/block/Block.java
@@ -114,6 +_,10 @@
@@ -111,6 +_,10 @@
public static final int UPDATE_LIMIT = 512;
protected final StateDefinition<Block, BlockState> stateDefinition;
private BlockState defaultBlockState;
@@ -11,7 +11,7 @@
// Paper start - Protect Bedrock and End Portal/Frames from being destroyed
public final boolean isDestroyable() {
return io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.allowPermanentBlockBreakExploits ||
@@ -415,7 +_,7 @@
@@ -412,7 +_,7 @@
event.setExpToDrop(block.getExpDrop(state, serverLevel, pos, net.minecraft.world.item.ItemStack.EMPTY, true)); // Paper - Properly handle xp dropping
event.callEvent();
for (org.bukkit.inventory.ItemStack drop : event.getDrops()) {
@@ -20,7 +20,7 @@
}
state.spawnAfterBreak(serverLevel, pos, ItemStack.EMPTY, false); // Paper - Properly handle xp dropping
block.popExperience(serverLevel, pos, event.getExpToDrop()); // Paper - Properly handle xp dropping
@@ -433,7 +_,7 @@
@@ -430,7 +_,7 @@
public static void dropResources(final BlockState state, final LevelAccessor level, final BlockPos pos, final @Nullable BlockEntity blockEntity) {
if (level instanceof ServerLevel serverLevel) {
@@ -29,7 +29,7 @@
state.spawnAfterBreak(serverLevel, pos, ItemStack.EMPTY, true);
}
}
@@ -454,11 +_,30 @@
@@ -451,11 +_,30 @@
, final boolean dropExperience // Paper - Properly handle xp dropping
) {
if (level instanceof ServerLevel serverLevel) {
@@ -59,9 +59,9 @@
+ // Purpur end - Persistent BlockEntity Lore and DisplayName
+
public static void popResource(final Level level, final BlockPos pos, final ItemStack itemStack) {
double halfHeight = EntityType.ITEM.getHeight() / 2.0;
double halfHeight = EntityTypes.ITEM.getHeight() / 2.0;
RandomSource random = level.getRandom();
@@ -548,7 +_,15 @@
@@ -545,7 +_,15 @@
}
public void setPlacedBy(final Level level, final BlockPos pos, final BlockState state, final @Nullable LivingEntity by, final ItemStack itemStack) {
@@ -78,7 +78,7 @@
public boolean isPossibleToRespawnInThis(final BlockState state) {
return !state.isSolid() && !state.liquid();
@@ -559,7 +_,7 @@
@@ -556,7 +_,7 @@
}
public void fallOn(final Level level, final BlockState state, final BlockPos pos, final Entity entity, final double fallDistance) {
@@ -86,4 +86,4 @@
+ entity.causeFallDamage(fallDistance * fallDistanceMultiplier, fallDamageMultiplier, entity.damageSources().fall()); // Purpur - Configurable block fall damage modifiers
}
public void updateEntityMovementAfterFallOn(final BlockGetter level, final Entity entity) {
public float getBounceRestitution() {

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/level/block/Blocks.java
+++ b/net/minecraft/world/level/block/Blocks.java
@@ -6727,6 +_,7 @@
@@ -5519,6 +_,7 @@
BlockBehaviour.Properties.of()
.mapColor(MapColor.PLANT)
.forceSolidOff()
@@ -8,7 +8,7 @@
.instabreak()
.sound(SoundType.AZALEA)
.noOcclusion()
@@ -6738,6 +_,7 @@
@@ -5530,6 +_,7 @@
BlockBehaviour.Properties.of()
.mapColor(MapColor.PLANT)
.forceSolidOff()

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/level/block/CampfireBlock.java
+++ b/net/minecraft/world/level/block/CampfireBlock.java
@@ -136,7 +_,7 @@
@@ -137,7 +_,7 @@
return this.defaultBlockState()
.setValue(WATERLOGGED, replacedWater)
.setValue(SIGNAL_FIRE, this.isSmokeSource(level.getBlockState(pos.below())))

View File

@@ -2,7 +2,7 @@
+++ b/net/minecraft/world/level/block/CarvedPumpkinBlock.java
@@ -67,7 +_,7 @@
if (snowGolemMatch != null) {
SnowGolem snowGolem = EntityType.SNOW_GOLEM.create(level, EntitySpawnReason.TRIGGERED);
SnowGolem snowGolem = EntityTypes.SNOW_GOLEM.create(level, EntitySpawnReason.TRIGGERED);
if (snowGolem != null) {
- spawnGolemInWorld(level, snowGolemMatch, snowGolem, snowGolemMatch.getBlock(0, 2, 0).getPos());
+ spawnGolemInWorld(level, snowGolemMatch, snowGolem, snowGolemMatch.getBlock(0, 2, 0).getPos(), this.placer); // Purpur - Summoner API
@@ -10,7 +10,7 @@
}
}
@@ -77,7 +_,7 @@
IronGolem ironGolem = EntityType.IRON_GOLEM.create(level, EntitySpawnReason.TRIGGERED);
IronGolem ironGolem = EntityTypes.IRON_GOLEM.create(level, EntitySpawnReason.TRIGGERED);
if (ironGolem != null) {
ironGolem.setPlayerCreated(true);
- spawnGolemInWorld(level, ironGolemMatch, ironGolem, ironGolemMatch.getBlock(1, 2, 0).getPos());
@@ -20,7 +20,7 @@
}
@@ -86,7 +_,7 @@
if (copperGolemMatch != null) {
CopperGolem copperGolem = EntityType.COPPER_GOLEM.create(level, EntitySpawnReason.TRIGGERED);
CopperGolem copperGolem = EntityTypes.COPPER_GOLEM.create(level, EntitySpawnReason.TRIGGERED);
if (copperGolem != null) {
- spawnGolemInWorld(level, copperGolemMatch, copperGolem, copperGolemMatch.getBlock(0, 0, 0).getPos());
+ spawnGolemInWorld(level, copperGolemMatch, copperGolem, copperGolemMatch.getBlock(0, 0, 0).getPos(), this.placer); // Purpur - Summoner API

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/level/block/ChestBlock.java
+++ b/net/minecraft/world/level/block/ChestBlock.java
@@ -347,6 +_,7 @@
@@ -348,6 +_,7 @@
}
public static boolean isBlockedChestByBlock(final BlockGetter level, final BlockPos pos) {

View File

@@ -1,15 +1,15 @@
--- a/net/minecraft/world/level/block/NetherPortalBlock.java
+++ b/net/minecraft/world/level/block/NetherPortalBlock.java
@@ -68,7 +_,7 @@
protected void randomTick(final BlockState state, final ServerLevel level, BlockPos pos, final RandomSource random) {
if (level.spigotConfig.enableZombiePigmenPortalSpawns && level.isSpawningMonsters() // Spigot
@@ -70,7 +_,7 @@
if (level.spigotConfig.enableZombiePigmenPortalSpawns && level.isSpawningMonsters() // Paper
&& level.getLevelData().getDifficulty() != Difficulty.PEACEFUL
&& level.environmentAttributes().getValue(EnvironmentAttributes.NETHER_PORTAL_SPAWNS_PIGLINS, pos)
- && random.nextInt(2000) < level.getDifficulty().getId()
+ && random.nextInt(level.purpurConfig.piglinPortalSpawnModifier) < level.getDifficulty().getId() // Purpur - Piglin portal spawn modifier
&& level.anyPlayerCloseEnoughForSpawning(pos)) {
while (level.getBlockState(pos).is(this)) {
pos = pos.below();
@@ -133,7 +_,7 @@
@@ -135,7 +_,7 @@
@Override
public int getPortalTransitionTime(final ServerLevel level, final Entity entity) {
return entity instanceof Player player

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/level/block/PointedDripstoneBlock.java
+++ b/net/minecraft/world/level/block/PointedDripstoneBlock.java
@@ -196,20 +_,20 @@
@@ -89,20 +_,20 @@
@VisibleForTesting
public static void maybeTransferFluid(final BlockState state, final ServerLevel level, final BlockPos pos, final float randomValue) {

View File

@@ -1,11 +0,0 @@
--- a/net/minecraft/world/level/block/RespawnAnchorBlock.java
+++ b/net/minecraft/world/level/block/RespawnAnchorBlock.java
@@ -176,7 +_,7 @@
}
};
Vec3 boomPos = pos.getCenter();
- level.explode(null, level.damageSources().badRespawnPointExplosion(boomPos).causingBlockSnapshot(blockState), damageCalculator, boomPos, 5.0F, true, Level.ExplosionInteraction.BLOCK); // CraftBukkit - add state
+ level.explode(null, level.damageSources().badRespawnPointExplosion(boomPos).causingBlockSnapshot(blockState), damageCalculator, boomPos, (float) level.purpurConfig.respawnAnchorExplosionPower, level.purpurConfig.respawnAnchorExplosionFire, level.purpurConfig.respawnAnchorExplosionEffect); // CraftBukkit - add state // Purpur - Implement respawn anchor explosion options
}
public static boolean canSetSpawn(final ServerLevel level, final BlockPos pos) {

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/level/block/SculkShriekerBlock.java
+++ b/net/minecraft/world/level/block/SculkShriekerBlock.java
@@ -116,7 +_,7 @@
@@ -117,7 +_,7 @@
@Override
public @Nullable BlockState getStateForPlacement(final BlockPlaceContext context) {

View File

@@ -0,0 +1,11 @@
--- a/net/minecraft/world/level/block/ShulkerBoxBlock.java
+++ b/net/minecraft/world/level/block/ShulkerBoxBlock.java
@@ -87,7 +_,7 @@
return InteractionResult.SUCCESS;
}
- public static boolean canOpen(final BlockState state, final Level level, final BlockPos pos, final ShulkerBoxBlockEntity blockEntity) {
+ private static boolean canOpen(final BlockState state, final Level level, final BlockPos pos, final ShulkerBoxBlockEntity blockEntity) {
if (blockEntity.getAnimationStatus() != ShulkerBoxBlockEntity.AnimationStatus.CLOSED) {
return true;
}

View File

@@ -1,8 +1,8 @@
--- a/net/minecraft/world/level/block/SlabBlock.java
+++ b/net/minecraft/world/level/block/SlabBlock.java
@@ -143,4 +_,25 @@
return false;
}
@@ -139,4 +_,25 @@
default -> false;
};
}
+
+ // Purpur start - Break individual slabs when sneaking

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/level/block/SpawnerBlock.java
+++ b/net/minecraft/world/level/block/SpawnerBlock.java
@@ -15,6 +_,7 @@
@@ -16,6 +_,7 @@
import org.jspecify.annotations.Nullable;
public class SpawnerBlock extends BaseEntityBlock {
@@ -8,8 +8,8 @@
public static final MapCodec<SpawnerBlock> CODEC = simpleCodec(SpawnerBlock::new);
@Override
@@ -36,6 +_,62 @@
return createTickerHelper(type, BlockEntityType.MOB_SPAWNER, level.isClientSide() ? SpawnerBlockEntity::clientTick : SpawnerBlockEntity::serverTick);
@@ -37,6 +_,62 @@
return createTickerHelper(type, BlockEntityTypes.MOB_SPAWNER, level.isClientSide() ? SpawnerBlockEntity::clientTick : SpawnerBlockEntity::serverTick);
}
+ // Purpur start - Silk touch spawners
@@ -71,7 +71,7 @@
@Override
protected void spawnAfterBreak(final BlockState state, final ServerLevel level, final BlockPos pos, final ItemStack tool, final boolean dropExperience) {
super.spawnAfterBreak(state, level, pos, tool, dropExperience);
@@ -44,6 +_,7 @@
@@ -45,6 +_,7 @@
@Override
public int getExpDrop(final BlockState state, final ServerLevel level, final BlockPos pos, final ItemStack tool, final boolean dropExperience) {

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/level/block/entity/BeaconBlockEntity.java
+++ b/net/minecraft/world/level/block/entity/BeaconBlockEntity.java
@@ -138,6 +_,16 @@
@@ -140,6 +_,16 @@
public double getEffectRange() {
if (this.effectRange < 0) {
@@ -17,7 +17,7 @@
return this.levels * 10 + 10;
} else {
return effectRange;
@@ -166,6 +_,7 @@
@@ -168,6 +_,7 @@
int y = pos.getY();
int z = pos.getZ();
BlockPos checkPos;
@@ -25,7 +25,7 @@
if (entity.lastCheckY < y) {
checkPos = pos;
entity.checkingBeamSections = Lists.newArrayList();
@@ -195,11 +_,15 @@
@@ -197,11 +_,15 @@
}
}
} else {
@@ -42,7 +42,7 @@
lastBeamSection.increaseHeight();
}
@@ -210,11 +_,11 @@
@@ -212,11 +_,11 @@
int previousLevels = entity.levels;
if (level.getGameTime() % 80L == 0L) {

View File

@@ -9,7 +9,7 @@
private static final int MIN_TICKS_BEFORE_REENTERING_HIVE = 400;
private static final int MIN_OCCUPATION_TICKS_NECTAR = 2400;
public static final int MIN_OCCUPATION_TICKS_NECTARLESS = 600;
@@ -157,10 +_,32 @@
@@ -157,11 +_,33 @@
return spawned;
}
@@ -33,12 +33,24 @@
public int getOccupantCount() {
return this.stored.size();
}
+
+ // Purpur start - Stored Bee API
+ public List<BeeData> getStored() {
+ return stored;
+ }
+ // Purpur end - Stored Bee API
+
// Paper start - Add EntityBlockStorage clearEntities
public void clearBees() {
this.stored.clear();
@@ -390,8 +_,8 @@
registration.register(DebugSubscriptions.BEE_HIVES, () -> DebugHiveInfo.pack(this));
}
- public static class BeeData {
- public final BeehiveBlockEntity.Occupant occupant;
+ private static class BeeData {
+ private final BeehiveBlockEntity.Occupant occupant;
private int exitTickCounter; // Paper - Fix bees aging inside hives; separate counter for checking if bee should exit to reduce exit attempts
private int ticksInHive;

View File

@@ -7,7 +7,7 @@
+ private int lapis = 0; // Purpur - Enchantment Table Persists Lapis
public EnchantingTableBlockEntity(final BlockPos worldPosition, final BlockState blockState) {
super(BlockEntityType.ENCHANTING_TABLE, worldPosition, blockState);
super(BlockEntityTypes.ENCHANTING_TABLE, worldPosition, blockState);
@@ -39,12 +_,14 @@
protected void saveAdditional(final ValueOutput output) {
super.saveAdditional(output);

View File

@@ -0,0 +1,11 @@
--- a/net/minecraft/world/level/block/entity/FuelValues.java
+++ b/net/minecraft/world/level/block/entity/FuelValues.java
@@ -17,7 +_,7 @@
import net.minecraft.world.level.block.Blocks;
public class FuelValues {
- public final Object2IntSortedMap<Item> values;
+ private final Object2IntSortedMap<Item> values;
private FuelValues(final Object2IntSortedMap<Item> values) {
this.values = values;

View File

@@ -0,0 +1,11 @@
--- a/net/minecraft/world/level/block/state/BlockBehaviour.java
+++ b/net/minecraft/world/level/block/state/BlockBehaviour.java
@@ -88,7 +_,7 @@
Direction.WEST, Direction.EAST, Direction.NORTH, Direction.SOUTH, Direction.DOWN, Direction.UP
};
public final boolean hasCollision;
- public float explosionResistance;
+ protected final float explosionResistance;
protected final boolean isRandomlyTicking;
protected final SoundType soundType;
protected final float friction;

View File

@@ -1,8 +1,8 @@
--- a/net/minecraft/world/level/chunk/storage/EntityStorage.java
+++ b/net/minecraft/world/level/chunk/storage/EntityStorage.java
@@ -105,6 +_,7 @@
}
// Paper end - Entity load/save limit per chunk
@@ -94,6 +_,7 @@
ListTag entities = new ListTag();
chunk.getEntities().forEach(e -> {
TagValueOutput output = TagValueOutput.createWithContext(reporter.forChild(e.problemPath()), e.registryAccess());
+ if (!e.canSaveToDisk()) return; // Purpur - Add canSaveToDisk to Entity
if (e.save(output)) {

View File

@@ -1,11 +0,0 @@
--- a/net/minecraft/world/level/chunk/storage/RegionFileStorage.java
+++ b/net/minecraft/world/level/chunk/storage/RegionFileStorage.java
@@ -309,7 +_,7 @@
// Paper start
private static void printOversizedLog(String msg, Path file, int x, int z) {
- LOGGER.error("{} ({} - {},{}) Go clean it up to remove this message. /minecraft:tp {} 128 {} - DO NOT REPORT THIS TO PAPER - You may ask for help on Discord, but do not file an issue. These error messages can not be removed.", msg, file.toString().replaceAll(".+[\\\\/]", ""), x, z, x << 4, z << 4);
+ LOGGER.error("{} ({} - {},{}) Go clean it up to remove this message. /minecraft:tp {} 128 {} - DO NOT REPORT THIS TO PURPUR - You may ask for help on Discord, but do not file an issue. These error messages can not be removed.", msg, file.toString().replaceAll(".+[\\\\/]", ""), x, z, x << 4, z << 4); // Purpur - Rebrand
}
private static CompoundTag readOversizedChunk(RegionFile regionfile, ChunkPos chunkCoordinate) throws IOException {

View File

@@ -19,7 +19,7 @@
int dayLength = 24000;
@@ -56,7 +_,7 @@
FluidState fluidState = level.getFluidState(spawnPos);
if (NaturalSpawner.isValidEmptySpawnBlock(level, spawnPos, blockState, fluidState, EntityType.PHANTOM)) {
if (NaturalSpawner.isValidEmptySpawnBlock(level, spawnPos, blockState, fluidState, EntityTypes.PHANTOM)) {
SpawnGroupData groupData = null;
- int groupSize = 1 + random.nextInt(difficulty.getDifficulty().getId() + 1);
+ int groupSize = level.purpurConfig.phantomSpawnMinPerAttempt + random.nextInt((level.purpurConfig.phantomSpawnMaxPerAttempt < 0 ? difficulty.getDifficulty().getId() : level.purpurConfig.phantomSpawnMaxPerAttempt - level.purpurConfig.phantomSpawnMinPerAttempt) + 1); // Purpur - Add phantom spawning options

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/level/material/FlowingFluid.java
+++ b/net/minecraft/world/level/material/FlowingFluid.java
@@ -234,7 +_,7 @@
@@ -192,7 +_,7 @@
}
}
@@ -9,7 +9,7 @@
BlockState belowState = level.getBlockState(mutablePos.setWithOffset(pos, Direction.DOWN));
FluidState belowFluid = belowState.getFluidState();
if (belowState.isSolid() || this.isSourceBlockOfThisType(belowFluid)) {
@@ -320,6 +_,12 @@
@@ -280,6 +_,12 @@
}
protected abstract boolean canConvertToSource(ServerLevel level);

View File

@@ -5,7 +5,7 @@
private static final int MIN_HEIGHT = 3;
public static final int MAX_HEIGHT = 21;
- public static final BlockBehaviour.StatePredicate FRAME = (state, level, pos) -> state.is(Blocks.OBSIDIAN);
+ public static final BlockBehaviour.StatePredicate FRAME = (state, level, pos) -> state.is(Blocks.OBSIDIAN) || (org.purpurmc.purpur.PurpurConfig.cryingObsidianValidForPortalFrame && state.is(Blocks.CRYING_OBSIDIAN)); // Purpur - Crying obsidian valid for portal frames
+ private static final BlockBehaviour.StatePredicate FRAME = (state, level, pos) -> state.is(Blocks.OBSIDIAN);
private static final float SAFE_TRAVEL_MAX_ENTITY_XY = 4.0F;
private static final double SAFE_TRAVEL_MAX_VERTICAL_DELTA = 1.0;
private final Direction.Axis axis;