Skip to content

Commit

Permalink
backport 1.21.1 fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
Xalcon committed Sep 26, 2024
1 parent 91dd4a0 commit d1c9e7d
Show file tree
Hide file tree
Showing 15 changed files with 173 additions and 139 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
## v21.0.3
- Fix crash when spawning a warden in an ancient city on fabric mod loader
- Improve compatibility with other fabric mods
- Re-enable mob spawn blocking during chunk generation inside blocking volumes
- Fix spawn blocking of spawners not working when `blockOnlyNaturalSpawns` is set to `false`
- Fix Feral Flare Lantern not rendering its stand

## v21.0.2
- Downgrade to MC 1.21 for fabric compatibility
- FIX: Improve blocking logic (fabric, neoforge)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import net.minecraft.world.item.context.BlockPlaceContext;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.block.*;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.BlockEntityTicker;
Expand All @@ -26,7 +27,7 @@ public class FeralFlareLanternBlock extends DirectionalBlock implements EntityBl
public FeralFlareLanternBlock(Properties properties)
{
super(properties);
this.registerDefaultState(this.getStateDefinition().any().setValue(FACING, Direction.SOUTH));
this.registerDefaultState(this.defaultBlockState().setValue(FACING, Direction.SOUTH));
}

@Override
Expand All @@ -43,7 +44,7 @@ public VoxelShape getShape(BlockState state, BlockGetter worldIn, BlockPos pos,

@Override
public BlockState getStateForPlacement(BlockPlaceContext context) {
return this.defaultBlockState().setValue(FACING, context.getNearestLookingDirection());
return this.defaultBlockState().setValue(FACING, context.getClickedFace().getOpposite());
}

@Override
Expand All @@ -52,23 +53,21 @@ protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockSt
}

@Override
public BlockState rotate(BlockState state, Rotation rot)
public void onRemove(BlockState state, Level level, BlockPos pos, BlockState oldState, boolean moving)
{
return state.setValue(FACING, rot.rotate(state.getValue(FACING)));
}
if(level.getBlockEntity(pos) instanceof FeralFlareLanternBlockEntity te)
te.removeChildLights();

@Override
public BlockState mirror(BlockState state, Mirror mirrorIn) {
return state.rotate(mirrorIn.getRotation(state.getValue(FACING)));
super.onRemove(state, level, pos, oldState, moving);
}

@Override
public void onRemove(BlockState state, Level world, BlockPos pos, BlockState oldState, boolean moving) {
var te = world.getBlockEntity(pos);
if(te instanceof FeralFlareLanternBlockEntity)
((FeralFlareLanternBlockEntity) te).removeChildLights();
public void destroy(LevelAccessor level, BlockPos pos, BlockState state)
{
if(level.getBlockEntity(pos) instanceof FeralFlareLanternBlockEntity te)
te.removeChildLights();

super.onRemove(state, world, pos, oldState, moving);
super.destroy(level, pos, state);
}

@Nullable
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ public String getTranslationKey()
}
}

@SuppressWarnings({"unchecked", "rawtypes"})
public static void register(CommandDispatcher<CommandSourceStack> dispatcher)
{
LiteralArgumentBuilder<CommandSourceStack> command = Commands.literal("torchmaster");
Expand All @@ -97,9 +98,6 @@ public static void register(CommandDispatcher<CommandSourceStack> dispatcher)

dispatcher.register(
(LiteralArgumentBuilder) ((LiteralArgumentBuilder) command.requires((cmdSrc) -> cmdSrc.hasPermission(2)))
.executes((ctx) ->
{
return 0;
}));
.executes((ctx) -> 0));
}
}
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
package net.xalcon.torchmaster.compat;

import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.MobCategory;
import net.xalcon.torchmaster.EntityFilterList;

public class VanillaCompat
{
public static void registerTorchEntities(EntityFilterList registry)
{
// TODO: Fix deprecation warning
BuiltInRegistries.ENTITY_TYPE.stream()
.map(entityType -> new EntityInfoWrapper(entityType.builtInRegistryHolder().key().location(), entityType))
.map(entityType -> new EntityInfoWrapper(EntityType.getKey(entityType), entityType))
.filter(e -> e.getEntityType() != null) // dont ask me why, but some ResourceLocations return null, i.e. minecraft:lightning_bolt
.filter(e -> !e.getEntityType().getCategory().isFriendly())
.forEach(e -> registry.registerEntity(e.getEntityName()));
Expand All @@ -19,9 +19,8 @@ public static void registerTorchEntities(EntityFilterList registry)

public static void registerDreadLampEntities(EntityFilterList registry)
{
// TODO: Fix deprecation warning
BuiltInRegistries.ENTITY_TYPE.stream()
.map(entityType -> new EntityInfoWrapper(entityType.builtInRegistryHolder().key().location(), entityType))
.map(entityType -> new EntityInfoWrapper(EntityType.getKey(entityType), entityType))
.filter(e -> e.getEntityType() != null) // dont ask me why, but some ResourceLocations return null, i.e. minecraft:lightning_bolt
.filter(e -> {
MobCategory cat = e.getEntityType().getCategory();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,64 @@
{
"variants": {
"facing=south": { "model": "torchmaster:block/feral_flare_lantern" },
"facing=north": { "model": "torchmaster:block/feral_flare_lantern" },
"facing=east": { "model": "torchmaster:block/feral_flare_lantern" },
"facing=west": { "model": "torchmaster:block/feral_flare_lantern" },
"facing=up": { "model": "torchmaster:block/feral_flare_lantern" },
"facing=down": { "model": "torchmaster:block/feral_flare_lantern" }
}
}
"multipart": [
{
"apply": {
"model": "torchmaster:block/feral_flare_lantern"
}
},
{
"apply": {
"model": "torchmaster:block/feral_flare_lantern_stand",
"x": 90
},
"when": {
"facing": "south"
}
},
{
"apply": {
"model": "torchmaster:block/feral_flare_lantern_stand",
"x": 270
},
"when": {
"facing": "north"
}
},
{
"apply": {
"model": "torchmaster:block/feral_flare_lantern_stand",
"x": 270,
"y": 90
},
"when": {
"facing": "east"
}
},
{
"apply": {
"model": "torchmaster:block/feral_flare_lantern_stand",
"x": 90,
"y": 90
},
"when": {
"facing": "west"
}
},
{
"apply": {
"model": "torchmaster:block/feral_flare_lantern_stand",
"x": 180
},
"when": {
"facing": "up"
}
},
{
"apply": {
"model": "torchmaster:block/feral_flare_lantern_stand"
},
"when": {
"facing": "down"
}
}
]
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"glass": "minecraft:block/glass"
},
"parent": "block/block",
"render_type": "minecraft:cutout",
"elements": [
{
"__comment": "Cube9",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,35 +1,28 @@
package net.xalcon.torchmaster.mixin;


import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
import net.minecraft.world.entity.Mob;
import net.minecraft.world.entity.MobSpawnType;
import net.minecraft.world.level.BaseSpawner;
import net.minecraft.world.level.LevelAccessor;
import net.xalcon.torchmaster.events.EventResult;
import net.xalcon.torchmaster.events.EventResultContainer;
import net.xalcon.torchmaster.events.TorchmasterEventHandler;
import net.xalcon.torchmaster.utils.MobWrapper;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;

@Mixin(value = BaseSpawner.class, priority = 100)
public abstract class BaseSpawnerMixin
{
@Redirect(
method = "serverTick",
@WrapOperation(
method = "serverTick(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/core/BlockPos;)V",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/world/entity/Mob;checkSpawnRules(Lnet/minecraft/world/level/LevelAccessor;Lnet/minecraft/world/entity/MobSpawnType;)Z"
)
)
private static boolean torchmaster_serverTick_checkSpawnRules(Mob mob, LevelAccessor level, MobSpawnType mobSpawnType)
private static boolean torchmaster_serverTick_checkSpawnRules(Mob mob, LevelAccessor level, MobSpawnType mobSpawnType, Operation<Boolean> original)
{
var container = new EventResultContainer(EventResult.DEFAULT);
TorchmasterEventHandler.onCheckSpawn(mobSpawnType, mob, mob.position(), container);
return switch(container.getResult())
{
case DEFAULT -> mob.checkSpawnRules(level, mobSpawnType);
case ALLOW -> true;
case DENY -> false;
};
return MobWrapper.checkSpawnRules(mob, level, mobSpawnType, original);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,25 +1,19 @@
package net.xalcon.torchmaster.mixin;

import com.llamalad7.mixinextras.sugar.Local;
import com.llamalad7.mixinextras.sugar.ref.LocalRef;
import net.minecraft.server.level.ServerLevel;
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
import net.minecraft.world.entity.Mob;
import net.minecraft.world.entity.MobSpawnType;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.NaturalSpawner;
import net.xalcon.torchmaster.events.EventResult;
import net.xalcon.torchmaster.events.EventResultContainer;
import net.xalcon.torchmaster.events.TorchmasterEventHandler;
import net.xalcon.torchmaster.utils.MobWrapper;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;

@Mixin(NaturalSpawner.class)
public abstract class NaturalSpawnerMixin
{

// Mob#checkSpawnRules is called just before spawning the entity
// This method is called twice in the NaturalSpawner class
// - isValidPositionForMob, which is used during the natural spawning cycle of an entity (i.e. low light)
Expand All @@ -30,57 +24,27 @@ public abstract class NaturalSpawnerMixin
// without calling base, our hook will not be executed
// If this happens, we will need to work something out

// It seems redirects are discouraged if compatibility is required.
// @Redirect(
// method = "net/minecraft/world/level/NaturalSpawner.isValidPositionForMob(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/entity/Mob;D)Z",
// at = @At(
// value = "INVOKE",
// target = "Lnet/minecraft/world/entity/Mob;checkSpawnRules(Lnet/minecraft/world/level/LevelAccessor;Lnet/minecraft/world/entity/MobSpawnType;)Z"
// )
// )
// private static boolean torchmaster_isValidPositionForMob_checkSpawnRules(Mob mob, LevelAccessor level, MobSpawnType mobSpawnType)
// {
// var container = new EventResultContainer(EventResult.DEFAULT);
// TorchmasterEventHandler.onCheckSpawn(mobSpawnType, mob, mob.position(), container);
// return switch(container.getResult())
// {
// case DEFAULT -> mob.checkSpawnRules(level, mobSpawnType);
// case ALLOW -> true;
// case DENY -> false;
// };
// }

@Inject(method = "isValidPositionForMob(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/entity/Mob;D)Z", at = @At("RETURN"), cancellable = true)
private static void torchmaster_isValidPositionForMob_checkSpawnRules(ServerLevel level, Mob mob, double distance, CallbackInfoReturnable<Boolean> cir)
@WrapOperation(
method = "net/minecraft/world/level/NaturalSpawner.isValidPositionForMob(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/entity/Mob;D)Z",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/world/entity/Mob;checkSpawnRules(Lnet/minecraft/world/level/LevelAccessor;Lnet/minecraft/world/entity/MobSpawnType;)Z"
)
)
private static boolean torchmaster_isValidPositionForMob_checkSpawnRules(Mob mob, LevelAccessor level, MobSpawnType mobSpawnType, Operation<Boolean> original)
{
if(cir.getReturnValueZ())
{
var container = new EventResultContainer(EventResult.DEFAULT);
TorchmasterEventHandler.onCheckSpawn(MobSpawnType.NATURAL, mob, mob.position(), container);
cir.setReturnValue(switch(container.getResult())
{
case DEFAULT, ALLOW -> true;
case DENY -> false;
});
}
return MobWrapper.checkSpawnRules(mob, level, mobSpawnType, original);
}

// @Redirect(
// method = "spawnMobsForChunkGeneration(Lnet/minecraft/world/level/ServerLevelAccessor;Lnet/minecraft/core/Holder;Lnet/minecraft/world/level/ChunkPos;Lnet/minecraft/util/RandomSource;)V",
// at = @At(
// value = "INVOKE",
// target = "Lnet/minecraft/world/entity/Mob;checkSpawnRules(Lnet/minecraft/world/level/LevelAccessor;Lnet/minecraft/world/entity/MobSpawnType;)Z"
// )
// )
private static boolean torchmaster_spawnMobsForChunkGeneration_checkSpawnRules(Mob mob, LevelAccessor level, MobSpawnType mobSpawnType)
@WrapOperation(
method = "spawnMobsForChunkGeneration(Lnet/minecraft/world/level/ServerLevelAccessor;Lnet/minecraft/core/Holder;Lnet/minecraft/world/level/ChunkPos;Lnet/minecraft/util/RandomSource;)V",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/world/entity/Mob;checkSpawnRules(Lnet/minecraft/world/level/LevelAccessor;Lnet/minecraft/world/entity/MobSpawnType;)Z"
)
)
private static boolean torchmaster_spawnMobsForChunkGeneration_checkSpawnRules(Mob mob, LevelAccessor level, MobSpawnType mobSpawnType, Operation<Boolean> original)
{
var container = new EventResultContainer(EventResult.DEFAULT);
TorchmasterEventHandler.onCheckSpawn(mobSpawnType, mob, mob.position(), container);
return switch(container.getResult())
{
case DEFAULT -> mob.checkSpawnRules(level, mobSpawnType);
case ALLOW -> true;
case DENY -> false;
};
return MobWrapper.checkSpawnRules(mob, level, mobSpawnType, original);
}
}
Original file line number Diff line number Diff line change
@@ -1,29 +1,27 @@
package net.xalcon.torchmaster.mixin;

import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
import net.minecraft.util.SpawnUtil;
import net.minecraft.world.entity.Mob;
import net.minecraft.world.entity.MobSpawnType;
import net.minecraft.world.level.LevelAccessor;
import net.xalcon.torchmaster.events.EventResult;
import net.xalcon.torchmaster.events.EventResultContainer;
import net.xalcon.torchmaster.events.TorchmasterEventHandler;
import net.xalcon.torchmaster.utils.MobWrapper;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;

@Mixin(SpawnUtil.class)
public abstract class SpawnUtilMixin
{
@Redirect(method = "trySpawnMob", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Mob;checkSpawnRules(Lnet/minecraft/world/level/LevelAccessor;Lnet/minecraft/world/entity/MobSpawnType;)Z"))
public boolean torchmaster_trySpawnMob_checkSpawnRules(Mob mob, LevelAccessor level, MobSpawnType mobSpawnType)
@WrapOperation(
method = "trySpawnMob",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/world/entity/Mob;checkSpawnRules(Lnet/minecraft/world/level/LevelAccessor;Lnet/minecraft/world/entity/MobSpawnType;)Z"
)
)
private static boolean torchmaster_trySpawnMob_checkSpawnRules(Mob mob, LevelAccessor level, MobSpawnType mobSpawnType, Operation<Boolean> original)
{
var container = new EventResultContainer(EventResult.DEFAULT);
TorchmasterEventHandler.onCheckSpawn(mobSpawnType, mob, mob.position(), container);
return switch(container.getResult())
{
case DEFAULT -> mob.checkSpawnRules(level, mobSpawnType);
case ALLOW -> true;
case DENY -> false;
};
return MobWrapper.checkSpawnRules(mob, level, mobSpawnType, original);
}
}
Loading

0 comments on commit d1c9e7d

Please sign in to comment.