Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New behaviors of mobs and dispenser 生物与发射器的新功能 #1456

Merged
merged 12 commits into from
Jan 9, 2025
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Implemented the "punishment for greed" feature for piglin
YocyCraft committed Jan 2, 2025
commit eb258d21ae72edf528fbee8a38e63c70c046059c
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"values": [
"anvilcraft:cursed_gold_block",
"anvilcraft:cursed_gold_ingot",
"anvilcraft:cursed_gold_nugget"
]
}
Original file line number Diff line number Diff line change
@@ -1,23 +1,34 @@
package dev.dubhe.anvilcraft.event;

import com.google.common.collect.ImmutableList;
import dev.dubhe.anvilcraft.AnvilCraft;
import dev.dubhe.anvilcraft.init.ModItems;

import dev.dubhe.anvilcraft.loot.functions.CurseLootItemFunction;
import net.minecraft.advancements.critereon.EntityPredicate;
import net.minecraft.advancements.critereon.NbtPredicate;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.storage.loot.BuiltInLootTables;
import net.minecraft.world.level.storage.loot.LootContext;
import net.minecraft.world.level.storage.loot.LootPool;
import net.minecraft.world.level.storage.loot.LootTable;
import net.minecraft.world.level.storage.loot.entries.LootItem;
import net.minecraft.world.level.storage.loot.functions.LootItemFunction;
import net.minecraft.world.level.storage.loot.functions.LootItemFunctions;
import net.minecraft.world.level.storage.loot.functions.SetItemCountFunction;
import net.minecraft.world.level.storage.loot.predicates.LootItemEntityPropertyCondition;
import net.minecraft.world.level.storage.loot.providers.number.ConstantValue;
import net.minecraft.world.level.storage.loot.providers.number.UniformGenerator;
import net.neoforged.bus.api.SubscribeEvent;
import net.neoforged.fml.common.EventBusSubscriber;
import net.neoforged.neoforge.attachment.AttachmentHolder;
import net.neoforged.neoforge.event.LootTableLoadEvent;

import org.jetbrains.annotations.NotNull;

import java.util.List;

@EventBusSubscriber(modid = AnvilCraft.MOD_ID)
public class LootTableEventListener {
/**
@@ -55,6 +66,26 @@ public static void lootTable(@NotNull LootTableLoadEvent event) {
.apply(SetItemCountFunction.setCount(UniformGenerator.between(1, 5))))
.build());
}
if (EntityType.ZOMBIFIED_PIGLIN.getDefaultLootTable().location().equals(id)) {
CompoundTag cursedTag = new CompoundTag();
cursedTag.putBoolean("anvilcraft:zombificated_by_curse", true);
CompoundTag attachmentTag = new CompoundTag();
attachmentTag.put(AttachmentHolder.ATTACHMENTS_NBT_KEY, cursedTag);
LootItemFunction convertToCursed = new CurseLootItemFunction(List.of(
LootItemEntityPropertyCondition.hasProperties(
LootContext.EntityTarget.THIS,
EntityPredicate.Builder.entity()
.of(EntityType.ZOMBIFIED_PIGLIN)
.nbt(new NbtPredicate(attachmentTag))
.build()
).build()
));
table.functions = ImmutableList.<LootItemFunction>builder()
.addAll(table.functions)
.add(convertToCursed)
.build();
table.compositeFunction = LootItemFunctions.compose(table.functions);
}
event.setTable(table);
}
}
1 change: 1 addition & 0 deletions src/main/java/dev/dubhe/anvilcraft/init/ModBlocks.java
Original file line number Diff line number Diff line change
@@ -2055,6 +2055,7 @@ public class ModBlocks {
.block("cursed_gold_block", Block::new)
.initialProperties(() -> Blocks.GOLD_BLOCK)
.item(CursedBlockItem::new)
.tag(ItemTags.PIGLIN_LOVED)
.build()
.tag(BlockTags.MINEABLE_WITH_PICKAXE,
BlockTags.NEEDS_IRON_TOOL,
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package dev.dubhe.anvilcraft.init;

import com.mojang.serialization.Codec;
import net.neoforged.bus.api.IEventBus;
import net.neoforged.neoforge.attachment.AttachmentType;
import net.neoforged.neoforge.registries.DeferredRegister;
@@ -23,7 +24,10 @@ public class ModDataAttachments {
"discount_rate", () -> AttachmentType.builder(() -> 0f).build());

public static final Supplier<AttachmentType<Boolean>> IMMUNE_TO_LIGHTNING = ATTACHMENT_TYPES.register(
"immune_to_lightning", () -> AttachmentType.builder(() -> false).build());
"immune_to_lightning", () -> AttachmentType.builder(() -> false).build());

public static final Supplier<AttachmentType<Boolean>> ZOMBIFICATED_BY_CURSE = ATTACHMENT_TYPES.register(
"zombificated_by_curse", () -> AttachmentType.builder(() -> false).serialize(Codec.BOOL).build());

public static void register(IEventBus eventBus) {
ATTACHMENT_TYPES.register(eventBus);
4 changes: 3 additions & 1 deletion src/main/java/dev/dubhe/anvilcraft/init/ModItems.java
Original file line number Diff line number Diff line change
@@ -608,7 +608,8 @@ public class ModItems {
// 诅咒黄金系
public static final ItemEntry<CursedItem> CURSED_GOLD_INGOT = REGISTRATE
.item("cursed_gold_ingot", CursedItem::new)
.tag(ItemTags.BEACON_PAYMENT_ITEMS)
.tag(ItemTags.BEACON_PAYMENT_ITEMS,
ItemTags.PIGLIN_LOVED)
.recipe((ctx, provider) -> {
ShapelessRecipeBuilder.shapeless(RecipeCategory.MISC, ctx.get(), 9)
.requires(ModBlocks.CURSED_GOLD_BLOCK)
@@ -631,6 +632,7 @@ public class ModItems {
.register();
public static final ItemEntry<CursedItem> CURSED_GOLD_NUGGET = REGISTRATE
.item("cursed_gold_nugget", CursedItem::new)
.tag(ItemTags.PIGLIN_LOVED)
.recipe((ctx, provider) -> {
ShapelessRecipeBuilder.shapeless(RecipeCategory.MISC, ctx.get(), 9)
.requires(ModItems.CURSED_GOLD_INGOT)
17 changes: 17 additions & 0 deletions src/main/java/dev/dubhe/anvilcraft/init/ModLootItemFunctions.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package dev.dubhe.anvilcraft.init;

import dev.dubhe.anvilcraft.AnvilCraft;
import dev.dubhe.anvilcraft.loot.functions.CurseLootItemFunction;
import net.minecraft.core.registries.Registries;
import net.minecraft.world.level.storage.loot.functions.LootItemFunctionType;
import net.neoforged.neoforge.registries.DeferredRegister;

import java.util.function.Supplier;

public class ModLootItemFunctions {
public static final DeferredRegister<LootItemFunctionType<?>> LOOT_FUNCTION_TYPES =
DeferredRegister.create(Registries.LOOT_FUNCTION_TYPE, AnvilCraft.MOD_ID);

public static final Supplier<LootItemFunctionType<CurseLootItemFunction>> CURSE_LOOT =
LOOT_FUNCTION_TYPES.register("curse_loot", () -> new LootItemFunctionType<>(CurseLootItemFunction.CODEC));
}
5 changes: 5 additions & 0 deletions src/main/java/dev/dubhe/anvilcraft/item/CursedBlockItem.java
Original file line number Diff line number Diff line change
@@ -22,4 +22,9 @@ public void inventoryTick(ItemStack stack, Level level, Entity entity, int slotI
super.inventoryTick(stack, level, entity, slotId, isSelected);
ICursed.super.inventoryTick(stack, level, entity, slotId, isSelected);
}

@Override
public boolean isPiglinCurrency(ItemStack stack) {
return ICursed.super.isPiglinCurrency(stack);
}
}
10 changes: 8 additions & 2 deletions src/main/java/dev/dubhe/anvilcraft/item/CursedItem.java
Original file line number Diff line number Diff line change
@@ -5,17 +5,23 @@
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;

import org.jetbrains.annotations.NotNull;
import javax.annotation.ParametersAreNonnullByDefault;

@ParametersAreNonnullByDefault
public class CursedItem extends Item implements ICursed {
public CursedItem(Properties properties) {
super(properties);
}

@Override
public void inventoryTick(
@NotNull ItemStack stack, @NotNull Level level, @NotNull Entity entity, int slotId, boolean isSelected) {
ItemStack stack, Level level, Entity entity, int slotId, boolean isSelected) {
super.inventoryTick(stack, level, entity, slotId, isSelected);
ICursed.super.inventoryTick(stack, level, entity, slotId, isSelected);
}

@Override
public boolean isPiglinCurrency(ItemStack stack) {
return ICursed.super.isPiglinCurrency(stack);
}
}
4 changes: 4 additions & 0 deletions src/main/java/dev/dubhe/anvilcraft/item/ICursed.java
Original file line number Diff line number Diff line change
@@ -39,6 +39,10 @@ default void inventoryTick(ItemStack stack, Level level, Entity entity, int slot
}
}

default boolean isPiglinCurrency(ItemStack stack) {
return true;
}

/**
* 统计诅咒物品数量
*
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package dev.dubhe.anvilcraft.loot.functions;

import com.mojang.serialization.MapCodec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import dev.dubhe.anvilcraft.init.ModBlocks;
import dev.dubhe.anvilcraft.init.ModItems;
import dev.dubhe.anvilcraft.init.ModLootItemFunctions;
import net.minecraft.MethodsReturnNonnullByDefault;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.level.storage.loot.LootContext;
import net.minecraft.world.level.storage.loot.functions.LootItemConditionalFunction;
import net.minecraft.world.level.storage.loot.functions.LootItemFunctionType;
import net.minecraft.world.level.storage.loot.predicates.LootItemCondition;

import javax.annotation.ParametersAreNonnullByDefault;
import java.util.List;

@ParametersAreNonnullByDefault
@MethodsReturnNonnullByDefault
public class CurseLootItemFunction extends LootItemConditionalFunction {

public static final MapCodec<CurseLootItemFunction> CODEC = RecordCodecBuilder.mapCodec(
p_298746_ -> commonFields(p_298746_).apply(p_298746_, CurseLootItemFunction::new)
);

public CurseLootItemFunction(List<LootItemCondition> predicates) {
super(predicates);
}

@Override
public LootItemFunctionType<? extends LootItemConditionalFunction> getType() {
return ModLootItemFunctions.CURSE_LOOT.get();
}

@Override
protected ItemStack run(ItemStack stack, LootContext context) {
if (stack.is(Items.GOLD_NUGGET)) return ModItems.CURSED_GOLD_NUGGET.asStack(stack.getCount());
if (stack.is(Items.GOLD_INGOT)) return ModItems.CURSED_GOLD_INGOT.asStack(stack.getCount());
if (stack.is(Items.GOLD_BLOCK)) return ModBlocks.CURSED_GOLD_BLOCK.asStack(stack.getCount());
return stack;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package dev.dubhe.anvilcraft.mixin.piglin;

import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.Mob;
import net.minecraft.world.entity.monster.ZombifiedPiglin;
import net.minecraft.world.entity.monster.piglin.AbstractPiglin;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;

import static dev.dubhe.anvilcraft.init.ModDataAttachments.ZOMBIFICATED_BY_CURSE;

@Mixin(AbstractPiglin.class)
public class AbstractPiglinMixin {

@WrapOperation(
method = "finishConversion",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/world/entity/monster/piglin/AbstractPiglin;convertTo" +
"(Lnet/minecraft/world/entity/EntityType;Z)Lnet/minecraft/world/entity/Mob;"
)
)
private Mob punishmentForGreed(
AbstractPiglin piglin,
EntityType<ZombifiedPiglin> type,
boolean transferInventory,
Operation<ZombifiedPiglin> original) {
boolean cursed = piglin.getData(ZOMBIFICATED_BY_CURSE);
Mob zombifiedPiglin = original.call(piglin, type, transferInventory);
if (cursed) {
zombifiedPiglin.setData(ZOMBIFICATED_BY_CURSE, true);
}
return zombifiedPiglin;
}
}
46 changes: 46 additions & 0 deletions src/main/java/dev/dubhe/anvilcraft/mixin/piglin/PiglinMixin.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package dev.dubhe.anvilcraft.mixin.piglin;

import dev.dubhe.anvilcraft.init.ModDataAttachments;
import dev.dubhe.anvilcraft.item.ICursed;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.monster.piglin.AbstractPiglin;
import net.minecraft.world.entity.monster.piglin.Piglin;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;

@Mixin(Piglin.class)
public abstract class PiglinMixin extends AbstractPiglin {

@Unique
private static final int MIN_CURSED_ZOMBIFICATION_TIME = 60;
@Unique
private static final int MAX_CURSED_ZOMBIFICATION_TIME = 100;

private PiglinMixin(EntityType<? extends AbstractPiglin> entityType, Level level) {
super(entityType, level);
}

@Inject(
method = "holdInOffHand",
at = @At(value = "HEAD")
)
private void startCursedZombification(ItemStack stack, CallbackInfo ci) {
if (!(stack.getItem() instanceof ICursed)) return;
this.timeInOverworld = CONVERSION_TIME - this.level().getRandom().nextIntBetweenInclusive(
MIN_CURSED_ZOMBIFICATION_TIME, MAX_CURSED_ZOMBIFICATION_TIME);
this.setData(ModDataAttachments.ZOMBIFICATED_BY_CURSE, true);
}

@Override
public boolean isConverting() {
if (this.getOffhandItem().getItem() instanceof ICursed) {
return true;
}
return super.isConverting();
}
}
2 changes: 2 additions & 0 deletions src/main/resources/META-INF/accesstransformer.cfg
Original file line number Diff line number Diff line change
@@ -38,6 +38,8 @@ public net.minecraft.world.item.crafting.ShapedRecipe result # result
public net.minecraft.world.item.crafting.ShapelessRecipe result # result

public net.minecraft.world.level.storage.loot.parameters.LootContextParamSets REGISTRY # REGISTRY
public-f net.minecraft.world.level.storage.loot.LootTable functions
public-f net.minecraft.world.level.storage.loot.LootTable compositeFunction

public net.minecraft.world.inventory.AbstractContainerMenu stillValid(Lnet/minecraft/world/inventory/ContainerLevelAccess;Lnet/minecraft/world/entity/player/Player;Lnet/minecraft/world/level/block/Block;)Z # stillValid

4 changes: 3 additions & 1 deletion src/main/resources/anvilcraft.mixins.json
Original file line number Diff line number Diff line change
@@ -32,7 +32,9 @@
"forge.FallingBlockEntityMixin",
"forge.LevelChunkMixin",
"forge.LightningBoltMixin",
"forge.PistonMovingBlockEntityMixin"
"forge.PistonMovingBlockEntityMixin",
"piglin.AbstractPiglinMixin",
"piglin.PiglinMixin"
],
"client": [
"ClientLevelMixin",