Skip to content

Commit 77e243e

Browse files
committed
feat: Automatic Entity invulnerability
1 parent c789d69 commit 77e243e

File tree

8 files changed

+209
-2
lines changed

8 files changed

+209
-2
lines changed

src/main/java/net/modgarden/flowerbed/annotation/PatchMetadata.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*/
88
@Documented
99
@Retention(RetentionPolicy.RUNTIME)
10-
@Target(ElementType.TYPE)
10+
@Target({ElementType.TYPE, ElementType.PACKAGE})
1111
public @interface PatchMetadata {
1212
/**
1313
* A lowercase alphanumeric & underscored identifier of the patch.
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package net.modgarden.flowerbed.mixin.showcase.spawning.invulnerability;
2+
3+
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
4+
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
5+
import net.minecraft.core.BlockPos;
6+
import net.minecraft.server.level.ServerLevel;
7+
import net.minecraft.world.entity.Entity;
8+
import net.minecraft.world.entity.EntitySpawnReason;
9+
import net.minecraft.world.entity.EntityType;
10+
import net.minecraft.world.entity.decoration.ArmorStand;
11+
import net.minecraft.world.item.ArmorStandItem;
12+
import net.modgarden.flowerbed.annotation.PatchMetadata;
13+
import org.jetbrains.annotations.Nullable;
14+
import org.spongepowered.asm.mixin.Mixin;
15+
import org.spongepowered.asm.mixin.injection.At;
16+
17+
import java.util.function.Consumer;
18+
19+
@PatchMetadata(
20+
id = "armor_stand_invulnerability",
21+
description = "Makes Armor Stands invulnerable."
22+
)
23+
@Mixin(ArmorStandItem.class)
24+
public class Mixin_ArmorStandItem {
25+
@WrapOperation(
26+
method = "useOn",
27+
at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/EntityType;create(Lnet/minecraft/server/level/ServerLevel;Ljava/util/function/Consumer;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/entity/EntitySpawnReason;ZZ)Lnet/minecraft/world/entity/Entity;")
28+
)
29+
private Entity flowerbed$immortalizeArmorStand(
30+
EntityType<Entity> instance,
31+
ServerLevel level,
32+
@Nullable Consumer<Entity> consumer,
33+
BlockPos pos,
34+
EntitySpawnReason reason,
35+
boolean shouldOffsetY,
36+
boolean shouldOffsetYMore,
37+
Operation<Entity> original
38+
) {
39+
ArmorStand armorStand = (ArmorStand) original.call(instance, level, consumer, pos, reason, shouldOffsetY, shouldOffsetYMore);
40+
if (armorStand != null) {
41+
armorStand.setInvulnerable(true);
42+
}
43+
return armorStand;
44+
}
45+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package net.modgarden.flowerbed.mixin.showcase.spawning.invulnerability;
2+
3+
import com.llamalad7.mixinextras.sugar.Local;
4+
import net.minecraft.world.entity.player.Player;
5+
import net.minecraft.world.entity.vehicle.AbstractBoat;
6+
import net.minecraft.world.item.BoatItem;
7+
import net.minecraft.world.item.ItemStack;
8+
import net.minecraft.world.level.Level;
9+
import net.minecraft.world.phys.HitResult;
10+
import net.modgarden.flowerbed.annotation.PatchMetadata;
11+
import org.spongepowered.asm.mixin.Mixin;
12+
import org.spongepowered.asm.mixin.injection.At;
13+
import org.spongepowered.asm.mixin.injection.Inject;
14+
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
15+
16+
@PatchMetadata(
17+
id = "boat_item_invulnerability",
18+
description = "Makes boats invulnerable when placed."
19+
)
20+
@Mixin(BoatItem.class)
21+
public class Mixin_BoatItem {
22+
@Inject(
23+
method = "getBoat",
24+
at = @At("TAIL")
25+
)
26+
private void flowerbed$immortalizeBoat(
27+
Level level,
28+
HitResult hitResult,
29+
ItemStack stack,
30+
Player player,
31+
CallbackInfoReturnable<AbstractBoat> cir,
32+
@Local AbstractBoat boat
33+
) {
34+
boat.setInvulnerable(true);
35+
}
36+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package net.modgarden.flowerbed.mixin.showcase.spawning.invulnerability;
2+
3+
import com.llamalad7.mixinextras.sugar.Local;
4+
import net.minecraft.world.InteractionResult;
5+
import net.minecraft.world.entity.decoration.HangingEntity;
6+
import net.minecraft.world.item.HangingEntityItem;
7+
import net.minecraft.world.item.context.UseOnContext;
8+
import net.modgarden.flowerbed.annotation.PatchMetadata;
9+
import org.spongepowered.asm.mixin.Mixin;
10+
import org.spongepowered.asm.mixin.injection.At;
11+
import org.spongepowered.asm.mixin.injection.Inject;
12+
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
13+
14+
@PatchMetadata(
15+
id = "hanging_entity_item_invulnerability",
16+
description = "Makes Item Frames and other hanging entities invulnerable."
17+
)
18+
@Mixin(HangingEntityItem.class)
19+
public class Mixin_HangingEntityItem {
20+
@Inject(
21+
method = "useOn",
22+
at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/EntityType;createDefaultStackConfig(Lnet/minecraft/world/level/Level;Lnet/minecraft/world/item/ItemStack;Lnet/minecraft/world/entity/LivingEntity;)Ljava/util/function/Consumer;")
23+
)
24+
private void flowerbed$immortalizeEntity(
25+
UseOnContext context,
26+
CallbackInfoReturnable<InteractionResult> cir,
27+
@Local HangingEntity hangingEntity
28+
) {
29+
hangingEntity.setInvulnerable(true);
30+
}
31+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package net.modgarden.flowerbed.mixin.showcase.spawning.invulnerability;
2+
3+
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
4+
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
5+
import net.minecraft.core.BlockPos;
6+
import net.minecraft.server.level.ServerLevel;
7+
import net.minecraft.world.entity.Entity;
8+
import net.minecraft.world.entity.EntitySpawnReason;
9+
import net.minecraft.world.entity.EntityType;
10+
import net.minecraft.world.entity.LivingEntity;
11+
import net.minecraft.world.item.ItemStack;
12+
import net.minecraft.world.item.SpawnEggItem;
13+
import net.modgarden.flowerbed.annotation.PatchMetadata;
14+
import org.jetbrains.annotations.Nullable;
15+
import org.spongepowered.asm.mixin.Mixin;
16+
import org.spongepowered.asm.mixin.injection.At;
17+
18+
@PatchMetadata(
19+
id = "spawn_egg_invulnerability",
20+
description = "Makes all mobs spawned via spawn egg invulnerable."
21+
)
22+
@Mixin(SpawnEggItem.class)
23+
public class Mixin_SpawnEggItem {
24+
@WrapOperation(
25+
method = "useOn",
26+
at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/EntityType;spawn(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/item/ItemStack;Lnet/minecraft/world/entity/LivingEntity;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/entity/EntitySpawnReason;ZZ)Lnet/minecraft/world/entity/Entity;")
27+
)
28+
private Entity flowerbed$immortalizeEntity(
29+
EntityType<Entity> instance,
30+
ServerLevel level,
31+
@Nullable ItemStack spawnedFrom,
32+
@Nullable LivingEntity owner,
33+
BlockPos pos,
34+
EntitySpawnReason reason,
35+
boolean shouldOffsetY,
36+
boolean shouldOffsetYMore,
37+
Operation<Entity> original
38+
) {
39+
Entity entity = original.call(instance, level, spawnedFrom, owner, pos, reason, shouldOffsetY, shouldOffsetYMore);
40+
entity.setInvulnerable(true);
41+
return entity;
42+
}
43+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
package net.modgarden.flowerbed.mixin.showcase.spawning.invulnerability;
2+
3+
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
4+
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
5+
import net.minecraft.commands.CommandSourceStack;
6+
import net.minecraft.core.Holder;
7+
import net.minecraft.nbt.CompoundTag;
8+
import net.minecraft.server.commands.SummonCommand;
9+
import net.minecraft.world.entity.Entity;
10+
import net.minecraft.world.entity.EntityType;
11+
import net.minecraft.world.phys.Vec3;
12+
import net.modgarden.flowerbed.annotation.PatchMetadata;
13+
import org.spongepowered.asm.mixin.Mixin;
14+
import org.spongepowered.asm.mixin.injection.At;
15+
16+
@PatchMetadata(
17+
id = "summon_command_invulnerability",
18+
description = "Makes entities spawned using /summon invulnerable by default."
19+
)
20+
@Mixin(SummonCommand.class)
21+
public class Mixin_SummonCommand {
22+
@WrapOperation(
23+
method = "spawnEntity",
24+
at = @At(value = "INVOKE", target = "Lnet/minecraft/server/commands/SummonCommand;createEntity(Lnet/minecraft/commands/CommandSourceStack;Lnet/minecraft/core/Holder$Reference;Lnet/minecraft/world/phys/Vec3;Lnet/minecraft/nbt/CompoundTag;Z)Lnet/minecraft/world/entity/Entity;")
25+
)
26+
private static Entity flowerbed$immortalizeEntity(
27+
CommandSourceStack source,
28+
Holder.Reference<EntityType<?>> type,
29+
Vec3 pos,
30+
CompoundTag tag,
31+
boolean randomizeProperties,
32+
Operation<Entity> original
33+
) {
34+
Entity entity = original.call(source, type, pos, tag, randomizeProperties);
35+
if (!tag.contains("Invulnerable")) {
36+
entity.setInvulnerable(true);
37+
}
38+
return entity;
39+
}
40+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
@PatchMetadata(
2+
id = "invulnerability",
3+
description = "Patches that apply invulnerability to manually spawned entities."
4+
)
5+
package net.modgarden.flowerbed.mixin.showcase.spawning.invulnerability;
6+
7+
import net.modgarden.flowerbed.annotation.PatchMetadata;

src/main/resources/flowerbed.mixins.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,12 @@
1212
"Mixin_ServerPlayer",
1313
"MIxin_WitherSkullBlock",
1414
"fix.log.Mixin_IdDispatchCodec",
15-
"showcase.spawning.Mixin_TrialSpawner"
15+
"showcase.spawning.Mixin_TrialSpawner",
16+
"showcase.spawning.invulnerability.Mixin_ArmorStandItem",
17+
"showcase.spawning.invulnerability.Mixin_BoatItem",
18+
"showcase.spawning.invulnerability.Mixin_HangingEntityItem",
19+
"showcase.spawning.invulnerability.Mixin_SpawnEggItem",
20+
"showcase.spawning.invulnerability.Mixin_SummonCommand"
1621
],
1722
"injectors": {
1823
"defaultRequire": 1

0 commit comments

Comments
 (0)