--- a/net/minecraft/world/level/levelgen/PhantomSpawner.java
+++ b/net/minecraft/world/level/levelgen/PhantomSpawner.java
@@ -25,13 +_,22 @@
     public void tick(ServerLevel level, boolean spawnEnemies, boolean spawnFriendlies) {
         if (spawnEnemies) {
             if (level.getGameRules().getBoolean(GameRules.RULE_DOINSOMNIA)) {
+                // Paper start - Ability to control player's insomnia and phantoms
+                if (level.paperConfig().entities.behavior.phantomsSpawnAttemptMaxSeconds <= 0) {
+                    return;
+                }
+                // Paper end - Ability to control player's insomnia and phantoms
                 RandomSource randomSource = level.random;
                 this.nextTick--;
                 if (this.nextTick <= 0) {
-                    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()) {
                         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);
@@ -50,13 +_,23 @@
                                                 int i2 = 1 + randomSource.nextInt(currentDifficultyAt.getDifficulty().getId() + 1);
 
                                                 for (int i3 = 0; i3 < i2; i3++) {
+                                                    // Paper start - PhantomPreSpawnEvent
+                                                    com.destroystokyo.paper.event.entity.PhantomPreSpawnEvent event = new com.destroystokyo.paper.event.entity.PhantomPreSpawnEvent(org.bukkit.craftbukkit.util.CraftLocation.toBukkit(blockPos1, level), 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.spawningEntity = serverPlayer.getUUID(); // Paper - PhantomPreSpawnEvent
                                                         phantom.snapTo(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.PATROL); // CraftBukkit
                                                     }
                                                 }
                                             }
