Skip to content

Commit

Permalink
修改部分内容
Browse files Browse the repository at this point in the history
- 修正任务按钮文本渲染与背景重复问题
- 删除指南针渲染提示
- 添加采蜜模式
- 修正日程表切换导致的女仆 AI 问题
- 攻击模式修改了识别方式(识别伤害属性而非剑)
  • Loading branch information
TartaricAcid committed Jan 7, 2024
1 parent 9fd7dad commit 54a48e4
Show file tree
Hide file tree
Showing 11 changed files with 230 additions and 62 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@ protected void renderTooltip(GuiGraphics graphics, int x, int y) {
renderTransTooltip(taskSwitch, graphics, x, y, "gui.touhou_little_maid.task.switch");
renderMaidInfo(graphics, x, y);
renderScheduleInfo(graphics, x, y);
renderTaskButtonInfo(graphics, x, y);
}

@Override
Expand Down Expand Up @@ -252,8 +253,8 @@ private List<Component> getTaskTooltips(IMaidTask maidTask) {
desc.add(Component.literal("\u0020"));
desc.add(Component.translatable("task.touhou_little_maid.desc.condition").withStyle(ChatFormatting.GOLD));
}
MutableComponent prefix = Component.literal("-\u0020");
for (Pair<String, Predicate<EntityMaid>> line : conditions) {
MutableComponent prefix = Component.literal("-\u0020");
String key = String.format("task.%s.%s.condition.%s", maidTask.getUid().getNamespace(), maidTask.getUid().getPath(), line.getFirst());
MutableComponent condition = Component.translatable(key);
if (line.getSecond().test(maid)) {
Expand Down Expand Up @@ -396,6 +397,14 @@ private void renderScheduleInfo(GuiGraphics graphics, int mouseX, int mouseY) {
}
}

private void renderTaskButtonInfo(GuiGraphics graphics, int x, int y) {
this.renderables.stream().filter(b -> b instanceof TaskButton).forEach(b -> {
if (((TaskButton) b).isHovered()) {
((TaskButton) b).renderToolTip(graphics, getMinecraft(), x, y);
}
});
}

private void drawMaidCharacter(GuiGraphics graphics, int x, int y) {
double scale = getMinecraft().getWindow().getGuiScale();
RenderSystem.enableScissor((int) ((leftPos + 6) * scale), (int) ((topPos + 107 + 42) * scale),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,12 +65,9 @@ public void renderWidget(GuiGraphics graphics, int mouseX, int mouseY, float par
graphics.blit(this.resourceLocation, this.getX(), this.getY(), (float) this.xTexStart, (float) i, this.width, this.height, this.textureWidth, this.textureHeight);
graphics.renderItem(task.getIcon(), this.getX() + 2, this.getY() + 2);
graphics.drawString(minecraft.font, task.getName(), this.getX() + 23, this.getY() + 6, 0x333333, false);
if (this.isHovered()) {
this.renderToolTip(graphics, minecraft, mouseX, mouseY);
}
}

private void renderToolTip(GuiGraphics graphics, Minecraft mc, int mouseX, int mouseY) {
public void renderToolTip(GuiGraphics graphics, Minecraft mc, int mouseX, int mouseY) {
if (!this.tooltips.isEmpty()) {
graphics.renderComponentTooltip(mc.font, this.tooltips, mouseX, mouseY);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,33 +12,24 @@
import com.github.tartaricacid.touhoulittlemaid.entity.passive.EntityMaid;
import com.google.common.collect.Lists;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.blaze3d.vertex.VertexConsumer;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.Font;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.entity.EntityRenderDispatcher;
import net.minecraft.client.renderer.entity.EntityRendererProvider;
import net.minecraft.client.renderer.entity.MobRenderer;
import net.minecraft.core.BlockPos;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.Items;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.common.MinecraftForge;
import org.joml.Matrix4f;
import org.joml.Vector3f;

import java.util.List;

@OnlyIn(Dist.CLIENT)
public class EntityMaidRenderer extends MobRenderer<EntityMaid, BedrockModel<EntityMaid>> {
private static final ResourceLocation DEFAULT_TEXTURE = new ResourceLocation(TouhouLittleMaid.MOD_ID, "textures/entity/empty.png");
private static final String DEFAULT_MODEL_ID = "touhou_little_maid:hakurei_reimu";
private final GeckoEntityMaidRenderer geckoEntityMaidRenderer;
private MaidModelInfo mainInfo;
private List<Object> mainAnimations = Lists.newArrayList();
private GeckoEntityMaidRenderer geckoEntityMaidRenderer;

public EntityMaidRenderer(EntityRendererProvider.Context manager) {
super(manager, new BedrockModel<>(), 0.5f);
Expand All @@ -52,8 +43,6 @@ public EntityMaidRenderer(EntityRendererProvider.Context manager) {

@Override
public void render(EntityMaid entity, float entityYaw, float partialTicks, PoseStack poseStack, MultiBufferSource bufferIn, int packedLightIn) {
renderHomeTips(entity, poseStack, bufferIn, packedLightIn);

// 读取默认模型,用于清除不存在模型的缓存残留
CustomPackLoader.MAID_MODELS.getModel(DEFAULT_MODEL_ID).ifPresent(model -> this.model = model);
CustomPackLoader.MAID_MODELS.getInfo(DEFAULT_MODEL_ID).ifPresent(info -> this.mainInfo = info);
Expand Down Expand Up @@ -93,40 +82,6 @@ public void render(EntityMaid entity, float entityYaw, float partialTicks, PoseS
GlWrapper.clearPoseStack();
}

private void renderHomeTips(EntityMaid entity, PoseStack poseStack, MultiBufferSource bufferIn, int packedLightIn) {
Minecraft mc = Minecraft.getInstance();
Player player = mc.player;
if (entity.hasRestriction() && player != null && extraCondition(entity, mc, player)) {
BlockPos restrictCenter = entity.getRestrictCenter();
Vector3f home = new Vector3f(restrictCenter.getX(), restrictCenter.getY(), restrictCenter.getZ());
home.add(0.5f, 0.25f, 0.5f);
home.add((float) -entity.getX(), (float) -entity.getY(), (float) -entity.getZ());

poseStack.pushPose();
poseStack.translate(home.x(), home.y() + 0.25, home.z());
poseStack.mulPose(this.entityRenderDispatcher.cameraOrientation());
poseStack.scale(-0.025F, -0.025F, 0.025F);
Matrix4f pose = poseStack.last().pose();
Font fontrenderer = this.getFont();
String text = String.format("[%d, %d, %d]", restrictCenter.getX(), restrictCenter.getY(), restrictCenter.getZ());
float x = (float) (-fontrenderer.width(text) / 2);
fontrenderer.drawInBatch(text, x, 0, -1, false, pose, bufferIn, Font.DisplayMode.NORMAL, 0, packedLightIn);
poseStack.popPose();

VertexConsumer buffer = bufferIn.getBuffer(RenderType.lines());
Matrix4f matrix4f = poseStack.last().pose();
buffer.vertex(matrix4f, 0, 0.5f, 0).color(0xff, 0x00, 0x00, 0xff).normal(1, 0, 0).endVertex();
buffer.vertex(matrix4f, home.x(), home.y(), home.z()).color(0xff, 0x00, 0x00, 0xff).normal(0, 0, 1).endVertex();
}
}

private boolean extraCondition(EntityMaid entity, Minecraft mc, Player player) {
if (player.getMainHandItem().getItem() == Items.COMPASS) {
return entity.equals(mc.crosshairPickEntity) || player.isShiftKeyDown();
}
return false;
}

@Override
protected void scale(EntityMaid maid, PoseStack poseStack, float partialTickTime) {
float scale = mainInfo.getRenderEntityScale();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
package com.github.tartaricacid.touhoulittlemaid.entity.ai.brain.task;

import com.github.tartaricacid.touhoulittlemaid.entity.passive.EntityMaid;
import com.github.tartaricacid.touhoulittlemaid.init.InitEntities;
import com.github.tartaricacid.touhoulittlemaid.util.ItemsUtil;
import com.google.common.collect.ImmutableMap;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.sounds.SoundSource;
import net.minecraft.tags.PoiTypeTags;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.entity.EquipmentSlot;
import net.minecraft.world.entity.ai.behavior.BehaviorUtils;
import net.minecraft.world.entity.ai.behavior.BlockPosTracker;
import net.minecraft.world.entity.ai.memory.MemoryModuleType;
import net.minecraft.world.entity.ai.memory.MemoryStatus;
import net.minecraft.world.entity.ai.village.poi.PoiManager;
import net.minecraft.world.entity.ai.village.poi.PoiRecord;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.BeehiveBlock;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraftforge.common.ToolActions;
import net.minecraftforge.items.ItemHandlerHelper;
import net.minecraftforge.items.wrapper.CombinedInvWrapper;

import javax.annotation.Nullable;
import java.util.Comparator;

public class MaidCollectHoneyTask extends MaidCheckRateTask {
private static final int MAX_DELAY_TIME = 100;
private final float speed;
private final int closeEnoughDist;

public MaidCollectHoneyTask(float speed, int closeEnoughDist) {
super(ImmutableMap.of(MemoryModuleType.WALK_TARGET, MemoryStatus.VALUE_ABSENT,
InitEntities.TARGET_POS.get(), MemoryStatus.VALUE_ABSENT));
this.speed = speed;
this.closeEnoughDist = closeEnoughDist;
this.setMaxCheckRate(MAX_DELAY_TIME);
}

@Override
protected boolean checkExtraStartConditions(ServerLevel worldIn, EntityMaid maid) {
if (super.checkExtraStartConditions(worldIn, maid)) {
BlockPos beehivePos = findBeehive(worldIn, maid);
if (beehivePos != null && maid.isWithinRestriction(beehivePos)) {
if (beehivePos.distToCenterSqr(maid.position()) < this.closeEnoughDist) {
maid.getBrain().setMemory(InitEntities.TARGET_POS.get(), new BlockPosTracker(beehivePos));
return true;
}
BehaviorUtils.setWalkAndLookTargetMemories(maid, beehivePos, speed, 1);
this.setNextCheckTickCount(5);
} else {
maid.getBrain().eraseMemory(InitEntities.TARGET_POS.get());
}
}
return false;
}

@Override
protected void start(ServerLevel level, EntityMaid maid, long gameTime) {
maid.getBrain().getMemory(InitEntities.TARGET_POS.get()).ifPresent(target -> {
BlockPos hivePos = target.currentBlockPosition();
BlockState hiveBlockState = level.getBlockState(hivePos);
if (hiveBlockState.getValue(BeehiveBlock.HONEY_LEVEL) < 5) {
return;
}
CombinedInvWrapper maidAvailableInv = maid.getAvailableInv(true);
if (!this.collectHoneyComb(level, maid, maidAvailableInv, hiveBlockState, hivePos)) {
this.collectHoneyBottle(level, maid, maidAvailableInv, hiveBlockState, hivePos);
}
});
}

private void collectHoneyBottle(ServerLevel level, EntityMaid maid, CombinedInvWrapper maidAvailableInv, BlockState hiveBlockState, BlockPos hivePos) {
ItemStack bottle = ItemsUtil.getStack(maidAvailableInv, stack -> stack.is(Items.GLASS_BOTTLE));
if (!bottle.isEmpty()) {
ItemStack honeyBottle = new ItemStack(Items.HONEY_BOTTLE);
ItemStack result = ItemHandlerHelper.insertItemStacked(maidAvailableInv, honeyBottle, true);
// 背包满了就不收集了
if (!result.isEmpty()) {
return;
}
bottle.shrink(1);
level.playSound(null, maid.getX(), maid.getY(), maid.getZ(), SoundEvents.BOTTLE_FILL, SoundSource.BLOCKS, 1.0F, 1.0F);
ItemHandlerHelper.insertItemStacked(maidAvailableInv, honeyBottle, false);
resetHoneyLevel(level, hiveBlockState, hivePos);
maid.swing(InteractionHand.MAIN_HAND);
maid.getBrain().eraseMemory(InitEntities.TARGET_POS.get());
maid.getBrain().eraseMemory(MemoryModuleType.LOOK_TARGET);
maid.getBrain().eraseMemory(MemoryModuleType.WALK_TARGET);
}
}

private boolean collectHoneyComb(ServerLevel level, EntityMaid maid, CombinedInvWrapper maidAvailableInv, BlockState hiveBlockState, BlockPos hivePos) {
boolean hasShears = maid.getMainHandItem().canPerformAction(ToolActions.SHEARS_HARVEST);
if (hasShears) {
ItemStack honeyComb = new ItemStack(Items.HONEYCOMB, 3);
ItemStack result = ItemHandlerHelper.insertItemStacked(maidAvailableInv, honeyComb, true);
// 背包满了就不收集了
if (!result.isEmpty()) {
return false;
}
level.playSound(null, maid.getX(), maid.getY(), maid.getZ(), SoundEvents.BEEHIVE_SHEAR, SoundSource.BLOCKS, 1.0F, 1.0F);
ItemHandlerHelper.insertItemStacked(maidAvailableInv, honeyComb, false);
resetHoneyLevel(level, hiveBlockState, hivePos);
maid.swing(InteractionHand.MAIN_HAND);
maid.getMainHandItem().hurtAndBreak(1, maid, e -> e.broadcastBreakEvent(EquipmentSlot.MAINHAND));
maid.getBrain().eraseMemory(InitEntities.TARGET_POS.get());
maid.getBrain().eraseMemory(MemoryModuleType.LOOK_TARGET);
maid.getBrain().eraseMemory(MemoryModuleType.WALK_TARGET);
return true;
}
return false;
}

@Nullable
private BlockPos findBeehive(ServerLevel world, EntityMaid maid) {
BlockPos blockPos = maid.blockPosition();
PoiManager poiManager = world.getPoiManager();
int range = (int) maid.getRestrictRadius();
return poiManager.getInRange((type) -> type.is(PoiTypeTags.BEE_HOME), blockPos, range, PoiManager.Occupancy.ANY)
.map(PoiRecord::getPos).filter(pos -> canCollectHoney(world, pos))
.min(Comparator.comparingDouble((pos) -> pos.distSqr(blockPos))).orElse(null);
}

private boolean canCollectHoney(ServerLevel world, BlockPos hivePos) {
return world.getBlockState(hivePos).getValue(BeehiveBlock.HONEY_LEVEL) >= 5;
}

public void resetHoneyLevel(Level level, BlockState state, BlockPos pos) {
level.setBlock(pos, state.setValue(BeehiveBlock.HONEY_LEVEL, 0), Block.UPDATE_ALL);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public class MaidShearTask extends MaidCheckRateTask {
private final float speedModifier;
private LivingEntity shearableEntity = null;

public MaidShearTask(int maxDistToWalk, float speedModifier) {
public MaidShearTask(float speedModifier) {
super(ImmutableMap.of(MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES, MemoryStatus.VALUE_PRESENT,
MemoryModuleType.WALK_TARGET, MemoryStatus.VALUE_ABSENT));
this.speedModifier = speedModifier;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.github.tartaricacid.touhoulittlemaid.entity.ai.brain.task;

import com.github.tartaricacid.touhoulittlemaid.entity.item.EntitySit;
import com.github.tartaricacid.touhoulittlemaid.entity.passive.EntityMaid;
import com.google.common.collect.ImmutableMap;
import net.minecraft.server.level.ServerLevel;
Expand All @@ -24,12 +23,16 @@ protected void start(ServerLevel level, EntityMaid maid, long gameTime) {
if (this.cacheActivity == null) {
this.cacheActivity = activity;
}
if (!this.cacheActivity.equals(activity) && !maid.isSleeping() && !(maid.getVehicle() instanceof EntitySit)) {
if (!this.cacheActivity.equals(activity) && this.maidStateConditions(maid)) {
this.cacheActivity = activity;
maid.getSchedulePos().restrictTo(maid);
BehaviorUtils.setWalkAndLookTargetMemories(maid, maid.getRestrictCenter(), 0.7f, 3);
}
}
brain.updateActivityFromSchedule(dayTime, level.getGameTime());
}

private boolean maidStateConditions(EntityMaid maid) {
return maid.isHomeModeEnable() && !maid.isInSittingPose() && !maid.isSleeping() && !maid.isLeashed() && !maid.isPassenger();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,13 @@
import com.mojang.datafixers.util.Pair;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.sounds.SoundEvent;
import net.minecraft.world.entity.EquipmentSlot;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.Mob;
import net.minecraft.world.entity.ai.attributes.Attributes;
import net.minecraft.world.entity.ai.behavior.*;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.item.SwordItem;

import java.util.Collections;
import java.util.List;
Expand All @@ -41,9 +42,9 @@ public SoundEvent getAmbientSound(EntityMaid maid) {

@Override
public List<Pair<Integer, BehaviorControl<? super EntityMaid>>> createBrainTasks(EntityMaid maid) {
BehaviorControl<EntityMaid> supplementedTask = StartAttacking.create(this::hasSword, IAttackTask::findFirstValidAttackTarget);
BehaviorControl<EntityMaid> supplementedTask = StartAttacking.create(this::hasAssaultWeapon, IAttackTask::findFirstValidAttackTarget);
BehaviorControl<EntityMaid> findTargetTask = StopAttackingIfTargetInvalid.create(
(target) -> !hasSword(maid) || farAway(target, maid));
(target) -> !hasAssaultWeapon(maid) || farAway(target, maid));
BehaviorControl<Mob> moveToTargetTask = SetWalkTargetFromAttackTargetIfTargetOutOfReach.create(0.6f);
BehaviorControl<Mob> attackTargetTask = MeleeAttack.create(20);

Expand All @@ -57,11 +58,11 @@ public List<Pair<Integer, BehaviorControl<? super EntityMaid>>> createBrainTasks

@Override
public List<Pair<String, Predicate<EntityMaid>>> getConditionDescription(EntityMaid maid) {
return Collections.singletonList(Pair.of("has_sword", this::hasSword));
return Collections.singletonList(Pair.of("assault_weapon", this::hasAssaultWeapon));
}

private boolean hasSword(EntityMaid maid) {
return maid.getMainHandItem().getItem() instanceof SwordItem;
private boolean hasAssaultWeapon(EntityMaid maid) {
return maid.getMainHandItem().getAttributeModifiers(EquipmentSlot.MAINHAND).containsKey(Attributes.ATTACK_DAMAGE);
}

private boolean farAway(LivingEntity target, EntityMaid maid) {
Expand Down
Loading

0 comments on commit 54a48e4

Please sign in to comment.