net.minecraft.world.level.levelgen

This commit is contained in:
Jake Potrebic
2024-12-14 15:00:16 -08:00
parent c9fd2a7ad5
commit d1369750e2
8 changed files with 211 additions and 210 deletions

View File

@@ -0,0 +1,52 @@
--- a/net/minecraft/world/level/levelgen/DensityFunctions.java
+++ b/net/minecraft/world/level/levelgen/DensityFunctions.java
@@ -506,6 +_,16 @@
);
private static final float ISLAND_THRESHOLD = -0.9F;
private final SimplexNoise islandNoise;
+ // Paper start - Perf: Optimize end generation
+ private static final class NoiseCache {
+ public long[] keys = new long[8192];
+ public float[] values = new float[8192];
+ public NoiseCache() {
+ java.util.Arrays.fill(keys, Long.MIN_VALUE);
+ }
+ }
+ private static final ThreadLocal<java.util.Map<SimplexNoise, NoiseCache>> noiseCache = ThreadLocal.withInitial(java.util.WeakHashMap::new);
+ // Paper end - Perf: Optimize end generation
public EndIslandDensityFunction(long seed) {
RandomSource randomSource = new LegacyRandomSource(seed);
@@ -518,15 +_,29 @@
int i1 = z / 2;
int i2 = x % 2;
int i3 = z % 2;
- float f = 100.0F - Mth.sqrt(x * x + z * z) * 8.0F;
+ float f = 100.0F - Mth.sqrt((long)x * (long)x + (long)z * (long)z) * 8.0F; // Paper - cast ints to long to avoid integer overflow
f = Mth.clamp(f, -100.0F, 80.0F);
+ NoiseCache cache = noiseCache.get().computeIfAbsent(noise, noiseKey -> new NoiseCache()); // Paper - Perf: Optimize end generation
for (int i4 = -12; i4 <= 12; i4++) {
for (int i5 = -12; i5 <= 12; i5++) {
long l = i + i4;
long l1 = i1 + i5;
- if (l * l + l1 * l1 > 4096L && noise.getValue(l, l1) < -0.9F) {
- float f1 = (Mth.abs((float)l) * 3439.0F + Mth.abs((float)l1) * 147.0F) % 13.0F + 9.0F;
+ // Paper start - Perf: Optimize end generation by using a noise cache
+ long key = net.minecraft.world.level.ChunkPos.asLong((int) l, (int) l);
+ int index = (int) it.unimi.dsi.fastutil.HashCommon.mix(key) & 8191;
+ float f1 = Float.MIN_VALUE;
+ if (cache.keys[index] == key) {
+ f1 = cache.values[index];
+ } else {
+ if (l * l + l1 * l1 > 4096L && noise.getValue((double)l, (double)l1) < -0.9F) {
+ f1 = (Mth.abs((float)l) * 3439.0F + Mth.abs((float)l1) * 147.0F) % 13.0F + 9.0F;
+ }
+ cache.keys[index] = key;
+ cache.values[index] = f1;
+ }
+ if (f1 != Float.MIN_VALUE) {
+ // Paper end - Perf: Optimize end generation
float f2 = i2 - i4 * 2;
float f3 = i3 - i5 * 2;
float f4 = 100.0F - Mth.sqrt(f2 * f2 + f3 * f3) * f1;

View File

@@ -0,0 +1,28 @@
--- a/net/minecraft/world/level/levelgen/FlatLevelSource.java
+++ b/net/minecraft/world/level/levelgen/FlatLevelSource.java
@@ -33,17 +_,22 @@
private final FlatLevelGeneratorSettings settings;
public FlatLevelSource(FlatLevelGeneratorSettings settings) {
- super(new FixedBiomeSource(settings.getBiome()), Util.memoize(settings::adjustGenerationSettings));
+ // CraftBukkit start
+ this(settings, new FixedBiomeSource(settings.getBiome()));
+ }
+ public FlatLevelSource(FlatLevelGeneratorSettings settings, net.minecraft.world.level.biome.BiomeSource biomeSource) {
+ super(biomeSource, Util.memoize(settings::adjustGenerationSettings));
+ // CraftBukkit end
this.settings = settings;
}
@Override
- public ChunkGeneratorStructureState createState(HolderLookup<StructureSet> structureSetLookup, RandomState randomState, long seed) {
+ public ChunkGeneratorStructureState createState(HolderLookup<StructureSet> structureSetLookup, RandomState randomState, long seed, org.spigotmc.SpigotWorldConfig conf) { // Spigot
Stream<Holder<StructureSet>> stream = this.settings
.structureOverrides()
.map(HolderSet::stream)
.orElseGet(() -> structureSetLookup.listElements().map(reference -> (Holder<StructureSet>)reference));
- return ChunkGeneratorStructureState.createForFlat(randomState, seed, this.biomeSource, stream);
+ return ChunkGeneratorStructureState.createForFlat(randomState, seed, this.biomeSource, stream, conf); // Spigot
}
@Override

View File

@@ -0,0 +1,7 @@
--- a/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java
+++ b/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java
@@ -1,3 +_,4 @@
+// keep
package net.minecraft.world.level.levelgen;
import com.google.common.annotations.VisibleForTesting;

View File

@@ -0,0 +1,91 @@
--- a/net/minecraft/world/level/levelgen/PatrolSpawner.java
+++ b/net/minecraft/world/level/levelgen/PatrolSpawner.java
@@ -20,28 +_,66 @@
@Override
public int tick(ServerLevel level, boolean spawnEnemies, boolean spawnFriendlies) {
+ if (level.paperConfig().entities.behavior.pillagerPatrols.disable || level.paperConfig().entities.behavior.pillagerPatrols.spawnChance == 0) return 0; // Paper - Add option to disable pillager patrols & Pillager patrol spawn settings and per player options
if (!spawnEnemies) {
return 0;
} else if (!level.getGameRules().getBoolean(GameRules.RULE_DO_PATROL_SPAWNING)) {
return 0;
} else {
RandomSource randomSource = level.random;
- this.nextTick--;
- if (this.nextTick > 0) {
- return 0;
- } else {
- this.nextTick = this.nextTick + 12000 + randomSource.nextInt(1200);
- long l = level.getDayTime() / 24000L;
- if (l < 5L || !level.isDay()) {
- return 0;
- } else if (randomSource.nextInt(5) != 0) {
- return 0;
- } else {
- int size = level.players().size();
+ // this.nextTick--;
+ // if (this.nextTick > 0) {
+ // return 0;
+ // } else {
+ // this.nextTick = this.nextTick + 12000 + randomSource.nextInt(1200);
+ // long l = level.getDayTime() / 24000L;
+ // if (l < 5L || !level.isDay()) {
+ // return 0;
+ // } else if (randomSource.nextInt(5) != 0) {
+ // Paper start - Pillager patrol spawn settings and per player options
+ // Random player selection moved up for per player spawning and configuration
+ int size = level.players().size();
+ if (size < 1) {
+ return 0;
+ }
+
+ net.minecraft.server.level.ServerPlayer player = level.players().get(randomSource.nextInt(size));
+ if (player.isSpectator()) {
+ return 0;
+ }
+
+ int patrolSpawnDelay;
+ if (level.paperConfig().entities.behavior.pillagerPatrols.spawnDelay.perPlayer) {
+ --player.patrolSpawnDelay;
+ patrolSpawnDelay = player.patrolSpawnDelay;
+ } else {
+ this.nextTick--;
+ patrolSpawnDelay = this.nextTick;
+ }
+ if (patrolSpawnDelay > 0) {
+ return 0;
+ } else {
+ long days;
+ if (level.paperConfig().entities.behavior.pillagerPatrols.start.perPlayer) {
+ days = player.getStats().getValue(net.minecraft.stats.Stats.CUSTOM.get(net.minecraft.stats.Stats.PLAY_TIME)) / 24000L; // PLAY_ONE_MINUTE is actually counting in ticks, a misnomer by Mojang
+ } else {
+ days = level.getDayTime() / 24000L;
+ }
+ if (level.paperConfig().entities.behavior.pillagerPatrols.spawnDelay.perPlayer) {
+ player.patrolSpawnDelay += level.paperConfig().entities.behavior.pillagerPatrols.spawnDelay.ticks + randomSource.nextInt(1200);
+ } else {
+ this.nextTick += level.paperConfig().entities.behavior.pillagerPatrols.spawnDelay.ticks + randomSource.nextInt(1200);
+ }
+
+ if (days < level.paperConfig().entities.behavior.pillagerPatrols.start.day || !level.isDay()) {
+ return 0;
+ } else if (randomSource.nextDouble() >= level.paperConfig().entities.behavior.pillagerPatrols.spawnChance) {
+ // Paper end - Pillager patrol spawn settings and per player options
+ return 0;
+ } else {
if (size < 1) {
return 0;
} else {
- Player player = level.players().get(randomSource.nextInt(size));
if (player.isSpectator()) {
return 0;
} else if (level.isCloseToVillage(player.blockPosition(), 2)) {
@@ -104,7 +_,7 @@
patrollingMonster.setPos(pos.getX(), pos.getY(), pos.getZ());
patrollingMonster.finalizeSpawn(level, level.getCurrentDifficultyAt(pos), EntitySpawnReason.PATROL, null);
- level.addFreshEntityWithPassengers(patrollingMonster);
+ level.addFreshEntityWithPassengers(patrollingMonster, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.PATROL); // CraftBukkit
return true;
} else {
return false;

View File

@@ -0,0 +1,67 @@
--- a/net/minecraft/world/level/levelgen/PhantomSpawner.java
+++ b/net/minecraft/world/level/levelgen/PhantomSpawner.java
@@ -28,19 +_,28 @@
} else if (!level.getGameRules().getBoolean(GameRules.RULE_DOINSOMNIA)) {
return 0;
} else {
+ // Paper start - Ability to control player's insomnia and phantoms
+ if (level.paperConfig().entities.behavior.phantomsSpawnAttemptMaxSeconds <= 0) {
+ return 0;
+ }
+ // Paper end - Ability to control player's insomnia and phantoms
RandomSource randomSource = level.random;
this.nextTick--;
if (this.nextTick > 0) {
return 0;
} else {
- this.nextTick = this.nextTick + (60 + randomSource.nextInt(60)) * 20;
+ // Paper start - Ability to control player's insomnia and phantoms
+ int spawnAttemptMinSeconds = level.paperConfig().entities.behavior.phantomsSpawnAttemptMinSeconds;
+ int spawnAttemptMaxSeconds = level.paperConfig().entities.behavior.phantomsSpawnAttemptMaxSeconds;
+ this.nextTick += (spawnAttemptMinSeconds + randomSource.nextInt(spawnAttemptMaxSeconds - spawnAttemptMinSeconds + 1)) * 20;
+ // Paper end - Ability to control player's insomnia and phantoms
if (level.getSkyDarken() < 5 && level.dimensionType().hasSkyLight()) {
return 0;
} else {
int i = 0;
for (ServerPlayer serverPlayer : level.players()) {
- if (!serverPlayer.isSpectator()) {
+ if (!serverPlayer.isSpectator() && (!level.paperConfig().entities.behavior.phantomsDoNotSpawnOnCreativePlayers || !serverPlayer.isCreative())) { // Paper - Add phantom creative and insomniac controls
BlockPos blockPos = serverPlayer.blockPosition();
if (!level.dimensionType().hasSkyLight() || blockPos.getY() >= level.getSeaLevel() && level.canSeeSky(blockPos)) {
DifficultyInstance currentDifficultyAt = level.getCurrentDifficultyAt(blockPos);
@@ -48,7 +_,7 @@
ServerStatsCounter stats = serverPlayer.getStats();
int i1 = Mth.clamp(stats.getValue(Stats.CUSTOM.get(Stats.TIME_SINCE_REST)), 1, Integer.MAX_VALUE);
int i2 = 24000;
- if (randomSource.nextInt(i1) >= 72000) {
+ if (randomSource.nextInt(i1) >= level.paperConfig().entities.behavior.playerInsomniaStartTicks) { // Paper - Ability to control player's insomnia and phantoms
BlockPos blockPos1 = blockPos.above(20 + randomSource.nextInt(15))
.east(-10 + randomSource.nextInt(21))
.south(-10 + randomSource.nextInt(21));
@@ -59,13 +_,23 @@
int i3 = 1 + randomSource.nextInt(currentDifficultyAt.getDifficulty().getId() + 1);
for (int i4 = 0; i4 < i3; i4++) {
+ // Paper start - PhantomPreSpawnEvent
+ com.destroystokyo.paper.event.entity.PhantomPreSpawnEvent event = new com.destroystokyo.paper.event.entity.PhantomPreSpawnEvent(io.papermc.paper.util.MCUtil.toLocation(level, blockPos1), serverPlayer.getBukkitEntity(), org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.NATURAL);
+ if (!event.callEvent()) {
+ if (event.shouldAbortSpawn()) {
+ break;
+ }
+ continue;
+ }
+ // Paper end - PhantomPreSpawnEvent
Phantom phantom = EntityType.PHANTOM.create(level, EntitySpawnReason.NATURAL);
if (phantom != null) {
+ phantom.setSpawningEntity(serverPlayer.getUUID()); // Paper - PhantomPreSpawnEvent
phantom.moveTo(blockPos1, 0.0F, 0.0F);
spawnGroupData = phantom.finalizeSpawn(
level, currentDifficultyAt, EntitySpawnReason.NATURAL, spawnGroupData
);
- level.addFreshEntityWithPassengers(phantom);
+ level.addFreshEntityWithPassengers(phantom, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.NATURAL); // CraftBukkit
i++;
}
}