Commit d849d7a2 by Jonathan Thomas

Adding new mixin to dynamically affect how the canTarget method works on…

Adding new mixin to dynamically affect how the canTarget method works on LivingEntities. This prevents them from targeting any Player users if the friendship score > 0. Also changed behavior of Follow to pause when they are near the player, allowing other goals to run.
parent a1f88a25
Pipeline #11970 passed with stage
in 19 seconds
......@@ -9,6 +9,7 @@ import com.owlmaddie.json.QuestJson;
import com.owlmaddie.message.Behavior;
import com.owlmaddie.message.MessageParser;
import com.owlmaddie.message.ParsedMessage;
import com.owlmaddie.utils.LivingEntityInterface;
import com.owlmaddie.utils.ServerEntityFinder;
import net.minecraft.entity.mob.MobEntity;
import net.minecraft.item.ItemStack;
......@@ -232,8 +233,10 @@ public class ChatDataManager {
EntityBehaviorManager.removeGoal(entity, FleePlayerGoal.class);
EntityBehaviorManager.removeGoal(entity, AttackPlayerGoal.class);
EntityBehaviorManager.addGoal(entity, followGoal, GoalPriority.FOLLOW_PLAYER);
} else if (behavior.getName().equals("UNFOLLOW")) {
EntityBehaviorManager.removeGoal(entity, FollowPlayerGoal.class);
} else if (behavior.getName().equals("FLEE")) {
float fleeDistance = 400F; // 20 blocks squared
FleePlayerGoal fleeGoal = new FleePlayerGoal(player, entity, entitySpeedFast, fleeDistance);
......@@ -241,14 +244,24 @@ public class ChatDataManager {
EntityBehaviorManager.removeGoal(entity, FollowPlayerGoal.class);
EntityBehaviorManager.removeGoal(entity, AttackPlayerGoal.class);
EntityBehaviorManager.addGoal(entity, fleeGoal, GoalPriority.FLEE_PLAYER);
} else if (behavior.getName().equals("ATTACK")) {
AttackPlayerGoal attackGoal = new AttackPlayerGoal(player, entity, entitySpeedFast);
EntityBehaviorManager.removeGoal(entity, TalkPlayerGoal.class);
EntityBehaviorManager.removeGoal(entity, FollowPlayerGoal.class);
EntityBehaviorManager.removeGoal(entity, FleePlayerGoal.class);
EntityBehaviorManager.addGoal(entity, attackGoal, GoalPriority.ATTACK_PLAYER);
} else if (behavior.getName().equals("FRIENDSHIP")) {
int new_friendship = Math.max(-3, Math.min(3, behavior.getArgument()));
if (new_friendship > 0) {
// positive friendship (apply friend goal)
((LivingEntityInterface)entity).setCanTargetPlayers(false);
} else if (new_friendship < 0) {
// negative friendship (remove friend goal)
((LivingEntityInterface)entity).setCanTargetPlayers(true);
}
// Does friendship improve?
if (new_friendship > this.friendship) {
// Stop any attack/flee if friendship improves
EntityBehaviorManager.removeGoal(entity, FleePlayerGoal.class);
......
......@@ -26,34 +26,26 @@ public class FollowPlayerGoal extends Goal {
@Override
public boolean canStart() {
boolean canStart = this.targetPlayer != null;
return canStart;
// Start only if the target player is more than 8 blocks away
return this.targetPlayer != null && this.entity.squaredDistanceTo(this.targetPlayer) > 64;
}
@Override
public boolean shouldContinue() {
boolean shouldContinue = this.targetPlayer != null && this.targetPlayer.isAlive();
return shouldContinue;
// Continue unless the entity gets within 3.x blocks of the player
return this.targetPlayer != null && this.targetPlayer.isAlive() && this.entity.squaredDistanceTo(this.targetPlayer) > 12;
}
@Override
public void stop() {
// Stop the entity temporarily
this.navigation.stop();
}
@Override
public void tick() {
// Calculate the squared distance between the entity and the player
double squaredDistanceToPlayer = this.entity.squaredDistanceTo(this.targetPlayer);
// Check if the entity is further away than 4 blocks (16 when squared)
if (squaredDistanceToPlayer > 16) {
// Entity is more than 4 blocks away, look at the player and start moving towards them
// Look at the player and start moving towards them
LookControls.LookAtEntity(this.targetPlayer, this.entity);
this.navigation.startMovingTo(this.targetPlayer, this.speed);
} else if (squaredDistanceToPlayer < 9) {
// Entity is closer than 3 blocks, stop moving to maintain distance
this.navigation.stop();
}
}
}
package com.owlmaddie.mixin;
import com.owlmaddie.utils.LivingEntityInterface;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.player.PlayerEntity;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(LivingEntity.class)
public class MixinLivingEntity implements LivingEntityInterface {
private boolean canTargetPlayers = true; // Default to true to maintain original behavior
@Inject(method = "canTarget(Lnet/minecraft/entity/LivingEntity;)Z", at = @At("HEAD"), cancellable = true)
private void modifyCanTarget(LivingEntity target, CallbackInfoReturnable<Boolean> cir) {
if (!this.canTargetPlayers && target instanceof PlayerEntity) {
cir.setReturnValue(false);
}
}
@Override
public void setCanTargetPlayers(boolean canTarget) {
this.canTargetPlayers = canTarget;
}
}
package com.owlmaddie.utils;
public interface LivingEntityInterface {
void setCanTargetPlayers(boolean canTarget);
}
\ No newline at end of file
......@@ -4,7 +4,8 @@
"compatibilityLevel": "JAVA_17",
"mixins": [
"ExampleMixin",
"MixinMobEntity"
"MixinMobEntity",
"MixinLivingEntity"
],
"injectors": {
"defaultRequire": 1
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment