-
Notifications
You must be signed in to change notification settings - Fork 69
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
be5b244
commit 951a2f7
Showing
15 changed files
with
483 additions
and
30 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
111 changes: 111 additions & 0 deletions
111
...main/java/com/github/tartaricacid/touhoulittlemaid/client/gui/item/MonsterListScreen.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
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.message.SetMonsterListMessage; | ||
import com.google.common.collect.Maps; | ||
import net.minecraft.client.Minecraft; | ||
import net.minecraft.client.gui.GuiGraphics; | ||
import net.minecraft.client.gui.screens.Screen; | ||
import net.minecraft.core.registries.BuiltInRegistries; | ||
import net.minecraft.network.chat.CommonComponents; | ||
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.neoforged.neoforge.network.PacketDistributor; | ||
|
||
import java.util.List; | ||
import java.util.Map; | ||
|
||
public class MonsterListScreen extends Screen { | ||
private static final int PER_MAX_COUNT = 10; | ||
|
||
private final Map<EntityType<?>, MonsterType> monsterList; | ||
private final List<EntityType<?>> 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(CommonComponents.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(GuiGraphics graphics, int mouseX, int mouseY, float partialTick) { | ||
super.render(graphics, 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; | ||
graphics.drawCenteredString(font, pageText, this.posX, startY, 0xFFFFFF); | ||
} | ||
|
||
@Override | ||
public void onClose() { | ||
Map<ResourceLocation, MonsterType> monsterListOutput = Maps.newHashMap(); | ||
this.monsterList.forEach((type, monsterType) -> { | ||
ResourceLocation key = BuiltInRegistries.ENTITY_TYPE.getKey(type); | ||
monsterListOutput.put(key, monsterType); | ||
}); | ||
PacketDistributor.sendToServer(new SetMonsterListMessage(monsterListOutput)); | ||
super.onClose(); | ||
} | ||
|
||
@Override | ||
public boolean isPauseScreen() { | ||
return false; | ||
} | ||
} |
119 changes: 119 additions & 0 deletions
119
src/main/java/com/github/tartaricacid/touhoulittlemaid/entity/misc/DefaultMonsterType.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
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.core.registries.BuiltInRegistries; | ||
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 javax.annotation.Nullable; | ||
import java.util.Map; | ||
|
||
public final class DefaultMonsterType { | ||
private final static Map<EntityType<?>, MonsterType> DEFAULT = Maps.newHashMap(); | ||
|
||
public static void initDefault(Level level) { | ||
// 只允许初始化一次 | ||
if (!DEFAULT.isEmpty()) { | ||
return; | ||
} | ||
|
||
BuiltInRegistries.ENTITY_TYPE.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<EntityType<?>, MonsterType> getMonsterList(ItemStack stack, @Nullable Level level) { | ||
Map<EntityType<?>, MonsterType> output = Maps.newHashMap(); | ||
|
||
if (level == null || stack.getItem() != InitItems.MONSTER_LIST.get()) { | ||
return output; | ||
} | ||
|
||
// 先从物品里读取数据 | ||
Map<ResourceLocation, MonsterType> monsterList = ItemMonsterList.getMonsterList(stack); | ||
monsterList.forEach((key, monsterType) -> { | ||
EntityType<?> entityType = BuiltInRegistries.ENTITY_TYPE.get(key); | ||
output.put(entityType, monsterType); | ||
}); | ||
|
||
// 最后补齐默认数据 | ||
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 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); | ||
} | ||
} |
48 changes: 48 additions & 0 deletions
48
src/main/java/com/github/tartaricacid/touhoulittlemaid/entity/misc/MonsterType.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
package com.github.tartaricacid.touhoulittlemaid.entity.misc; | ||
|
||
import com.mojang.serialization.Codec; | ||
import io.netty.buffer.ByteBuf; | ||
import net.minecraft.network.chat.Component; | ||
import net.minecraft.network.chat.MutableComponent; | ||
import net.minecraft.network.codec.StreamCodec; | ||
import net.minecraft.util.StringRepresentable; | ||
|
||
import java.util.Locale; | ||
|
||
public enum MonsterType implements StringRepresentable { | ||
FRIENDLY, | ||
NEUTRAL, | ||
HOSTILE; | ||
|
||
public static final Codec<MonsterType> CODEC = StringRepresentable.fromEnum(MonsterType::values); | ||
public static final StreamCodec<ByteBuf, MonsterType> STREAM_CODEC = StreamCodec.of( | ||
(byteBuf, type) -> byteBuf.writeInt(type.ordinal()), | ||
byteBuf -> getTypeByIndex(byteBuf.readInt()) | ||
); | ||
|
||
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; | ||
} | ||
|
||
@Override | ||
public String getSerializedName() { | ||
return this.name().toLowerCase(Locale.ENGLISH); | ||
} | ||
} |
20 changes: 20 additions & 0 deletions
20
src/main/java/com/github/tartaricacid/touhoulittlemaid/event/LevelLoadEvent.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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.neoforged.bus.api.SubscribeEvent; | ||
import net.neoforged.fml.common.EventBusSubscriber; | ||
import net.neoforged.neoforge.event.level.LevelEvent; | ||
|
||
@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); | ||
} | ||
} | ||
} |
Oops, something went wrong.