From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: William Blake Galbreath 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 cef8e9b379c4205386d1001e86abc7dcb0b18eb6..4fa0f6ce7f8e6f5fba68d66a2c81ad4a53ca2146 100644 --- a/src/main/java/net/minecraft/world/level/World.java +++ b/src/main/java/net/minecraft/world/level/World.java @@ -1749,6 +1749,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 d5e1ca888c6fe0910f54e30b3b59af4dfde86cb3..104947fbf7c68c94e5b0b72b13307197e041ae1c 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -352,10 +352,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;