diff --git a/src/main/java/com/github/tartaricacid/touhoulittlemaid/api/task/IAttackTask.java b/src/main/java/com/github/tartaricacid/touhoulittlemaid/api/task/IAttackTask.java index 219cbd6ef..d3f458ac1 100644 --- a/src/main/java/com/github/tartaricacid/touhoulittlemaid/api/task/IAttackTask.java +++ b/src/main/java/com/github/tartaricacid/touhoulittlemaid/api/task/IAttackTask.java @@ -1,14 +1,20 @@ package com.github.tartaricacid.touhoulittlemaid.api.task; import com.github.tartaricacid.touhoulittlemaid.config.subconfig.MaidConfig; +import com.github.tartaricacid.touhoulittlemaid.entity.misc.DefaultMonsterType; +import com.github.tartaricacid.touhoulittlemaid.entity.misc.MonsterType; import com.github.tartaricacid.touhoulittlemaid.entity.passive.EntityMaid; +import com.github.tartaricacid.touhoulittlemaid.init.InitItems; +import com.github.tartaricacid.touhoulittlemaid.item.ItemMonsterList; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.Tag; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.TamableAnimal; import net.minecraft.world.entity.ai.memory.MemoryModuleType; -import net.minecraft.world.entity.monster.Enemy; import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; import net.minecraftforge.registries.ForgeRegistries; import java.util.Optional; @@ -25,18 +31,6 @@ static Optional findFirstValidAttackTarget(EntityMaid ma mobs -> mobs.findClosest((e) -> maid.canAttack(e) && maid.isWithinRestriction(e.blockPosition()))); } - private static boolean checkCanAttackEntity(LivingEntity target) { - // 不能攻击玩家 - if (target instanceof Player) { - return false; - } - // 有主的宠物也不攻击 - if (target instanceof TamableAnimal tamableAnimal) { - return tamableAnimal.getOwnerUUID() == null; - } - return true; - } - /** * 能否攻击该对象 * @@ -45,25 +39,41 @@ private static boolean checkCanAttackEntity(LivingEntity target) { * @return 能否攻击? */ default boolean canAttack(EntityMaid maid, LivingEntity target) { - if (maid.getOwner() instanceof Player player) { - LivingEntity lastHurtByMob = player.getLastHurtByMob(); - if (target.equals(lastHurtByMob) && checkCanAttackEntity(lastHurtByMob)) { - return true; - } - LivingEntity lastHurtMob = player.getLastHurtMob(); - if (target.equals(lastHurtMob) && checkCanAttackEntity(lastHurtMob)) { - return true; - } + // 获取实体 ID + ResourceLocation location = ForgeRegistries.ENTITY_TYPES.getKey(target.getType()); + if (location == null) { + return false; } - LivingEntity maidLastHurtByMob = maid.getLastHurtByMob(); - if (target.equals(maidLastHurtByMob) && checkCanAttackEntity(maidLastHurtByMob)) { - return true; + String id = location.toString(); + + // 模组自身强制指定的 + if (target instanceof Player) { + return false; + } + if (target instanceof TamableAnimal tamableAnimal) { + // 有主的宠物也不攻击 + return tamableAnimal.getOwnerUUID() == null; } - ResourceLocation key = ForgeRegistries.ENTITY_TYPES.getKey(target.getType()); - if (key != null && MaidConfig.MAID_ATTACK_IGNORE.get().contains(key.toString())) { + + // 判断配置文件的 + if (MaidConfig.MAID_ATTACK_IGNORE.get().contains(id)) { return false; } - return target instanceof Enemy; + + // 获取女仆副手是否有妖怪名单 + ItemStack offhandItem = maid.getOffhandItem(); + if (offhandItem.is(InitItems.MONSTER_LIST.get())) { + CompoundTag monsterList = ItemMonsterList.getMonsterList(offhandItem); + if (monsterList.contains(id, Tag.TAG_INT)) { + int index = monsterList.getInt(id); + MonsterType monsterType = MonsterType.getTypeByIndex(index); + return DefaultMonsterType.canAttack(maid, target, monsterType); + } + } + + // 那如果没有呢?走默认配置 + MonsterType monsterType = DefaultMonsterType.getMonsterType(target.getType()); + return DefaultMonsterType.canAttack(maid, target, monsterType); } default boolean hasExtraAttack(EntityMaid maid, Entity target) { diff --git a/src/main/java/com/github/tartaricacid/touhoulittlemaid/client/gui/item/MonsterListScreen.java b/src/main/java/com/github/tartaricacid/touhoulittlemaid/client/gui/item/MonsterListScreen.java new file mode 100644 index 000000000..0ee935b0d --- /dev/null +++ b/src/main/java/com/github/tartaricacid/touhoulittlemaid/client/gui/item/MonsterListScreen.java @@ -0,0 +1,112 @@ +package com.github.tartaricacid.touhoulittlemaid.client.gui.item; + +import com.github.tartaricacid.touhoulittlemaid.client.gui.widget.button.FlatColorButton; +import com.github.tartaricacid.touhoulittlemaid.entity.misc.DefaultMonsterType; +import com.github.tartaricacid.touhoulittlemaid.entity.misc.MonsterType; +import com.github.tartaricacid.touhoulittlemaid.network.NetworkHandler; +import com.github.tartaricacid.touhoulittlemaid.network.message.SetMonsterListMessage; +import com.google.common.collect.Maps; +import com.mojang.blaze3d.vertex.PoseStack; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.screens.Screen; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.item.ItemStack; +import net.minecraftforge.registries.ForgeRegistries; +import org.apache.commons.lang3.StringUtils; + +import java.util.List; +import java.util.Map; + +public class MonsterListScreen extends Screen { + private static final int PER_MAX_COUNT = 10; + + private final Map, MonsterType> monsterList; + private final List> monsterListIndex; + + private int page = 0; + private int posX; + private int posY; + + public MonsterListScreen(ItemStack stack) { + super(Component.literal("Monster List Screen")); + this.monsterList = DefaultMonsterType.getMonsterList(stack, Minecraft.getInstance().level); + this.monsterListIndex = this.monsterList.keySet().stream().toList(); + } + + @Override + protected void init() { + this.clearWidgets(); + + this.posX = this.width / 2; + this.posY = this.height / 2; + + int startY = posY - 16 * PER_MAX_COUNT / 2 - 8; + int size = this.monsterListIndex.size(); + for (int i = 0; i < PER_MAX_COUNT; i++) { + final int index = page * PER_MAX_COUNT + i; + if (index >= size) { + break; + } + + EntityType entityType = this.monsterListIndex.get(index); + MonsterType monsterType = this.monsterList.get(entityType); + Component text = monsterType.getComponent() + .copy() + .append(StringUtils.SPACE) + .append(entityType.getDescription()); + + FlatColorButton button = new FlatColorButton(posX - 100, startY, 200, 14, text, b -> { + MonsterType next = monsterType.getNext(); + this.monsterList.put(entityType, next); + this.init(); + }); + + this.addRenderableWidget(button); + startY += 16; + } + + startY = posY + 16 * PER_MAX_COUNT / 2 - 8; + this.addRenderableWidget(new FlatColorButton(posX - 100, startY, 28, 14, Component.literal("<"), b -> { + if (this.page > 0) { + this.page--; + this.init(); + } + })); + + this.addRenderableWidget(new FlatColorButton(posX + 100 - 28, startY, 28, 14, Component.literal(">"), b -> { + int nextStartIndex = (this.page + 1) * PER_MAX_COUNT; + if (nextStartIndex < this.monsterListIndex.size()) { + this.page++; + this.init(); + } + })); + } + + @Override + public void render(PoseStack poseStack, int mouseX, int mouseY, float partialTick) { + this.renderBackground(poseStack); + super.render(poseStack, mouseX, mouseY, partialTick); + + String pageText = String.format("%d/%d", page + 1, this.monsterListIndex.size() / PER_MAX_COUNT + 1); + int startY = posY + 16 * PER_MAX_COUNT / 2 - 5; + drawCenteredString(poseStack, font, pageText, this.posX, startY, 0xFFFFFF); + } + + @Override + public void onClose() { + Map monsterListOutput = Maps.newHashMap(); + this.monsterList.forEach((type, monsterType) -> { + ResourceLocation key = ForgeRegistries.ENTITY_TYPES.getKey(type); + monsterListOutput.put(key, monsterType); + }); + NetworkHandler.CHANNEL.sendToServer(new SetMonsterListMessage(monsterListOutput)); + super.onClose(); + } + + @Override + public boolean isPauseScreen() { + return false; + } +} diff --git a/src/main/java/com/github/tartaricacid/touhoulittlemaid/entity/misc/DefaultMonsterType.java b/src/main/java/com/github/tartaricacid/touhoulittlemaid/entity/misc/DefaultMonsterType.java new file mode 100644 index 000000000..647ab7843 --- /dev/null +++ b/src/main/java/com/github/tartaricacid/touhoulittlemaid/entity/misc/DefaultMonsterType.java @@ -0,0 +1,127 @@ +package com.github.tartaricacid.touhoulittlemaid.entity.misc; + +import com.github.tartaricacid.touhoulittlemaid.entity.item.AbstractEntityFromItem; +import com.github.tartaricacid.touhoulittlemaid.entity.passive.EntityMaid; +import com.github.tartaricacid.touhoulittlemaid.init.InitItems; +import com.github.tartaricacid.touhoulittlemaid.item.ItemMonsterList; +import com.google.common.collect.Maps; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.TamableAnimal; +import net.minecraft.world.entity.decoration.ArmorStand; +import net.minecraft.world.entity.monster.Enemy; +import net.minecraft.world.entity.npc.Npc; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; +import net.minecraftforge.registries.ForgeRegistries; + +import javax.annotation.Nullable; +import java.util.Map; + +public final class DefaultMonsterType { + private final static Map, MonsterType> DEFAULT = Maps.newHashMap(); + + public static void initDefault(Level level) { + // 只允许初始化一次 + if (!DEFAULT.isEmpty()) { + return; + } + + ForgeRegistries.ENTITY_TYPES.getValues().forEach(type -> { + Entity entity = type.create(level); + if (!(entity instanceof LivingEntity livingEntity)) { + return; + } + + // 排除一些盔甲架,还有本模组的实体,以及玩家 + if (livingEntity instanceof ArmorStand || livingEntity instanceof AbstractEntityFromItem || livingEntity instanceof Player) { + return; + } + + // 如果继承了 Enemy 接口,那就是敌对生物 + if (livingEntity instanceof Enemy) { + DEFAULT.putIfAbsent(type, MonsterType.HOSTILE); + return; + } + + // 如果是玩家、宠物、NPC、归为友好 + if (livingEntity instanceof TamableAnimal || livingEntity instanceof Npc) { + DEFAULT.putIfAbsent(type, MonsterType.FRIENDLY); + return; + } + + // 否则归为中立 + DEFAULT.putIfAbsent(type, MonsterType.NEUTRAL); + }); + } + + public static Map, MonsterType> getMonsterList(ItemStack stack, @Nullable Level level) { + Map, MonsterType> output = Maps.newHashMap(); + + if (level == null || stack.getItem() != InitItems.MONSTER_LIST.get()) { + return output; + } + + // 先从物品里读取数据 + CompoundTag monsterList = ItemMonsterList.getMonsterList(stack); + monsterList.getAllKeys().forEach(key -> readTagData(key, monsterList, output)); + + // 最后补齐默认数据 + DEFAULT.forEach(output::putIfAbsent); + + return output; + } + + public static MonsterType getMonsterType(EntityType entityType) { + return DEFAULT.getOrDefault(entityType, MonsterType.NEUTRAL); + } + + public static boolean canAttack(EntityMaid maid, LivingEntity target, MonsterType monsterType) { + // 友好生物,无论什么情况不攻击 + if (monsterType == MonsterType.FRIENDLY) { + return true; + } + + // 中立生物,只有玩家攻击的,或者攻击过玩家的才会攻击 + if (monsterType == MonsterType.NEUTRAL) { + return checkNeutral(maid, target); + } + + // 其他的,那只有敌对了,攻击 + return true; + } + + private static void readTagData(String key, CompoundTag monsterList, Map, MonsterType> output) { + int index = monsterList.getInt(key); + MonsterType monsterType = MonsterType.getTypeByIndex(index); + ResourceLocation id = new ResourceLocation(key); + EntityType entityType = ForgeRegistries.ENTITY_TYPES.getValue(id); + if (entityType != null) { + output.put(entityType, monsterType); + } + } + + private static boolean checkNeutral(EntityMaid maid, LivingEntity target) { + // 先判断主人 + if (maid.getOwner() instanceof Player player) { + // 获取攻击主人的生物 + LivingEntity lastHurtByMob = player.getLastHurtByMob(); + if (target.equals(lastHurtByMob)) { + return true; + } + // 获取主人攻击过的生物 + LivingEntity lastHurtMob = player.getLastHurtMob(); + if (target.equals(lastHurtMob)) { + return true; + } + } + + // 再判断女仆自身被攻击的 + LivingEntity maidLastHurtByMob = maid.getLastHurtByMob(); + return target.equals(maidLastHurtByMob); + } +} diff --git a/src/main/java/com/github/tartaricacid/touhoulittlemaid/entity/misc/MonsterType.java b/src/main/java/com/github/tartaricacid/touhoulittlemaid/entity/misc/MonsterType.java new file mode 100644 index 000000000..6505927b0 --- /dev/null +++ b/src/main/java/com/github/tartaricacid/touhoulittlemaid/entity/misc/MonsterType.java @@ -0,0 +1,33 @@ +package com.github.tartaricacid.touhoulittlemaid.entity.misc; + +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.MutableComponent; + +import java.util.Locale; + +public enum MonsterType { + FRIENDLY, + NEUTRAL, + HOSTILE; + + private final MutableComponent component; + + MonsterType() { + this.component = Component.translatable("gui.touhou_little_maid.monster_type." + this.name().toLowerCase(Locale.ENGLISH)); + } + + public static MonsterType getTypeByIndex(int index) { + int length = MonsterType.values().length; + return MonsterType.values()[Math.min(index, length - 1)]; + } + + public MonsterType getNext() { + int ordinal = this.ordinal(); + int length = MonsterType.values().length; + return MonsterType.values()[(ordinal + 1) % length]; + } + + public MutableComponent getComponent() { + return component; + } +} \ No newline at end of file diff --git a/src/main/java/com/github/tartaricacid/touhoulittlemaid/event/LevelLoadEvent.java b/src/main/java/com/github/tartaricacid/touhoulittlemaid/event/LevelLoadEvent.java new file mode 100644 index 000000000..4be965def --- /dev/null +++ b/src/main/java/com/github/tartaricacid/touhoulittlemaid/event/LevelLoadEvent.java @@ -0,0 +1,20 @@ +package com.github.tartaricacid.touhoulittlemaid.event; + +import com.github.tartaricacid.touhoulittlemaid.TouhouLittleMaid; +import com.github.tartaricacid.touhoulittlemaid.entity.misc.DefaultMonsterType; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.LevelAccessor; +import net.minecraftforge.event.level.LevelEvent; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.common.Mod; + +@Mod.EventBusSubscriber(modid = TouhouLittleMaid.MOD_ID) +public class LevelLoadEvent { + @SubscribeEvent + public static void onLevelLoadEvent(LevelEvent.Load event) { + LevelAccessor levelAccessor = event.getLevel(); + if (levelAccessor instanceof Level level) { + DefaultMonsterType.initDefault(level); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/github/tartaricacid/touhoulittlemaid/init/InitItems.java b/src/main/java/com/github/tartaricacid/touhoulittlemaid/init/InitItems.java index 451992e1c..0ab8fa2db 100644 --- a/src/main/java/com/github/tartaricacid/touhoulittlemaid/init/InitItems.java +++ b/src/main/java/com/github/tartaricacid/touhoulittlemaid/init/InitItems.java @@ -69,6 +69,7 @@ public final class InitItems { public static RegistryObject PICNIC_BASKET = ITEMS.register("picnic_basket", () -> new ItemPicnicBasket(InitBlocks.PICNIC_MAT.get())); public static RegistryObject SCARECROW = ITEMS.register("scarecrow", () -> new BlockItem(InitBlocks.SCARECROW.get(), new Item.Properties().tab(MAIN_TAB))); public static RegistryObject SERVANT_BELL = ITEMS.register("servant_bell", ItemServantBell::new); + public static RegistryObject MONSTER_LIST = ITEMS.register("monster_list", ItemMonsterList::new); public static RegistryObject MAID_SPAWN_EGG = ITEMS.register("maid_spawn_egg", () -> new ForgeSpawnEggItem(() -> EntityMaid.TYPE, 0x4a6195, 0xffffff, (new Item.Properties()).tab(MAIN_TAB))); public static RegistryObject FAIRY_SPAWN_EGG = ITEMS.register("fairy_spawn_egg", () -> new ForgeSpawnEggItem(() -> EntityFairy.TYPE, 0x171c20, 0xffffff, (new Item.Properties()).tab(MAIN_TAB))); diff --git a/src/main/java/com/github/tartaricacid/touhoulittlemaid/item/ItemMonsterList.java b/src/main/java/com/github/tartaricacid/touhoulittlemaid/item/ItemMonsterList.java new file mode 100644 index 000000000..d61de6dde --- /dev/null +++ b/src/main/java/com/github/tartaricacid/touhoulittlemaid/item/ItemMonsterList.java @@ -0,0 +1,69 @@ +package com.github.tartaricacid.touhoulittlemaid.item; + +import com.github.tartaricacid.touhoulittlemaid.client.gui.item.MonsterListScreen; +import com.github.tartaricacid.touhoulittlemaid.entity.misc.MonsterType; +import net.minecraft.ChatFormatting; +import net.minecraft.client.Minecraft; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.Tag; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResultHolder; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.TooltipFlag; +import net.minecraft.world.level.Level; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.fml.DistExecutor; + +import javax.annotation.Nullable; +import java.util.List; +import java.util.Map; + +import static com.github.tartaricacid.touhoulittlemaid.item.MaidGroup.MAIN_TAB; + +public class ItemMonsterList extends Item { + private static final String TAG_NAME = "MonsterList"; + + public static CompoundTag getMonsterList(ItemStack stack) { + CompoundTag tag = stack.getTag(); + if (tag != null && tag.contains(TAG_NAME, Tag.TAG_COMPOUND)) { + return tag.getCompound(TAG_NAME); + } + return new CompoundTag(); + } + + public static void addMonster(ItemStack stack, Map monsterList) { + CompoundTag tag = stack.getOrCreateTagElement(TAG_NAME); + monsterList.forEach((key, value) -> tag.putInt(key.toString(), value.ordinal())); + } + + public ItemMonsterList() { + super(new Item.Properties().tab(MAIN_TAB).stacksTo(1)); + } + + @Override + public InteractionResultHolder use(Level worldIn, Player playerIn, InteractionHand handIn) { + if (handIn == InteractionHand.MAIN_HAND) { + ItemStack stack = playerIn.getMainHandItem(); + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> openMonsterListSetScreen(stack, playerIn)); + return InteractionResultHolder.success(stack); + } + return super.use(worldIn, playerIn, handIn); + } + + @OnlyIn(Dist.CLIENT) + private void openMonsterListSetScreen(ItemStack stack, Player playerIn) { + if (playerIn.level.isClientSide) { + Minecraft.getInstance().setScreen(new MonsterListScreen(stack)); + } + } + + @Override + public void appendHoverText(ItemStack stack, @Nullable Level worldIn, List tooltip, TooltipFlag flagIn) { + tooltip.add(Component.translatable("tooltips.touhou_little_maid.monster_list.desc").withStyle(ChatFormatting.GRAY)); + } +} \ No newline at end of file diff --git a/src/main/java/com/github/tartaricacid/touhoulittlemaid/network/NetworkHandler.java b/src/main/java/com/github/tartaricacid/touhoulittlemaid/network/NetworkHandler.java index 7f7f09bc7..4cfbc7046 100644 --- a/src/main/java/com/github/tartaricacid/touhoulittlemaid/network/NetworkHandler.java +++ b/src/main/java/com/github/tartaricacid/touhoulittlemaid/network/NetworkHandler.java @@ -84,6 +84,8 @@ public static void init() { Optional.of(NetworkDirection.PLAY_TO_CLIENT)); CHANNEL.registerMessage(29, ServantBellSetMessage.class, ServantBellSetMessage::encode, ServantBellSetMessage::decode, ServantBellSetMessage::handle, Optional.of(NetworkDirection.PLAY_TO_SERVER)); + CHANNEL.registerMessage(30, SetMonsterListMessage.class, SetMonsterListMessage::encode, SetMonsterListMessage::decode, SetMonsterListMessage::handle, + Optional.of(NetworkDirection.PLAY_TO_SERVER)); } public static void sendToClientPlayer(Object message, Player player) { diff --git a/src/main/java/com/github/tartaricacid/touhoulittlemaid/network/message/SetMonsterListMessage.java b/src/main/java/com/github/tartaricacid/touhoulittlemaid/network/message/SetMonsterListMessage.java new file mode 100644 index 000000000..05f67c2df --- /dev/null +++ b/src/main/java/com/github/tartaricacid/touhoulittlemaid/network/message/SetMonsterListMessage.java @@ -0,0 +1,60 @@ +package com.github.tartaricacid.touhoulittlemaid.network.message; + +import com.github.tartaricacid.touhoulittlemaid.entity.misc.MonsterType; +import com.github.tartaricacid.touhoulittlemaid.init.InitItems; +import com.github.tartaricacid.touhoulittlemaid.item.ItemMonsterList; +import com.google.common.collect.Maps; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.item.ItemStack; +import net.minecraftforge.network.NetworkEvent; + +import java.util.Map; +import java.util.function.Supplier; + +public class SetMonsterListMessage { + private final Map monsterList; + + public SetMonsterListMessage(Map monsterList) { + this.monsterList = monsterList; + } + + public static void encode(SetMonsterListMessage message, FriendlyByteBuf buf) { + buf.writeVarInt(message.monsterList.size()); + for (ResourceLocation id : message.monsterList.keySet()) { + buf.writeResourceLocation(id); + buf.writeEnum(message.monsterList.get(id)); + } + } + + public static SetMonsterListMessage decode(FriendlyByteBuf buf) { + Map monsterListOutput = Maps.newHashMap(); + int size = buf.readVarInt(); + for (int i = 0; i < size; i++) { + ResourceLocation id = buf.readResourceLocation(); + MonsterType type = buf.readEnum(MonsterType.class); + monsterListOutput.put(id, type); + } + return new SetMonsterListMessage(monsterListOutput); + } + + public static void handle(SetMonsterListMessage message, Supplier contextSupplier) { + NetworkEvent.Context context = contextSupplier.get(); + if (context.getDirection().getReceptionSide().isServer()) { + context.enqueueWork(() -> writeList(message, context)); + } + context.setPacketHandled(true); + } + + private static void writeList(SetMonsterListMessage message, NetworkEvent.Context context) { + ServerPlayer sender = context.getSender(); + if (sender == null) { + return; + } + ItemStack item = sender.getMainHandItem(); + if (item.is(InitItems.MONSTER_LIST.get())) { + ItemMonsterList.addMonster(item, message.monsterList); + } + } +} diff --git a/src/main/resources/assets/touhou_little_maid/lang/en_us.json b/src/main/resources/assets/touhou_little_maid/lang/en_us.json index 287cdfe1a..64985ba79 100644 --- a/src/main/resources/assets/touhou_little_maid/lang/en_us.json +++ b/src/main/resources/assets/touhou_little_maid/lang/en_us.json @@ -57,6 +57,7 @@ "item.touhou_little_maid.broom": "Marisa's Broom", "item.touhou_little_maid.picnic_basket": "Picnic Basket", "item.touhou_little_maid.servant_bell": "Servant Bell", + "item.touhou_little_maid.monster_list": "Monster List", "enchantment.touhou_little_maid.impeding": "Impeding Danmaku", "enchantment.touhou_little_maid.impeding.desc": "Danmaku can inflict slowness I - IV on the enemy", "enchantment.touhou_little_maid.speedy": "Speedy Danmaku", @@ -130,6 +131,7 @@ "tooltips.touhou_little_maid.servant_bell.uuid": "UUID: %s", "tooltips.touhou_little_maid.servant_bell.desc.1": "- Right click on the maid to mark it.", "tooltips.touhou_little_maid.servant_bell.desc.2": "- After mark, you can teleport the bound maid after using it.", + "tooltips.touhou_little_maid.monster_list.desc": "Placed in the maid's offhand, she can attack based on this list", "overlay.touhou_little_maid.compass.tips": "Right click to display the maid's task area", "overlay.touhou_little_maid.golden_apple.tips": "Golden apple shift click can be fed to maid", "overlay.touhou_little_maid.potion.tips": "Potion shift click can be fed to maid", @@ -255,8 +257,11 @@ "gui.touhou_little_maid.cloth_config_warning.tips": "You'll need to install the Cloth Config API mod to use the ingame configuration feature", "gui.touhou_little_maid.cloth_config_warning.download": "Download Cloth Config API", "gui.touhou_little_maid.servant_bell.edit_box": "Please enter some tips", - "gui.touhou_little_maid.cache_screen.desc": "Caching model icon, please wait...", "gui.touhou_little_maid.cache_screen.progress": "Progress: %d/%d", + "gui.touhou_little_maid.cache_screen.desc": "Caching model icon, please wait...", + "gui.touhou_little_maid.monster_type.friendly": "§a[Friendly]", + "gui.touhou_little_maid.monster_type.neutral": "§7[Neutral]", + "gui.touhou_little_maid.monster_type.hostile": "§c[Hostile]", "chat_bubble.touhou_little_maid.inner.feed_animal.max_number": "So many animals... I don't feed them anymore!", "chat_bubble.touhou_little_maid.inner.home_meal.two_hand_is_full": "My hands were full of items... I couldn't eat!", "chat_bubble.touhou_little_maid.inner.home_meal.meal_is_empty": "Hurry up, Hurry up, I don't have anything to eat!", @@ -698,4 +703,4 @@ "patchouli.touhou_little_maid.book.entries.overview.make_custom_chatbubble_text.pages.3.text": "Special Situation:$(li)morning: Display in the morning$(li)night: Displayed in the evening$(li)rain: displayed when it rains$(li)snow: Displayed when it snows$(li)cold: Displayed when in a cold biome$(li)hot: Displayed when in a hot biome$(li)hurt: displayed when injured$(li)beg: Displayed when beg", "patchouli.touhou_little_maid.book.entries.overview.make_custom_chatbubble_text.pages.4.text": "Work Task:$(li)Will be displayed in specific working task, such as attack, farm, etc.$(br2)When you have written the text, you only need to right click on the maid to write the text.$(br)If you right click the maid with a Book and Quill (or Written Book) while holding down the Shift key, you can clear the maid's text.$(br)If you hold a blank Book and Quill and right click on a maid who already has a text, you can copy the maid's text to the book.", "patchouli.touhou_little_maid.book.entries.overview.make_custom_chatbubble_text.pages.5.text": "When the advanced tooltips function (F3+H) is turned on, you can see the task id." -} +} \ No newline at end of file diff --git a/src/main/resources/assets/touhou_little_maid/lang/zh_cn.json b/src/main/resources/assets/touhou_little_maid/lang/zh_cn.json index 53f759bd1..8b59cb16f 100644 --- a/src/main/resources/assets/touhou_little_maid/lang/zh_cn.json +++ b/src/main/resources/assets/touhou_little_maid/lang/zh_cn.json @@ -57,6 +57,7 @@ "item.touhou_little_maid.broom": "魔理沙的扫帚", "item.touhou_little_maid.picnic_basket": "野餐篮", "item.touhou_little_maid.servant_bell": "仆人铃", + "item.touhou_little_maid.monster_list": "妖怪名单", "enchantment.touhou_little_maid.impeding": "阻碍", "enchantment.touhou_little_maid.impeding.desc": "弹幕会对敌方造成缓慢 I - IV 的效果", "enchantment.touhou_little_maid.speedy": "极速", @@ -130,6 +131,7 @@ "tooltips.touhou_little_maid.servant_bell.uuid": "UUID: %s", "tooltips.touhou_little_maid.servant_bell.desc.1": "- 右击女仆进行绑定;", "tooltips.touhou_little_maid.servant_bell.desc.2": "- 绑定后,右键使用即可召回女仆。", + "tooltips.touhou_little_maid.monster_list.desc": "放置在女仆的副手,她会依据此名单来进行攻击", "overlay.touhou_little_maid.compass.tips": "右击可以显示女仆的任务区域", "overlay.touhou_little_maid.golden_apple.tips": "金苹果可以 Shfit 右击喂给女仆", "overlay.touhou_little_maid.potion.tips": "药水可以 Shift 右击喂给女仆", @@ -255,8 +257,11 @@ "gui.touhou_little_maid.cloth_config_warning.tips": "您需要安装 Cloth Config API 模组才能使用游戏内配置功能", "gui.touhou_little_maid.cloth_config_warning.download": "下载 Cloth Config API 模组", "gui.touhou_little_maid.servant_bell.edit_box": "请输入提示文本", - "gui.touhou_little_maid.cache_screen.desc": "缓存模型图标中,请等待……", "gui.touhou_little_maid.cache_screen.progress": "进度:%d/%d", + "gui.touhou_little_maid.cache_screen.desc": "缓存模型图标中,请等待……", + "gui.touhou_little_maid.monster_type.friendly": "§a[友好]", + "gui.touhou_little_maid.monster_type.neutral": "§7[中立]", + "gui.touhou_little_maid.monster_type.hostile": "§c[敌对]", "chat_bubble.touhou_little_maid.inner.feed_animal.max_number": "动物太多了……我不再喂养它们了!", "chat_bubble.touhou_little_maid.inner.home_meal.two_hand_is_full": "我的双手根本空不出来……我没法吃饭了!", "chat_bubble.touhou_little_maid.inner.home_meal.meal_is_empty": "快上菜、快上菜,我都没东西吃了!", diff --git a/src/main/resources/assets/touhou_little_maid/models/item/monster_list.json b/src/main/resources/assets/touhou_little_maid/models/item/monster_list.json new file mode 100644 index 000000000..093e2f1ca --- /dev/null +++ b/src/main/resources/assets/touhou_little_maid/models/item/monster_list.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "touhou_little_maid:item/monster_list" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/touhou_little_maid/textures/item/monster_list.png b/src/main/resources/assets/touhou_little_maid/textures/item/monster_list.png new file mode 100644 index 000000000..056bb07d3 Binary files /dev/null and b/src/main/resources/assets/touhou_little_maid/textures/item/monster_list.png differ