Files
Purpur/patches/server/0080-Add-phantom-spawning-options.patch
BillyGalbreath 1343a05085 Updated Upstream (Paper, Tuinity, & Airplane)
Upstream has released updates that appear to apply and compile correctly

Paper Changes:
f3e541ca1 Actually list all missing hard depends (#5701)
11f83fe8e [CI-SKIP] [Auto] Rebuild Patches
a36e5d65f MC-148809: Fix incorrect structure block data length

Tuinity Changes:
f0e91a4ae Update Upstream (Paper)

Airplane Changes:
50babee71 Update Upstream (Tuinity)
85e0c63f5 Revert "Allow plugins to stupidly replace server internals"
db3fe2c70 Remove auto import
6b32e01eb Allow plugins to stupidly replace server internals
f849f00fc Flare update
ac10e43a9 Flare update
2021-05-21 17:25:12 -05:00

303 lines
17 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: William Blake Galbreath <Blake.Galbreath@GMail.com>
Date: Fri, 3 Jul 2020 00:03:52 -0500
Subject: [PATCH] Add phantom spawning options
diff --git a/src/main/java/net/minecraft/world/DifficultyDamageScaler.java b/src/main/java/net/minecraft/world/DifficultyDamageScaler.java
index c2fe4329576e6dcd5df435bc580d79a2b6db1fcd..44f19d8c8f5d344b2659cf01eb4be40f5510a2c2 100644
--- a/src/main/java/net/minecraft/world/DifficultyDamageScaler.java
+++ b/src/main/java/net/minecraft/world/DifficultyDamageScaler.java
@@ -14,6 +14,7 @@ public class DifficultyDamageScaler {
this.b = this.a(enumdifficulty, i, j, f);
}
+ public EnumDifficulty getGlobalDifficulty() { return a(); } // Purpur - OBFHELPER
public EnumDifficulty a() {
return this.a;
}
@@ -22,6 +23,7 @@ public class DifficultyDamageScaler {
return this.b;
}
+ public boolean isHarderThan(float f) { return a(f); } // Purpur - OBFHELPER
public boolean a(float f) {
return this.b > f;
}
diff --git a/src/main/java/net/minecraft/world/EnumDifficulty.java b/src/main/java/net/minecraft/world/EnumDifficulty.java
index 53fac6aa71938805264b7cc4769e63a9d4a66114..a1a80aab7ef6fdb2a35082fa452d0b46c1fcdcbe 100644
--- a/src/main/java/net/minecraft/world/EnumDifficulty.java
+++ b/src/main/java/net/minecraft/world/EnumDifficulty.java
@@ -21,6 +21,7 @@ public enum EnumDifficulty {
this.g = s;
}
+ public int getId() { return a(); } // Purpur - OBFHELPER
public int a() {
return this.f;
}
diff --git a/src/main/java/net/minecraft/world/level/IBlockLightAccess.java b/src/main/java/net/minecraft/world/level/IBlockLightAccess.java
index 8b2e57c833c03940f2e0727e00decce59f263269..642bf019d32a2fdc18718337ecfe45d24022f8bd 100644
--- a/src/main/java/net/minecraft/world/level/IBlockLightAccess.java
+++ b/src/main/java/net/minecraft/world/level/IBlockLightAccess.java
@@ -15,6 +15,7 @@ public interface IBlockLightAccess extends IBlockAccess {
return this.e().b(blockposition, i);
}
+ default boolean isSkyVisible(BlockPosition blockposition) { return e(blockposition); } // Purpur - OBFHELPER
default boolean e(BlockPosition blockposition) {
return this.getBrightness(EnumSkyBlock.SKY, blockposition) >= this.K();
}
diff --git a/src/main/java/net/minecraft/world/level/SpawnerCreature.java b/src/main/java/net/minecraft/world/level/SpawnerCreature.java
index d98526785ff2fa3b72e8ffffcb89a57a2203a5c8..7859d84471436b427138593776ebd30a0429b6b4 100644
--- a/src/main/java/net/minecraft/world/level/SpawnerCreature.java
+++ b/src/main/java/net/minecraft/world/level/SpawnerCreature.java
@@ -431,6 +431,7 @@ public final class SpawnerCreature {
return new BlockPosition(i, l, j);
}
+ public static boolean canSpawn(IBlockAccess iblockaccess, BlockPosition blockposition, IBlockData iblockdata, Fluid fluid, EntityTypes entitytypes) { return a(iblockaccess, blockposition, iblockdata, fluid, entitytypes); } // Purpur - OBFHELPER
public static boolean a(IBlockAccess iblockaccess, BlockPosition blockposition, IBlockData iblockdata, Fluid fluid, EntityTypes<?> entitytypes) {
return iblockdata.r(iblockaccess, blockposition) ? false : (iblockdata.isPowerSource() ? false : (!fluid.isEmpty() ? false : (iblockdata.a((Tag) TagsBlock.PREVENT_MOB_SPAWNING_INSIDE) ? false : !entitytypes.a(iblockdata))));
}
diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java
index b67914145517bd027f297cc4358d287b6899919f..fc5e2263d05661672b3295da46d7e7495c5b40b6 100644
--- a/src/main/java/net/minecraft/world/level/World.java
+++ b/src/main/java/net/minecraft/world/level/World.java
@@ -1757,6 +1757,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable {
return new DifficultyDamageScaler(this.getDifficulty(), this.getDayTime(), i, f);
}
+ public int getSkyDarkness() { return c(); } // Purpur - OBFHELPER
@Override
public int c() {
return this.d;
diff --git a/src/main/java/net/minecraft/world/level/levelgen/MobSpawnerPhantom.java b/src/main/java/net/minecraft/world/level/levelgen/MobSpawnerPhantom.java
index e4f5e570636862481aac92ec9b74d6cf5723eb6e..e954adeff4fbfc1aa85ac3785c0c4c86bde24cdb 100644
--- a/src/main/java/net/minecraft/world/level/levelgen/MobSpawnerPhantom.java
+++ b/src/main/java/net/minecraft/world/level/levelgen/MobSpawnerPhantom.java
@@ -1,9 +1,6 @@
package net.minecraft.world.level.levelgen;
-import java.util.Iterator;
-import java.util.Random;
import net.minecraft.core.BlockPosition;
-import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.server.MCUtil;
import net.minecraft.server.level.EntityPlayer;
import net.minecraft.server.level.WorldServer;
@@ -15,92 +12,103 @@ import net.minecraft.world.entity.EntityTypes;
import net.minecraft.world.entity.EnumMobSpawn;
import net.minecraft.world.entity.GroupDataEntity;
import net.minecraft.world.entity.monster.EntityPhantom;
-import net.minecraft.world.entity.player.EntityHuman;
import net.minecraft.world.level.GameRules;
-import net.minecraft.world.level.IBlockAccess;
import net.minecraft.world.level.MobSpawner;
import net.minecraft.world.level.SpawnerCreature;
-import net.minecraft.world.level.World;
-import net.minecraft.world.level.block.state.IBlockData;
-import net.minecraft.world.level.material.Fluid;
+import com.destroystokyo.paper.event.entity.PhantomPreSpawnEvent;
+import org.bukkit.event.entity.CreatureSpawnEvent;
public class MobSpawnerPhantom implements MobSpawner {
-
- private int a;
+ private int spawnDelay;
public MobSpawnerPhantom() {}
@Override
- public int a(WorldServer worldserver, boolean flag, boolean flag1) {
- if (!flag) {
+ public int a(WorldServer world, boolean allowMonsters, boolean allowAnimals) {
+ // Purpur start - rewrite entire thing
+ if (!allowMonsters) {
+ return 0;
+ }
+
+ if (!world.getGameRules().getBoolean(GameRules.DO_INSOMNIA)) {
return 0;
- } else if (!worldserver.getGameRules().getBoolean(GameRules.DO_INSOMNIA)) {
+ }
+
+ --this.spawnDelay;
+ if (this.spawnDelay > 0) {
return 0;
- } else {
- Random random = worldserver.random;
-
- --this.a;
- if (this.a > 0) {
- return 0;
- } else {
- this.a += (60 + random.nextInt(60)) * 20;
- if (worldserver.c() < 5 && worldserver.getDimensionManager().hasSkyLight()) {
- return 0;
- } else {
- int i = 0;
- Iterator iterator = worldserver.getPlayers().iterator();
-
- while (iterator.hasNext()) {
- EntityHuman entityhuman = (EntityHuman) iterator.next();
-
- if (!entityhuman.isSpectator() && (!worldserver.paperConfig.phantomIgnoreCreative || !entityhuman.isCreative())) { // Paper
- BlockPosition blockposition = entityhuman.getChunkCoordinates();
-
- if (!worldserver.getDimensionManager().hasSkyLight() || blockposition.getY() >= worldserver.getSeaLevel() && worldserver.e(blockposition)) {
- DifficultyDamageScaler difficultydamagescaler = worldserver.getDamageScaler(blockposition);
-
- if (difficultydamagescaler.a(random.nextFloat() * 3.0F)) {
- ServerStatisticManager serverstatisticmanager = ((EntityPlayer) entityhuman).getStatisticManager();
- int j = MathHelper.clamp(serverstatisticmanager.getStatisticValue(StatisticList.CUSTOM.b(StatisticList.TIME_SINCE_REST)), 1, Integer.MAX_VALUE);
- boolean flag2 = true;
-
- if (random.nextInt(j) >= 72000) {
- BlockPosition blockposition1 = blockposition.up(20 + random.nextInt(15)).east(-10 + random.nextInt(21)).south(-10 + random.nextInt(21));
- IBlockData iblockdata = worldserver.getType(blockposition1);
- Fluid fluid = worldserver.getFluid(blockposition1);
-
- if (SpawnerCreature.a((IBlockAccess) worldserver, blockposition1, iblockdata, fluid, EntityTypes.PHANTOM)) {
- GroupDataEntity groupdataentity = null;
- int k = 1 + random.nextInt(difficultydamagescaler.a().a() + 1);
-
- for (int l = 0; l < k; ++l) {
- // Paper start
- com.destroystokyo.paper.event.entity.PhantomPreSpawnEvent event = new com.destroystokyo.paper.event.entity.PhantomPreSpawnEvent(MCUtil.toLocation(worldserver, blockposition1), ((EntityPlayer) entityhuman).getBukkitEntity(), org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.NATURAL);
- if (!event.callEvent()) {
- if (event.shouldAbortSpawn()) {
- break;
- }
- continue;
- }
- // Paper end
- EntityPhantom entityphantom = (EntityPhantom) EntityTypes.PHANTOM.a((World) worldserver);
- entityphantom.setSpawningEntity(entityhuman.getUniqueID()); // Paper
- entityphantom.setPositionRotation(blockposition1, 0.0F, 0.0F);
- groupdataentity = entityphantom.prepare(worldserver, difficultydamagescaler, EnumMobSpawn.NATURAL, groupdataentity, (NBTTagCompound) null);
- worldserver.addAllEntities(entityphantom, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.NATURAL); // CraftBukkit
- }
-
- i += k;
- }
- }
- }
- }
- }
+ }
+ this.spawnDelay += world.purpurConfig.phantomSpawnDelayMin + world.random.nextInt(world.purpurConfig.phantomSpawnDelayMax - world.purpurConfig.phantomSpawnDelayMin);
+
+ if (!world.getDimensionManager().hasSkyLight() || world.getSkyDarkness() < world.purpurConfig.phantomSpawnMinSkyDarkness) {
+ return 0;
+ }
+
+ int numberSpawnsAttempted = 0;
+ for (EntityPlayer player : world.getPlayers()) {
+ if (player.isSpectator() || (player.isCreative() && world.paperConfig.phantomIgnoreCreative)) { // Paper
+ continue;
+ }
+
+ BlockPosition playerPos = player.getChunkCoordinates();
+ if (playerPos.getY() < world.getSeaLevel() && world.purpurConfig.phantomSpawnOnlyAboveSeaLevel) {
+ continue;
+ }
+
+ if (!world.isSkyVisible(playerPos) && world.purpurConfig.phantomSpawnOnlyWithVisibleSky) {
+ continue;
+ }
+
+ DifficultyDamageScaler dmgScaler = world.getDamageScaler(playerPos);
+ if (!dmgScaler.isHarderThan(world.random.nextFloat() * (float) world.purpurConfig.phantomSpawnLocalDifficultyChance)) {
+ continue;
+ }
+
+ ServerStatisticManager stats = player.getStatisticManager();
+ int timeSinceRest = MathHelper.clamp(stats.getStatisticValue(StatisticList.CUSTOM.get(StatisticList.TIME_SINCE_REST)), 1, Integer.MAX_VALUE);
+ if (world.random.nextInt(timeSinceRest) < world.purpurConfig.phantomSpawnMinTimeSinceSlept) {
+ continue;
+ }
+
+ BlockPosition spawnPos = playerPos
+ .up(world.purpurConfig.phantomSpawnMinOverhead + world.random.nextInt(world.purpurConfig.phantomSpawnMaxOverhead - world.purpurConfig.phantomSpawnMinOverhead))
+ .east(-world.purpurConfig.phantomSpawnOverheadRadius + world.random.nextInt(world.purpurConfig.phantomSpawnOverheadRadius + 1))
+ .south(-world.purpurConfig.phantomSpawnOverheadRadius + world.random.nextInt(world.purpurConfig.phantomSpawnOverheadRadius + 1));
+
+ if (!SpawnerCreature.canSpawn(world, spawnPos, world.getType(spawnPos), world.getFluid(spawnPos), EntityTypes.PHANTOM)) {
+ continue;
+ }
+
+ int difficulty = dmgScaler.getGlobalDifficulty().getId();
+ int spawnAttempts = world.purpurConfig.phantomSpawnMinPerAttempt + world.random.nextInt((world.purpurConfig.phantomSpawnMaxPerAttempt < 0 ? difficulty : world.purpurConfig.phantomSpawnMaxPerAttempt) + world.purpurConfig.phantomSpawnMinPerAttempt);
+
+ GroupDataEntity groupData = null;
+ for (int count = 0; count < spawnAttempts; ++count) {
+ // Paper start
+ PhantomPreSpawnEvent event = new PhantomPreSpawnEvent(MCUtil.toLocation(world, spawnPos), player.getBukkitEntity(), CreatureSpawnEvent.SpawnReason.NATURAL);
+ if (!event.callEvent()) {
+ if (event.shouldAbortSpawn()) {
+ break;
}
+ continue;
+ }
+ // Paper end
- return i;
+ EntityPhantom phantom = EntityTypes.PHANTOM.create(world);
+ if (phantom == null) {
+ continue;
}
+
+ phantom.setSpawningEntity(player.getUniqueID()); // Paper
+ phantom.setPositionRotation(spawnPos, 0.0F, 0.0F);
+ groupData = phantom.prepare(world, dmgScaler, EnumMobSpawn.NATURAL, groupData, null);
+ world.addEntity(phantom, CreatureSpawnEvent.SpawnReason.NATURAL); // CraftBukkit
}
+
+ numberSpawnsAttempted += spawnAttempts;
}
+
+ return numberSpawnsAttempted;
+ // Purpur end - rewrite entire thing
}
}
diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
index 3aec221db2cd425bc5188979bb0fc0625ca40f4a..d957ee4c10fde8596442f2f05f0347994df7bae5 100644
--- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
+++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
@@ -398,10 +398,34 @@ public class PurpurWorldConfig {
public double phantomAttackedByCrystalRadius = 0.0D;
public float phantomAttackedByCrystalDamage = 1.0F;
public double phantomOrbitCrystalRadius = 0.0D;
+ public int phantomSpawnDelayMin = 1200;
+ public int phantomSpawnDelayMax = 2400;
+ public int phantomSpawnMinSkyDarkness = 5;
+ public boolean phantomSpawnOnlyAboveSeaLevel = true;
+ public boolean phantomSpawnOnlyWithVisibleSky = true;
+ public double phantomSpawnLocalDifficultyChance = 3.0D;
+ public int phantomSpawnMinTimeSinceSlept = 72000;
+ public int phantomSpawnMinOverhead = 20;
+ public int phantomSpawnMaxOverhead = 35;
+ public int phantomSpawnOverheadRadius = 10;
+ public int phantomSpawnMinPerAttempt = 1;
+ public int phantomSpawnMaxPerAttempt = -1;
private void phantomSettings() {
phantomAttackedByCrystalRadius = getDouble("mobs.phantom.attacked-by-crystal-range", phantomAttackedByCrystalRadius);
phantomAttackedByCrystalDamage = (float) getDouble("mobs.phantom.attacked-by-crystal-damage", phantomAttackedByCrystalDamage);
phantomOrbitCrystalRadius = getDouble("mobs.phantom.orbit-crystal-radius", phantomOrbitCrystalRadius);
+ phantomSpawnDelayMin = getInt("mobs.phantom.spawn.delay.min", phantomSpawnDelayMin);
+ phantomSpawnDelayMax = getInt("mobs.phantom.spawn.delay.max", phantomSpawnDelayMax);
+ phantomSpawnMinSkyDarkness = getInt("mobs.phantom.spawn.min-sky-darkness", phantomSpawnMinSkyDarkness);
+ phantomSpawnOnlyAboveSeaLevel = getBoolean("mobs.phantom.spawn.only-above-sea-level", phantomSpawnOnlyAboveSeaLevel);
+ phantomSpawnOnlyWithVisibleSky = getBoolean("mobs.phantom.spawn.only-with-visible-sky", phantomSpawnOnlyWithVisibleSky);
+ phantomSpawnLocalDifficultyChance = getDouble("mobs.phantom.spawn.local-difficulty-chance", phantomSpawnLocalDifficultyChance);
+ phantomSpawnMinTimeSinceSlept = getInt("mobs.phantom.spawn.min-time-since-slept", phantomSpawnMinTimeSinceSlept);
+ phantomSpawnMinOverhead = getInt("mobs.phantom.spawn.overhead.min", phantomSpawnMinOverhead);
+ phantomSpawnMaxOverhead = getInt("mobs.phantom.spawn.overhead.max", phantomSpawnMaxOverhead);
+ phantomSpawnOverheadRadius = getInt("mobs.phantom.spawn.overhead.radius", phantomSpawnOverheadRadius);
+ phantomSpawnMinPerAttempt = getInt("mobs.phantom.spawn.per-attempt.min", phantomSpawnMinPerAttempt);
+ phantomSpawnMaxPerAttempt = getInt("mobs.phantom.spawn.per-attempt.max", phantomSpawnMaxPerAttempt);
}
public boolean pigGiveSaddleBack = false;