Skip to content

Commit 551a26f

Browse files
committed
add support for phantom blocking #263
1 parent 9ee6757 commit 551a26f

File tree

12 files changed

+140
-45
lines changed

12 files changed

+140
-45
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
## v21.1.7
2+
- Add support to prevent phantoms from spawning from player insomnia mechanics
3+
14
## v21.1.6
25
- Re-Added Frozen Pearl to remove residual lights from the Feral Flare Lantern
36

common/src/main/java/net/xalcon/torchmaster/events/TorchmasterEventHandler.java

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import net.minecraft.world.entity.Entity;
66
import net.minecraft.world.entity.EntityType;
77
import net.minecraft.world.entity.MobSpawnType;
8+
import net.minecraft.world.entity.player.Player;
89
import net.minecraft.world.level.Level;
910
import net.minecraft.world.phys.Vec3;
1011
import net.xalcon.torchmaster.Torchmaster;
@@ -18,14 +19,15 @@ private static boolean isIntentionalSpawn(MobSpawnType spawnType)
1819
{
1920
switch(spawnType)
2021
{
22+
case SPAWN_EGG:
2123
case BREEDING:
2224
case DISPENSER:
2325
case BUCKET:
2426
case CONVERSION:
25-
case SPAWN_EGG:
2627
case TRIGGERED:
2728
case COMMAND:
2829
case EVENT:
30+
case TRIAL_SPAWNER:
2931
return true;
3032
case NATURAL:
3133
case CHUNK_GENERATION:
@@ -49,6 +51,7 @@ private static boolean isNaturalSpawn(MobSpawnType spawnType)
4951
case PATROL: // Patrol can be considered natural
5052
default:
5153
return true;
54+
case TRIAL_SPAWNER:
5255
case BREEDING:
5356
case CONVERSION:
5457
case BUCKET:
@@ -84,18 +87,43 @@ public static void onCheckSpawn(final MobSpawnType spawnType, final Entity entit
8487
return;
8588

8689
var level = entity.getCommandSenderWorld();
90+
var entityType = entity.getType();
91+
92+
Torchmaster.getRegistryForLevel(level).ifPresent(reg ->
93+
{
94+
if(reg.shouldBlockEntityType(entityType, entity.getCommandSenderWorld(), location, spawnType))
95+
{
96+
container.setResult(EventResult.DENY);
97+
Torchmaster.LOG.debug("Blocking spawn of {}", EntityType.getKey(entityType));
98+
}
99+
else
100+
{
101+
Torchmaster.LOG.debug("Allowed spawn of {}", EntityType.getKey(entityType));
102+
}
103+
});
104+
}
105+
106+
public static void onPlayerSpawnPhantoms(Player player, final Vec3 location, final EventResultContainer container)
107+
{
108+
var config = Services.PLATFORM.getConfig();
109+
Torchmaster.LOG.debug("PlayerSpawnPhantoms - Pos: {}/{}/{}", location.x, location.y, location.z);
110+
111+
// If aggressive spawn checks are disabled, check if other mods already explicitly allowed the spawn
112+
if(!config.getAggressiveSpawnChecks() && container.getResult() == EventResult.ALLOW)
113+
return;
114+
115+
var level = player.getCommandSenderWorld();
87116

88117
Torchmaster.getRegistryForLevel(level).ifPresent(reg ->
89118
{
90-
if(reg.shouldBlockEntity(entity, entity.getCommandSenderWorld(), spawnType))
119+
if(reg.shouldBlockEntityType(EntityType.PHANTOM, level, player.position(), MobSpawnType.NATURAL))
91120
{
92121
container.setResult(EventResult.DENY);
93-
Torchmaster.LOG.debug("Blocking spawn of {}", EntityType.getKey(entity.getType()));
94-
//event.getEntity().addTag("torchmaster_removed_spawn");
122+
Torchmaster.LOG.debug("Blocking spawn of {}", EntityType.getKey(EntityType.PHANTOM));
95123
}
96124
else
97125
{
98-
Torchmaster.LOG.debug("Allowed spawn of {}", EntityType.getKey(entity.getType()));
126+
Torchmaster.LOG.debug("Allowed spawn of {}", EntityType.getKey(EntityType.PHANTOM));
99127
}
100128
});
101129
}
@@ -109,7 +137,7 @@ public static void onVillageSiege(Level level, Vec3 attemptedSpawnPos, EventResu
109137

110138
Torchmaster.getRegistryForLevel(level).ifPresent(reg ->
111139
{
112-
if(reg.shouldBlockVillagePillagerSiege(attemptedSpawnPos))
140+
if(reg.shouldBlockVillageZombieRaid(attemptedSpawnPos))
113141
{
114142
container.setResult(EventResult.DENY);
115143
Torchmaster.LOG.debug("Blocking village siege @ {}", attemptedSpawnPos);

common/src/main/java/net/xalcon/torchmaster/logic/entityblocking/FilteredLightManager.java

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import net.minecraft.nbt.ListTag;
66
import net.minecraft.nbt.Tag;
77
import net.minecraft.world.entity.Entity;
8+
import net.minecraft.world.entity.EntityType;
89
import net.minecraft.world.entity.MobSpawnType;
910
import net.minecraft.world.level.Level;
1011
import net.minecraft.world.level.saveddata.SavedData;
@@ -20,24 +21,11 @@ public class FilteredLightManager extends SavedData implements IBlockingLightMan
2021
private final Map<String, IEntityBlockingLight> lights = new HashMap<>();
2122

2223
@Override
23-
public boolean shouldBlockEntity(Entity entity, Level level, MobSpawnType spawnType)
24+
public boolean shouldBlockEntityType(EntityType<?> entityType, Level level, Vec3 pos, MobSpawnType spawnType)
2425
{
2526
for(var light: lights.values())
2627
{
27-
if(light.shouldBlockEntity(entity, level, spawnType))
28-
{
29-
return true;
30-
}
31-
}
32-
return false;
33-
}
34-
35-
@Override
36-
public boolean shouldBlockVillagePillagerSiege(Vec3 pos)
37-
{
38-
for(var light: lights.values())
39-
{
40-
if(light.shouldBlockVillagePillagerSiege(pos))
28+
if(light.shouldBlockEntityType(entityType, level, pos, spawnType))
4129
{
4230
return true;
4331
}

common/src/main/java/net/xalcon/torchmaster/logic/entityblocking/IBlockingLightManager.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import net.minecraft.nbt.CompoundTag;
44
import net.minecraft.world.entity.Entity;
5+
import net.minecraft.world.entity.EntityType;
56
import net.minecraft.world.entity.MobSpawnType;
67
import net.minecraft.world.level.Level;
78
import net.minecraft.world.phys.Vec3;
@@ -10,8 +11,7 @@
1011

1112
public interface IBlockingLightManager
1213
{
13-
boolean shouldBlockEntity(Entity entity, Level level, MobSpawnType spawnType);
14-
boolean shouldBlockVillagePillagerSiege(Vec3 pos);
14+
boolean shouldBlockEntityType(EntityType<?> entityType, Level level, Vec3 pos, MobSpawnType spawnType);
1515
boolean shouldBlockVillageZombieRaid(Vec3 pos);
1616

1717
/**

common/src/main/java/net/xalcon/torchmaster/logic/entityblocking/IEntityBlockingLight.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,15 @@
22

33
import net.minecraft.core.BlockPos;
44
import net.minecraft.world.entity.Entity;
5+
import net.minecraft.world.entity.EntityType;
56
import net.minecraft.world.entity.MobSpawnType;
67
import net.minecraft.world.level.Level;
78
import net.minecraft.world.phys.Vec3;
89

910
public interface IEntityBlockingLight
1011
{
11-
boolean shouldBlockEntity(Entity entity, Level level, MobSpawnType spawnType);
12-
boolean shouldBlockVillagePillagerSiege(Vec3 pos);
12+
//boolean shouldBlockEntity(Entity entity, Level level, EntitySpawnReason spawnType);
13+
boolean shouldBlockEntityType(EntityType<?> entityType, Level level, Vec3 pos, MobSpawnType spawnType);
1314
boolean shouldBlockVillageZombieRaid(Vec3 pos);
1415

1516
String getLightSerializerType();

common/src/main/java/net/xalcon/torchmaster/logic/entityblocking/dreadlamp/DreadLampEntityBlockingLight.java

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import net.minecraft.core.BlockPos;
44
import net.minecraft.world.entity.Entity;
55
import net.minecraft.world.entity.EntityType;
6+
import net.minecraft.world.entity.Mob;
67
import net.minecraft.world.entity.MobSpawnType;
78
import net.minecraft.world.level.Level;
89
import net.minecraft.world.level.block.Block;
@@ -25,16 +26,10 @@ public DreadLampEntityBlockingLight(BlockPos pos)
2526
}
2627

2728
@Override
28-
public boolean shouldBlockEntity(Entity entity, Level level, MobSpawnType spawnType)
29+
public boolean shouldBlockEntityType(EntityType<?> entityType, Level level, Vec3 pos, MobSpawnType spawnType)
2930
{
30-
return Torchmaster.DreadLampFilterRegistry.containsEntity(EntityType.getKey(entity.getType()))
31-
&& IDistanceLogic.Cubic.isPositionInRange(entity.getX(), entity.getY(), entity.getZ(), this.pos, Services.PLATFORM.getConfig().getDreadLampRadius());
32-
}
33-
34-
@Override
35-
public boolean shouldBlockVillagePillagerSiege(Vec3 pos)
36-
{
37-
return false;
31+
return Torchmaster.DreadLampFilterRegistry.containsEntity(EntityType.getKey(entityType))
32+
&& IDistanceLogic.Cubic.isPositionInRange(pos.x, pos.y, pos.z, this.pos, Services.PLATFORM.getConfig().getDreadLampRadius());
3833
}
3934

4035
@Override

common/src/main/java/net/xalcon/torchmaster/logic/entityblocking/megatorch/MegatorchEntityBlockingLight.java

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,16 +25,10 @@ public MegatorchEntityBlockingLight(BlockPos pos)
2525
}
2626

2727
@Override
28-
public boolean shouldBlockEntity(Entity entity, Level level, MobSpawnType spawnType)
28+
public boolean shouldBlockEntityType(EntityType<?> entityType, Level level, Vec3 pos, MobSpawnType spawnType)
2929
{
30-
return Torchmaster.MegaTorchFilterRegistry.containsEntity(EntityType.getKey(entity.getType()))
31-
&& IDistanceLogic.Cubic.isPositionInRange(entity.getX(), entity.getY(), entity.getZ(), this.pos, Services.PLATFORM.getConfig().getMegaTorchRadius());
32-
}
33-
34-
@Override
35-
public boolean shouldBlockVillagePillagerSiege(Vec3 pos)
36-
{
37-
return IDistanceLogic.Cubic.isPositionInRange(pos.x(), pos.y(), pos.z(), this.pos, Services.PLATFORM.getConfig().getMegaTorchRadius());
30+
return Torchmaster.MegaTorchFilterRegistry.containsEntity(EntityType.getKey(entityType))
31+
&& IDistanceLogic.Cubic.isPositionInRange(pos.x, pos.y, pos.z, this.pos, Services.PLATFORM.getConfig().getMegaTorchRadius());
3832
}
3933

4034
@Override
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package net.xalcon.torchmaster.mixin;
2+
3+
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
4+
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
5+
import com.llamalad7.mixinextras.sugar.Local;
6+
import net.minecraft.core.BlockPos;
7+
import net.minecraft.server.level.ServerPlayer;
8+
import net.minecraft.world.entity.EntityType;
9+
import net.minecraft.world.level.BlockGetter;
10+
import net.minecraft.world.level.block.state.BlockState;
11+
import net.minecraft.world.level.levelgen.PhantomSpawner;
12+
import net.minecraft.world.level.material.FluidState;
13+
import net.xalcon.torchmaster.utils.NaturalSpawnerWrapper;
14+
import org.spongepowered.asm.mixin.Mixin;
15+
import org.spongepowered.asm.mixin.injection.At;
16+
17+
@Mixin(PhantomSpawner.class)
18+
public abstract class PhantomSpawnerMixin {
19+
20+
@WrapOperation(
21+
method = "tick(Lnet/minecraft/server/level/ServerLevel;ZZ)V",
22+
at = @At(
23+
value = "INVOKE",
24+
target = "net/minecraft/world/level/NaturalSpawner.isValidEmptySpawnBlock(Lnet/minecraft/world/level/BlockGetter;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/world/level/material/FluidState;Lnet/minecraft/world/entity/EntityType;)Z"
25+
)
26+
)
27+
private static boolean torchmaster_tick_NaturalSpawner__isValidEmptySpawnBlock(BlockGetter block, BlockPos pos, BlockState blockState, FluidState fluidState, EntityType<?> entityType, Operation<Boolean> original, @Local ServerPlayer player)
28+
{
29+
return NaturalSpawnerWrapper.isValidEmptySpawnBlock(block, pos, blockState, fluidState, entityType, original, player);
30+
}
31+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package net.xalcon.torchmaster.utils;
2+
3+
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
4+
import net.minecraft.core.BlockPos;
5+
import net.minecraft.server.level.ServerPlayer;
6+
import net.minecraft.world.entity.EntityType;
7+
import net.minecraft.world.level.BlockGetter;
8+
import net.minecraft.world.level.block.state.BlockState;
9+
import net.minecraft.world.level.material.FluidState;
10+
import net.xalcon.torchmaster.events.EventResult;
11+
import net.xalcon.torchmaster.events.EventResultContainer;
12+
import net.xalcon.torchmaster.events.TorchmasterEventHandler;
13+
14+
public class NaturalSpawnerWrapper {
15+
16+
public static boolean isValidEmptySpawnBlock(BlockGetter block, BlockPos pos, BlockState blockState, FluidState fluidState, EntityType<?> entityType, Operation<Boolean> original, ServerPlayer player)
17+
{
18+
var container = new EventResultContainer(EventResult.DEFAULT);
19+
TorchmasterEventHandler.onPlayerSpawnPhantoms(player, player.position(), container);
20+
return switch(container.getResult())
21+
{
22+
// Make sure we call the origínal
23+
// otherwise we skip other mods down the chain (if any)
24+
// We may still run into compat issues in cases where we deny or explicitly allow the spawn,
25+
// but I'll look at those when necessary.
26+
case DEFAULT -> original.call(block, pos, blockState, fluidState, entityType);
27+
case ALLOW -> true;
28+
case DENY -> false;
29+
};
30+
}
31+
}

fabric/src/main/resources/torchmaster.fabric.mixins.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88
"NaturalSpawnerMixin",
99
"VillageSiegeMixin",
1010
"BaseSpawnerMixin",
11-
"SpawnUtilMixin"
11+
"SpawnUtilMixin",
12+
"PhantomSpawnerMixin"
1213
],
1314
"client": [],
1415
"server": [],

0 commit comments

Comments
 (0)