Use remapped Mojang jars for 1.17

This will make it easier to develop for 1.17, and future versions if I choose to continue using Mojang remappings. I also fixed some logic errors in all version implementations.
This commit is contained in:
SeanOMik 2021-06-24 15:44:44 -04:00
parent 201b2641e7
commit f5903a16be
No known key found for this signature in database
GPG Key ID: CA09E5BE1F32728A
17 changed files with 688 additions and 648 deletions

View File

@ -276,11 +276,20 @@ public class EntityTamableFox extends EntityFox {
return flag;
} else if (entityhuman.isSneaking()) { // Swap/Put/Take item from fox.
// Ignore buckets since they can be easily duplicated.
if (itemstack.getItem() == Items.BUCKET || itemstack.getItem() == Items.LAVA_BUCKET || itemstack.getItem() == Items.WATER_BUCKET) return true;
if (itemstack.getItem() instanceof ItemBucket) {
return false;
}
// If the fox has something in its mouth and the player has something in its hand, empty it.
if (!this.getEquipment(EnumItemSlot.MAINHAND).isEmpty()) {
getBukkitEntity().getWorld().dropItem(getBukkitEntity().getLocation(), CraftItemStack.asBukkitCopy(this.getEquipment(EnumItemSlot.MAINHAND)));
this.setSlot(EnumItemSlot.MAINHAND, new ItemStack(Items.AIR));
} // Check if the player's hand is empty and if it is, make the fox sleep.
// The reason its here is to make sure that we don't take the item
// from its mouth and make it sleep in a single click.
else if (entityhuman.getEquipment(EnumItemSlot.MAINHAND).isEmpty()) {
this.goalSit.setSitting(false);
this.setSleeping(!this.isSleeping());
}
// Run this task async to make sure to not slow the server down.

View File

@ -276,11 +276,20 @@ public class EntityTamableFox extends EntityFox {
return flag;
} else if (entityhuman.isSneaking()) { // Swap/Put/Take item from fox.
// Ignore buckets since they can be easily duplicated.
if (itemstack.getItem() == Items.BUCKET || itemstack.getItem() == Items.LAVA_BUCKET || itemstack.getItem() == Items.WATER_BUCKET) return true;
if (itemstack.getItem() instanceof ItemBucket) {
return false;
}
// If the fox has something in its mouth and the player has something in its hand, empty it.
if (!this.getEquipment(EnumItemSlot.MAINHAND).isEmpty()) {
getBukkitEntity().getWorld().dropItem(getBukkitEntity().getLocation(), CraftItemStack.asBukkitCopy(this.getEquipment(EnumItemSlot.MAINHAND)));
this.setSlot(EnumItemSlot.MAINHAND, new ItemStack(Items.AIR));
} // Check if the player's hand is empty and if it is, make the fox sleep.
// The reason its here is to make sure that we don't take the item
// from its mouth and make it sleep in a single click.
else if (entityhuman.getEquipment(EnumItemSlot.MAINHAND).isEmpty()) {
this.goalSit.setSitting(false);
this.setSleeping(!this.isSleeping());
}
// Run this task async to make sure to not slow the server down.

View File

@ -276,13 +276,20 @@ public class EntityTamableFox extends EntityFox {
return flag;
} else if (entityhuman.isSneaking()) { // Swap/Put/Take item from fox.
// Ignore buckets since they can be easily duplicated.
if (itemstack.getItem() == Items.BUCKET || itemstack.getItem() == Items.LAVA_BUCKET || itemstack.getItem() == Items.WATER_BUCKET) {
if (itemstack.getItem() instanceof ItemBucket) {
return EnumInteractionResult.PASS;
}
// If the fox has something in its mouth and the player has something in its hand, empty it.
if (!this.getEquipment(EnumItemSlot.MAINHAND).isEmpty()) {
getBukkitEntity().getWorld().dropItem(getBukkitEntity().getLocation(), CraftItemStack.asBukkitCopy(this.getEquipment(EnumItemSlot.MAINHAND)));
this.setSlot(EnumItemSlot.MAINHAND, new ItemStack(Items.AIR));
} // Check if the player's hand is empty and if it is, make the fox sleep.
// The reason its here is to make sure that we don't take the item
// from its mouth and make it sleep in a single click.
else if (entityhuman.getEquipment(EnumItemSlot.MAINHAND).isEmpty()) {
this.goalSit.setSitting(false);
this.setSleeping(!this.isSleeping());
}
// Run this task async to make sure to not slow the server down.

View File

@ -273,13 +273,20 @@ public class EntityTamableFox extends EntityFox {
return flag;
} else if (entityhuman.isSneaking()) { // Swap/Put/Take item from fox.
// Ignore buckets since they can be easily duplicated.
if (itemstack.getItem() == Items.BUCKET || itemstack.getItem() == Items.LAVA_BUCKET || itemstack.getItem() == Items.WATER_BUCKET) {
if (itemstack.getItem() instanceof ItemBucket) {
return EnumInteractionResult.PASS;
}
// If the fox has something in its mouth and the player has something in its hand, empty it.
if (!this.getEquipment(EnumItemSlot.MAINHAND).isEmpty()) {
getBukkitEntity().getWorld().dropItem(getBukkitEntity().getLocation(), CraftItemStack.asBukkitCopy(this.getEquipment(EnumItemSlot.MAINHAND)));
this.setSlot(EnumItemSlot.MAINHAND, new ItemStack(Items.AIR));
} // Check if the player's hand is empty and if it is, make the fox sleep.
// The reason its here is to make sure that we don't take the item
// from its mouth and make it sleep in a single click.
else if (entityhuman.getEquipment(EnumItemSlot.MAINHAND).isEmpty()) {
this.goalSit.setSitting(false);
this.setSleeping(!this.isSleeping());
}
// Run this task async to make sure to not slow the server down.
@ -297,11 +304,6 @@ public class EntityTamableFox extends EntityFox {
this.setSlot(EnumItemSlot.MAINHAND, c);
}
// If the player doesn't have anything in their hand, make the fox sleep or wakeup.
else {
this.goalSit.setSitting(false);
this.setSleeping(!this.isSleeping());
}
}, (long) 0.1);
return EnumInteractionResult.SUCCESS;

View File

@ -261,7 +261,7 @@ public class EntityTamableFox extends EntityFox {
return EnumInteractionResult.CONSUME;
}
if (isOwnedBy(entityhuman)) {
if (isOwnedBy(entityhuman) && enumhand == EnumHand.MAIN_HAND) {
// This super method checks if the fox can breed or not.
EnumInteractionResult flag = super.b(entityhuman, enumhand);
@ -271,16 +271,22 @@ public class EntityTamableFox extends EntityFox {
this.setSleeping(false);
this.goalSit.setSitting(!this.isSitting());
return flag;
} else if (entityhuman.isSneaking() && enumhand == EnumHand.MAIN_HAND) { // Swap/Put/Take item from fox.
} else if (entityhuman.isSneaking()) { // Swap/Put/Take item from fox.
// Ignore buckets since they can be easily duplicated.
if (itemstack.getItem() == Items.BUCKET || itemstack.getItem() == Items.LAVA_BUCKET || itemstack.getItem() == Items.WATER_BUCKET) {
if (itemstack.getItem() instanceof ItemBucket) {
return EnumInteractionResult.PASS;
}
// Check if the player has something in their main hand.
// If the fox has something in its mouth and the player has something in its hand, empty it.
if (!this.getEquipment(EnumItemSlot.MAINHAND).isEmpty()) {
getBukkitEntity().getWorld().dropItem(getBukkitEntity().getLocation(), CraftItemStack.asBukkitCopy(this.getEquipment(EnumItemSlot.MAINHAND)));
this.setSlot(EnumItemSlot.MAINHAND, new ItemStack(Items.AIR));
this.setSlot(EnumItemSlot.MAINHAND, new ItemStack(Items.AIR), false);
} // Check if the player's hand is empty and if it is, make the fox sleep.
// The reason its here is to make sure that we don't take the item
// from its mouth and make it sleep in a single click.
else if (entityhuman.getEquipment(EnumItemSlot.MAINHAND).isEmpty()) {
this.goalSit.setSitting(false);
this.setSleeping(!this.isSleeping());
}
// Run this task async to make sure to not slow the server down.
@ -298,11 +304,6 @@ public class EntityTamableFox extends EntityFox {
this.setSlot(EnumItemSlot.MAINHAND, c);
}
// If the player doesn't have anything in their hand, make the fox sleep or wakeup.
else {
this.goalSit.setSitting(false);
this.setSleeping(!this.isSleeping());
}
}, (long) 0.1);
return EnumInteractionResult.SUCCESS;

View File

@ -10,6 +10,44 @@
<version>2.0.0-SNAPSHOT</version>
</parent>
<build>
<plugins>
<plugin>
<groupId>net.md-5</groupId>
<artifactId>specialsource-maven-plugin</artifactId>
<version>1.2.2</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>remap</goal>
</goals>
<id>remap-obf</id>
<configuration>
<srgIn>org.spigotmc:minecraft-server:1.17-R0.1-SNAPSHOT:txt:maps-mojang</srgIn>
<reverse>true</reverse>
<remappedDependencies>org.spigotmc:spigot:1.17-R0.1-SNAPSHOT:jar:remapped-mojang</remappedDependencies>
<remappedArtifactAttached>true</remappedArtifactAttached>
<remappedClassifierName>remapped-obf</remappedClassifierName>
</configuration>
</execution>
<execution>
<phase>package</phase>
<goals>
<goal>remap</goal>
</goals>
<id>remap-spigot</id>
<configuration>
<inputFile>${project.build.directory}/${project.artifactId}-${project.version}-remapped-obf.jar</inputFile>
<srgIn>org.spigotmc:minecraft-server:1.17-R0.1-SNAPSHOT:csrg:maps-spigot</srgIn>
<remappedDependencies>org.spigotmc:spigot:1.17-R0.1-SNAPSHOT:jar:remapped-obf</remappedDependencies>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<artifactId>tamablefoxes_v1_17_R1</artifactId>
<repositories>
@ -34,6 +72,7 @@
<groupId>org.spigotmc</groupId>
<artifactId>spigot</artifactId>
<version>1.17-R0.1-SNAPSHOT</version>
<classifier>remapped-mojang</classifier>
<scope>provided</scope>
</dependency>
<dependency>

View File

@ -1,37 +1,28 @@
package net.seanomik.tamablefoxes.versions.version_1_17_R1;
import net.minecraft.advancements.CriterionTriggers;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.network.syncher.DataWatcher;
import net.minecraft.network.syncher.DataWatcherObject;
import net.minecraft.network.syncher.DataWatcherRegistry;
import net.minecraft.server.level.EntityPlayer;
import net.minecraft.server.level.WorldServer;
import net.minecraft.world.EnumHand;
import net.minecraft.world.EnumInteractionResult;
import net.minecraft.advancements.CriteriaTriggers;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.syncher.*;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.damagesource.DamageSource;
import net.minecraft.world.entity.*;
import net.minecraft.world.entity.ai.attributes.GenericAttributes;
import net.minecraft.world.entity.ai.attributes.Attributes;
import net.minecraft.world.entity.ai.goal.*;
import net.minecraft.world.entity.ai.goal.target.PathfinderGoalNearestAttackableTarget;
import net.minecraft.world.entity.ai.goal.target.NearestAttackableTargetGoal;
import net.minecraft.world.entity.animal.*;
import net.minecraft.world.entity.animal.horse.EntityHorseAbstract;
import net.minecraft.world.entity.monster.EntityCreeper;
import net.minecraft.world.entity.monster.EntityGhast;
import net.minecraft.world.entity.player.EntityHuman;
import net.minecraft.world.entity.player.PlayerAbilities;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemMonsterEgg;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.entity.animal.horse.AbstractHorse;
import net.minecraft.world.entity.monster.Creeper;
import net.minecraft.world.entity.monster.Ghast;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.*;
import net.minecraft.world.level.GameRules;
import net.minecraft.world.level.World;
import net.minecraft.world.scores.ScoreboardTeamBase;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityTypes;
import net.minecraft.world.entity.IEntitySelector;
import net.minecraft.world.entity.ai.goal.PathfinderGoal;
import net.minecraft.world.entity.animal.EntityFox;
import net.minecraft.world.entity.animal.Fox;
import net.minecraft.world.level.Level;
import net.minecraft.world.scores.Team;
import net.seanomik.tamablefoxes.util.Utils;
import net.seanomik.tamablefoxes.util.io.Config;
import net.seanomik.tamablefoxes.util.io.LanguageConfig;
@ -41,245 +32,228 @@ import net.wesjd.anvilgui.AnvilGUI;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.GameMode;
import org.bukkit.Server;
import org.bukkit.craftbukkit.libs.jline.internal.Nullable;
import org.bukkit.craftbukkit.v1_17_R1.CraftServer;
import org.bukkit.craftbukkit.v1_17_R1.entity.CraftHumanEntity;
import org.bukkit.craftbukkit.v1_17_R1.entity.CraftPlayer;
import org.bukkit.craftbukkit.v1_17_R1.event.CraftEventFactory;
import org.bukkit.craftbukkit.v1_17_R1.inventory.CraftItemStack;
import org.bukkit.entity.Player;
import org.bukkit.event.entity.EntityRegainHealthEvent;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;
import java.util.function.Predicate;
public class EntityTamableFox extends EntityFox {
public class EntityTamableFox extends Fox {
protected static final DataWatcherObject<Byte> tamed;
protected static final DataWatcherObject<Optional<UUID>> ownerUUID;
protected static final EntityDataAccessor<Byte> tamed;
protected static final EntityDataAccessor<Optional<UUID>> ownerUUID;
private static final DataWatcherObject<Byte> bw; // DATA_FLAGS_ID
private static final Predicate<Entity> bC; // AVOID_PLAYERS
//private static final EntityDataAccessor<Byte> bw; // DATA_FLAGS_ID
private static final Predicate<Entity> AVOID_PLAYERS; // AVOID_PLAYERS
static {
tamed = DataWatcher.a(EntityTamableFox.class, DataWatcherRegistry.a);
ownerUUID = DataWatcher.a(EntityTamableFox.class, DataWatcherRegistry.o);
tamed = SynchedEntityData.defineId(EntityTamableFox.class, EntityDataSerializers.BYTE);
ownerUUID = SynchedEntityData.defineId(EntityTamableFox.class, EntityDataSerializers.OPTIONAL_UUID);
bw = DataWatcher.a(EntityFox.class, DataWatcherRegistry.a);
bC = (entity) -> !entity.isSneaking() && IEntitySelector.e.test(entity);
AVOID_PLAYERS = (entity) -> !entity.isCrouching();// && EntitySelector.test(entity);
}
List<PathfinderGoal> untamedGoals;
private FoxPathfinderGoalSit goalSit;
List<Goal> untamedGoals;
private FoxPathfinderGoalSitWhenOrdered goalSitWhenOrdered;
private FoxPathfinderGoalSleepWhenOrdered goalSleepWhenOrdered;
public EntityTamableFox(EntityTypes<? extends EntityFox> entitytypes, World world) {
super(entitytypes, world);
public EntityTamableFox(EntityType<? extends Fox> entitytype, Level world) {
super(entitytype, world);
this.getAttributeInstance(GenericAttributes.d).setValue(0.33000001192092896D); // Set movement speed
this.getAttribute(Attributes.MOVEMENT_SPEED).setBaseValue(0.33000001192092896D); // Set movement speed
if (isTamed()) {
this.getAttributeInstance(GenericAttributes.a).setValue(24.0D); // Set max health
this.getAttributeInstance(GenericAttributes.f).setValue(3.0D); // Set attack damage
this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(24.0D);
this.getAttribute(Attributes.ATTACK_DAMAGE).setBaseValue(3.0D);
this.setHealth(this.getMaxHealth());
} else {
this.getAttributeInstance(GenericAttributes.a).setValue(10.0D); // Set max health
this.getAttributeInstance(GenericAttributes.f).setValue(2.0D); // Set attack damage
this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(10.0D);
this.getAttribute(Attributes.ATTACK_DAMAGE).setBaseValue(2.0D);
}
}
@Override
public void initPathfinder() {
public void registerGoals() {
try {
this.goalSit = new FoxPathfinderGoalSit(this);
this.bO.a(1, goalSit);
this.goalSitWhenOrdered = new FoxPathfinderGoalSitWhenOrdered(this);
this.goalSelector.addGoal(1, goalSitWhenOrdered);
this.goalSleepWhenOrdered = new FoxPathfinderGoalSleepWhenOrdered(this);
this.goalSelector.addGoal(1, goalSleepWhenOrdered);
// Wild animal attacking
Field landTargetGoal = this.getClass().getSuperclass().getDeclaredField("cj"); // landTargetGoal
landTargetGoal.setAccessible(true);
landTargetGoal.set(this, new PathfinderGoalNearestAttackableTarget(this, EntityAnimal.class, 10, false, false, (entityliving) -> {
return (!isTamed() || (Config.doesTamedAttackWildAnimals() && isTamed())) && (entityliving instanceof EntityChicken || entityliving instanceof EntityRabbit);
landTargetGoal.set(this, new NearestAttackableTargetGoal(this, Animal.class, 10, false, false, (entityliving) -> {
return (!isTamed() || (Config.doesTamedAttackWildAnimals() && isTamed())) && (entityliving instanceof Chicken || entityliving instanceof Rabbit);
}));
Field turtleEggTargetGoal = this.getClass().getSuperclass().getDeclaredField("ck"); // turtleEggTargetGoal
turtleEggTargetGoal.setAccessible(true);
turtleEggTargetGoal.set(this, new PathfinderGoalNearestAttackableTarget(this, EntityTurtle.class, 10, false, false, EntityTurtle.bT));
turtleEggTargetGoal.set(this, new NearestAttackableTargetGoal(this, Turtle.class, 10, false, false, Turtle.BABY_ON_LAND_SELECTOR));
Field fishTargetGoal = this.getClass().getSuperclass().getDeclaredField("cl"); // fishTargetGoal
fishTargetGoal.setAccessible(true);
fishTargetGoal.set(this, new PathfinderGoalNearestAttackableTarget(this, EntityFish.class, 20, false, false, (entityliving) -> {
return (!isTamed() || (Config.doesTamedAttackWildAnimals() && isTamed())) && entityliving instanceof EntityFishSchool;
fishTargetGoal.set(this, new NearestAttackableTargetGoal(this, AbstractFish.class, 20, false, false, (entityliving) -> {
return (!isTamed() || (Config.doesTamedAttackWildAnimals() && isTamed())) && entityliving instanceof AbstractSchoolingFish;
}));
this.goalSelector().a(0, getFoxInnerPathfinderGoal("g")); // FoxFloatGoal
this.goalSelector().a(1, getFoxInnerPathfinderGoal("b")); // FaceplantGoal
this.goalSelector().a(2, new FoxPathfinderGoalPanic(this, 2.2D));
this.goalSelector().a(2, new FoxPathfinderGoalSleepWithOwner(this));
this.goalSelector().a(3, getFoxInnerPathfinderGoal("e", Arrays.asList(1.0D), Arrays.asList(double.class))); // FoxBreedGoal
this.goalSelector.addGoal(0, getFoxInnerPathfinderGoal("g")); // FoxFloatGoal
this.goalSelector.addGoal(1, getFoxInnerPathfinderGoal("b")); // FaceplantGoal
this.goalSelector.addGoal(2, getFoxInnerPathfinderGoal("n", Arrays.asList(2.2D), Arrays.asList(double.class))); // FoxPanicGoal
this.goalSelector.addGoal(2, new FoxPathfinderGoalSleepWithOwner(this));
this.goalSelector.addGoal(3, getFoxInnerPathfinderGoal("e", Arrays.asList(1.0D), Arrays.asList(double.class))); // FoxBreedGoal
this.goalSelector().a(4, new PathfinderGoalAvoidTarget(this, EntityHuman.class, 16.0F, 1.6D, 1.4D, (entityliving) -> {
return !isTamed() && bC.test((EntityLiving) entityliving) && !this.isDefending();
this.goalSelector.addGoal(4, new AvoidEntityGoal(this, Player.class, 16.0F, 1.6D, 1.4D, (entityliving) -> {
return !isTamed() && AVOID_PLAYERS.test((LivingEntity) entityliving) && !this.isDefending();
}));
this.goalSelector().a(4, new PathfinderGoalAvoidTarget(this, EntityWolf.class, 8.0F, 1.6D, 1.4D, (entityliving) -> {
return !((EntityWolf)entityliving).isTamed() && !this.isDefending();
this.goalSelector.addGoal(4, new AvoidEntityGoal(this, Wolf.class, 8.0F, 1.6D, 1.4D, (entityliving) -> {
return !((Wolf)entityliving).isTame() && !this.isDefending();
}));
this.goalSelector().a(4, new PathfinderGoalAvoidTarget(this, EntityPolarBear.class, 8.0F, 1.6D, 1.4D, (entityliving) -> {
this.goalSelector.addGoal(4, new AvoidEntityGoal(this, PolarBear.class, 8.0F, 1.6D, 1.4D, (entityliving) -> {
return !this.isDefending();
}));
this.goalSelector().a(5, getFoxInnerPathfinderGoal("u")); // StalkPreyGoal
this.goalSelector().a(6, new o()); // FoxPounceGoal
this.goalSelector().a(7, getFoxInnerPathfinderGoal("l", Arrays.asList(1.2000000476837158D, true), Arrays.asList(double.class, boolean.class))); // FoxMeleeAttackGoal
this.goalSelector().a(8, getFoxInnerPathfinderGoal("h", Arrays.asList(this, 1.25D), Arrays.asList(EntityFox.class, double.class))); // FoxFollowParentGoal
this.goalSelector().a(8, new FoxPathfinderGoalSleepWithOwner(this));
this.goalSelector().a(9, new FoxPathfinderGoalFollowOwner(this, 1.3D, 10.0F, 2.0F, false));
this.goalSelector().a(10, new PathfinderGoalLeapAtTarget(this, 0.4F));
this.goalSelector().a(11, new PathfinderGoalRandomStrollLand(this, 1.0D));
this.goalSelector().a(11, getFoxInnerPathfinderGoal("p")); // FoxSearchForItemsGoal
this.goalSelector().a(12, getFoxInnerPathfinderGoal("j", Arrays.asList(this, EntityHuman.class, 24.0f),
Arrays.asList(EntityInsentient.class, Class.class, float.class))); // LookAtPlayer
this.goalSelector.addGoal(5, getFoxInnerPathfinderGoal("u")); // StalkPreyGoal
this.goalSelector.addGoal(6, new FoxPounceGoal());
this.goalSelector.addGoal(7, getFoxInnerPathfinderGoal("l", Arrays.asList(1.2000000476837158D, true), Arrays.asList(double.class, boolean.class))); // FoxMeleeAttackGoal
this.goalSelector.addGoal(8, getFoxInnerPathfinderGoal("h", Arrays.asList(this, 1.25D), Arrays.asList(Fox.class, double.class))); // FoxFollowParentGoal
//this.goalSelector.addGoal(8, new FoxPathfinderGoalSleepWithOwner(this));
this.goalSelector.addGoal(9, new FoxPathfinderGoalFollowOwner(this, 1.3D, 10.0F, 2.0F, false));
this.goalSelector.addGoal(10, new LeapAtTargetGoal(this, 0.4F));
this.goalSelector.addGoal(11, new RandomStrollGoal(this, 1.0D));
this.goalSelector.addGoal(11, getFoxInnerPathfinderGoal("p")); // FoxSearchForItemsGoal
this.goalSelector.addGoal(12, getFoxInnerPathfinderGoal("j", Arrays.asList(this, Player.class, 24.0f),
Arrays.asList(Mob.class, Class.class, float.class))); // LookAtPlayer
this.targetSelector().a(1, new FoxPathfinderGoalOwnerHurtByTarget(this));
this.targetSelector().a(2, new FoxPathfinderGoalOwnerHurtTarget(this));
this.targetSelector().a(3, (new FoxPathfinderGoalHurtByTarget(this)).a(new Class[0]));
this.targetSelector.addGoal(1, new FoxPathfinderGoalOwnerHurtByTarget(this));
this.targetSelector.addGoal(2, new FoxPathfinderGoalOwnerHurtTarget(this));
this.targetSelector.addGoal(3, (new FoxPathfinderGoalHurtByTarget(this)).setAlertOthers(new Class[0]));
// Assign all the untamed goals that will later be removed.
untamedGoals = new ArrayList<>();
// SleepGoal
PathfinderGoal sleep = getFoxInnerPathfinderGoal("t");
this.goalSelector().a(7, sleep);
Goal sleep = getFoxInnerPathfinderGoal("t");
this.goalSelector.addGoal(7, sleep);
untamedGoals.add(sleep);
// PerchAndSearch (Random sitting?)
PathfinderGoal perchAndSearch = getFoxInnerPathfinderGoal("r");
this.goalSelector().a(13, perchAndSearch);
// PerchAndSearchGoal
Goal perchAndSearch = getFoxInnerPathfinderGoal("r");
this.goalSelector.addGoal(13, perchAndSearch);
untamedGoals.add(perchAndSearch);
// FoxEatBerriesGoal (Pick berry bushes)
PathfinderGoal eatBerries = new f(1.2000000476837158D, 12, 2);
this.goalSelector().a(11, eatBerries);
Goal eatBerries = new FoxEatBerriesGoal(1.2000000476837158D, 12, 2);
this.goalSelector.addGoal(11, eatBerries);
untamedGoals.add(eatBerries); // Maybe this should be configurable too?
// SeekShelterGoal
PathfinderGoal seekShelter = getFoxInnerPathfinderGoal("s", Arrays.asList(1.25D), Arrays.asList(double.class));
this.goalSelector().a(6, seekShelter);
Goal seekShelter = getFoxInnerPathfinderGoal("s", Arrays.asList(1.25D), Arrays.asList(double.class));
this.goalSelector.addGoal(6, seekShelter);
untamedGoals.add(seekShelter);
// StrollThroughVillage
PathfinderGoal strollThroughVillage = getFoxInnerPathfinderGoal("q", Arrays.asList(32, 200), Arrays.asList(int.class, int.class));
this.goalSelector().a(9, strollThroughVillage);
// FoxStrollThroughVillageGoal
Goal strollThroughVillage = getFoxInnerPathfinderGoal("q", Arrays.asList(32, 200), Arrays.asList(int.class, int.class));
this.goalSelector.addGoal(9, strollThroughVillage);
untamedGoals.add(strollThroughVillage);
} catch (Exception e) {
e.printStackTrace();
}
}
private DataWatcher datawatcher() {
return this.Y;
}
private PathfinderGoalSelector goalSelector() {
return this.bO;
}
private PathfinderGoalSelector targetSelector() {
return this.bP;
}
private Random random() {
return this.Q;
}
// deobf: 'getFlag'
private boolean u(int i) {
return ((Byte)datawatcher().get(bw) & i) != 0;
}
// deobf: 'isDefending' from 'fI'
public boolean isDefending() {
return this.u(128);
}
public static Object getPrivateField(String fieldName, Class clazz, Object object) {
Field field;
Object o = null;
try {
field = clazz.getDeclaredField(fieldName);
field.setAccessible(true);
o = field.get(object);
} catch (NoSuchFieldException | IllegalAccessException e) {
Method method = Fox.class.getDeclaredMethod("fI"); // isDefending
method.setAccessible(true);
boolean defending = (boolean) method.invoke((Fox) this);
method.setAccessible(false);
return defending;
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
return o;
}
protected void initDatawatcher() {
super.initDatawatcher();
this.datawatcher().register(tamed, (byte) 0);
this.datawatcher().register(ownerUUID, Optional.empty());
return false;
}
@Override
public void saveData(NBTTagCompound compound) {
super.saveData(compound);
protected void defineSynchedData() {
super.defineSynchedData();
this.entityData.define(tamed, (byte) 0);
this.entityData.define(ownerUUID, Optional.empty());
}
@Override
public void addAdditionalSaveData(CompoundTag compound) {
super.addAdditionalSaveData(compound);
if (this.getOwnerUUID() == null) {
compound.setString("OwnerUUID", "");
compound.putUUID("OwnerUUID", new UUID(0L, 0L));
} else {
compound.setString("OwnerUUID", this.getOwnerUUID().toString());
compound.putUUID("OwnerUUID", this.getOwnerUUID());
}
compound.setBoolean("Sitting", this.goalSit.isWillSit());
compound.putBoolean("Sitting", this.goalSitWhenOrdered.isOrderedToSit());
compound.putBoolean("Sleeping", this.goalSleepWhenOrdered.isOrderedToSleep());
}
@Override
public void loadData(NBTTagCompound compound) {
super.loadData(compound);
String ownerUuid = "";
public void readAdditionalSaveData(CompoundTag compound) {
super.readAdditionalSaveData(compound);
UUID ownerUuid = null;
if (compound.hasKeyOfType("OwnerUUID", 8)) {
ownerUuid = compound.getString("OwnerUUID");
}
if (!ownerUuid.isEmpty()) {
if (compound.contains("OwnerUUID")) {
try {
this.setOwnerUUID(UUID.fromString(ownerUuid));
this.setTamed(true);
} catch (Throwable throwable) {
this.setTamed(false);
ownerUuid = compound.getUUID("OwnerUUID");
} catch (IllegalArgumentException e) {
String uuidStr = compound.getString("OwnerUUID");
if (!uuidStr.isEmpty()) {
ownerUuid = UUID.fromString(uuidStr);
} else {
ownerUuid = null;
}
}
}
if (this.goalSit != null) {
this.goalSit.setSitting(compound.getBoolean("Sitting"));
if (ownerUuid != null) {
this.setOwnerUUID(ownerUuid);
this.setTamed(true);
}
if (this.goalSitWhenOrdered != null) {
this.goalSitWhenOrdered.setOrderedToSit(compound.getBoolean("Sitting"));
}
if (this.goalSleepWhenOrdered != null) {
this.goalSleepWhenOrdered.setOrderedToSleep(compound.getBoolean("Sleeping"));
}
if (!this.isTamed()) {
goalSit.setSitting(false);
goalSitWhenOrdered.setOrderedToSit(false);
goalSleepWhenOrdered.setOrderedToSleep(false);
}
}
public boolean isTamed() {
return ((Byte) this.datawatcher().get(tamed) & 4) != 0;
return ((Byte) this.entityData.get(tamed) & 4) != 0;
}
public void setTamed(boolean tamed_) {
byte isTamed = this.datawatcher().get(tamed);
byte isTamed = this.entityData.get(tamed);
if (tamed_) {
this.datawatcher().set(tamed, (byte) (isTamed | 4));
this.entityData.set(tamed, (byte) (isTamed | 4));
} else {
this.datawatcher().set(tamed, (byte) (isTamed & -5));
this.entityData.set(tamed, (byte) (isTamed & -5));
}
this.reassessTameGoals();
if (tamed_) {
this.getAttributeInstance(GenericAttributes.a).setValue(24.0D); // Set max health
this.getAttributeInstance(GenericAttributes.f).setValue(3.0D); // Set attack damage
this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(24.0D);
this.getAttribute(Attributes.ATTACK_DAMAGE).setBaseValue(3.0D);
} else {
this.getAttributeInstance(GenericAttributes.a).setValue(10.0D); // Set max health
this.getAttributeInstance(GenericAttributes.f).setValue(2.0D); // Set attack damage
this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(10.0D);
this.getAttribute(Attributes.ATTACK_DAMAGE).setBaseValue(2.0D);
}
this.setHealth(this.getMaxHealth());
}
@ -288,120 +262,114 @@ public class EntityTamableFox extends EntityFox {
private void reassessTameGoals() {
if (!isTamed()) return;
for (PathfinderGoal untamedGoal : untamedGoals) {
this.goalSelector().a(untamedGoal);
for (Goal untamedGoal : untamedGoals) {
this.goalSelector.removeGoal(untamedGoal);
}
}
// mobInteract
@Override
public EnumInteractionResult b(EntityHuman entityhuman, EnumHand enumhand) {
ItemStack itemstack = entityhuman.b(enumhand);
public InteractionResult mobInteract(Player entityhuman, InteractionHand enumhand) {
ItemStack itemstack = entityhuman.getItemInHand(enumhand);
Item item = itemstack.getItem();
if (itemstack.getItem() instanceof ItemMonsterEgg) {
return super.b(entityhuman, enumhand);
if (itemstack.getItem() instanceof SpawnEggItem) {
return super.mobInteract(entityhuman, enumhand);
} else {
if (this.isTamed()) {
// Heal the fox if its health is below the max.
if (item.isFood() && item.getFoodInfo().c() && this.getHealth() < this.getMaxHealth()) {
if (item.isEdible() && item.getFoodProperties().isMeat() && this.getHealth() < this.getMaxHealth()) {
// Only remove the item from the player if they're in survival mode.
Player player = (Player) entityhuman.getBukkitEntity();
org.bukkit.entity.Player player = (org.bukkit.entity.Player) entityhuman.getBukkitEntity();
if (player.getGameMode() != GameMode.CREATIVE ) {
itemstack.subtract(1);
itemstack.shrink(1);
}
this.heal((float)item.getFoodInfo().getNutrition(), EntityRegainHealthEvent.RegainReason.EATING);
return EnumInteractionResult.b; // CONSUME
this.heal((float)item.getFoodProperties().getNutrition(), EntityRegainHealthEvent.RegainReason.EATING);
return InteractionResult.CONSUME;
}
if (isOwnedBy(entityhuman)) {
if (isOwnedBy(entityhuman) && enumhand == InteractionHand.MAIN_HAND) {
// This super method checks if the fox can breed or not.
EnumInteractionResult flag = super.b(entityhuman, enumhand);
InteractionResult flag = super.mobInteract(entityhuman, enumhand);
// If the player is not sneaking and the fox cannot breed, then make the fox sit.
// @TODO: Do I need to use this.eQ() instead of flag != EnumInteractionResult.SUCCESS?
// EnumInteractionResult.a = EnumInteractionResult.SUCCESS
if (!entityhuman.isSneaking() && (flag != EnumInteractionResult.a || this.isBaby())) {
this.setSleeping(false);
this.goalSit.setSitting(!this.isSitting());
return flag;
} else if (entityhuman.isSneaking() && enumhand == EnumHand.a) { // EnumHand.a = EnumHand.MAIN_HAND; Swap/Put/Take item from fox.
if (!entityhuman.isCrouching() && (flag != InteractionResult.SUCCESS || this.isBaby())) {
this.goalSleepWhenOrdered.setOrderedToSleep(false);
this.goalSitWhenOrdered.setOrderedToSit(!this.isOrderedToSit());
return InteractionResult.SUCCESS;
} else if (entityhuman.isCrouching()) { // Swap/Put/Take item from fox.
// Ignore buckets since they can be easily duplicated.
// nW = BUCKET; nX = WATER_BUCKET; nY = LAVA_BUCKET
if (itemstack.getItem() == Items.nW || itemstack.getItem() == Items.nX || itemstack.getItem() == Items.nY) {
return EnumInteractionResult.c; // EnumInteractionResult.c = EnumInteractionResult.PASS
if (itemstack.getItem() instanceof BucketItem) {
return InteractionResult.PASS;
}
// Check if the player has something in their main hand.
// EnumItemSlot.MAINHAND = EnumItemSlot.a
if (!this.getEquipment(EnumItemSlot.a).isEmpty()) {
getBukkitEntity().getWorld().dropItem(getBukkitEntity().getLocation(), CraftItemStack.asBukkitCopy(this.getEquipment(EnumItemSlot.a)));
this.setSlot(EnumItemSlot.a, new ItemStack(Items.a)); // Items.a = AIR
// If the fox has something in its mouth and the player has something in its hand, empty it.
if (this.hasItemInSlot(EquipmentSlot.MAINHAND)) {
getBukkitEntity().getWorld().dropItem(getBukkitEntity().getLocation(), CraftItemStack.asBukkitCopy(this.getItemBySlot(EquipmentSlot.MAINHAND)));
this.setSlot(EquipmentSlot.MAINHAND, new ItemStack(Items.AIR), false);
} // Check if the player's hand is empty and if it is, make the fox sleep.
// The reason its here is to make sure that we don't take the item
// from its mouth and make it sleep in a single click.
else if (!entityhuman.hasItemInSlot(EquipmentSlot.MAINHAND)) {
this.goalSitWhenOrdered.setOrderedToSit(false);
this.goalSleepWhenOrdered.setOrderedToSleep(!this.goalSleepWhenOrdered.isOrderedToSleep());
}
// Run this task async to make sure to not slow the server down.
// This is needed due to the item being remove as soon as its put in the foxes mouth.
// This is needed due to the item being removed as soon as its put in the foxes mouth.
Bukkit.getScheduler().runTaskLaterAsynchronously(Utils.tamableFoxesPlugin, ()-> {
// Put item in mouth
if (item != Items.a) { // Items.a = AIR
ItemStack c = itemstack.cloneItemStack();
if (entityhuman.hasItemInSlot(EquipmentSlot.MAINHAND)) {
ItemStack c = itemstack.copy();
c.setCount(1);
// Only remove the item from the player if they're in survival mode.
Player player = (Player) entityhuman.getBukkitEntity();
org.bukkit.entity.Player player = (org.bukkit.entity.Player) entityhuman.getBukkitEntity();
if (player.getGameMode() != GameMode.CREATIVE ) {
itemstack.subtract(1);
itemstack.shrink(1);
}
this.setSlot(EnumItemSlot.a, c);
this.setSlot(EquipmentSlot.MAINHAND, c, false);
}
// If the player doesn't have anything in their hand, make the fox sleep or wakeup.
else {
this.goalSit.setSitting(false);
this.setSleeping(!this.isSleeping());
}
}, (long) 0.1);
}, 1L);
return EnumInteractionResult.a;
//return true;
return InteractionResult.SUCCESS;
}
}
} else if (item == Items.px) { // px = CHICKEN
} else if (item == Items.CHICKEN) {
// Check if the player has permissions to tame the fox
if (Config.canPlayerTameFox((Player) entityhuman.getBukkitEntity())) {
if (Config.canPlayerTameFox((org.bukkit.entity.Player) entityhuman.getBukkitEntity())) {
// Only remove the item from the player if they're in survival mode.
Player player = (Player) entityhuman.getBukkitEntity();
org.bukkit.entity.Player player = (org.bukkit.entity.Player) entityhuman.getBukkitEntity();
if (player.getGameMode() != GameMode.CREATIVE ) {
itemstack.subtract(1);
itemstack.shrink(1);
}
SQLiteHelper sqLiteHelper = SQLiteHelper.getInstance(Utils.tamableFoxesPlugin);
int maxTameCount = Config.getMaxPlayerFoxTames();
if ( !((Player) entityhuman.getBukkitEntity()).hasPermission("tamablefoxes.tame.unlimited") && maxTameCount > 0 && sqLiteHelper.getPlayerFoxAmount(entityhuman.getUniqueID()) >= maxTameCount) {
((Player) entityhuman.getBukkitEntity()).sendMessage(Config.getPrefix() + ChatColor.RED + LanguageConfig.getFoxDoesntTrust());
if ( !((org.bukkit.entity.Player) entityhuman.getBukkitEntity()).hasPermission("tamablefoxes.tame.unlimited") && maxTameCount > 0 && sqLiteHelper.getPlayerFoxAmount(entityhuman.getUUID()) >= maxTameCount) {
((org.bukkit.entity.Player) entityhuman.getBukkitEntity()).sendMessage(Config.getPrefix() + ChatColor.RED + LanguageConfig.getFoxDoesntTrust());
return EnumInteractionResult.a;
return InteractionResult.SUCCESS;
}
// 0.33% chance to tame the fox, also check if the called tame entity event is cancelled or not.
if (this.getRandom().nextInt(3) == 0 && !CraftEventFactory.callEntityTameEvent(this, entityhuman).isCancelled()) {
this.tame(entityhuman);
// Remove all navigation when tamed.
this.bN.o(); // bN = navigation
this.setGoalTarget(null);
this.goalSit.setSitting(true);
this.navigation.stop();
this.goalSitWhenOrdered.setOrderedToSit(true);
if (maxTameCount > 0) {
sqLiteHelper.addPlayerFoxAmount(entityhuman.getUniqueID(), 1);
sqLiteHelper.addPlayerFoxAmount(entityhuman.getUUID(), 1);
}
getBukkitEntity().getWorld().spawnParticle(org.bukkit.Particle.HEART, getBukkitEntity().getLocation(), 6, 0.5D, 0.5D, 0.5D);
// Give player tamed message.
((Player) entityhuman.getBukkitEntity()).sendMessage(Config.getPrefix() + ChatColor.GREEN + LanguageConfig.getTamedMessage());
((org.bukkit.entity.Player) entityhuman.getBukkitEntity()).sendMessage(Config.getPrefix() + ChatColor.GREEN + LanguageConfig.getTamedMessage());
// Let the player choose the new fox's name if its enabled in config.
if (Config.askForNameAfterTaming()) {
@ -430,17 +398,17 @@ public class EntityTamableFox extends EntityFox {
}
}
return EnumInteractionResult.a;
return InteractionResult.SUCCESS;
}
return super.b(entityhuman, enumhand);
return super.mobInteract(entityhuman, enumhand);
}
}
@Override
public EntityTamableFox createChild(WorldServer worldserver, EntityAgeable entityageable) {
EntityTamableFox entityfox = (EntityTamableFox) EntityTypes.E.a(worldserver); // EntityTypes.E = EntityTypes.FOX
entityfox.setFoxType(this.getRandom().nextBoolean() ? this.getFoxType() : ((EntityFox)entityageable).getFoxType());
public EntityTamableFox createChild(ServerLevel worldserver, AgeableMob entityageable) {
EntityTamableFox entityfox = (EntityTamableFox) EntityType.FOX.create(worldserver);
entityfox.setFoxType(this.getRandom().nextBoolean() ? this.getFoxType() : ((Fox)entityageable).getFoxType());
UUID uuid = this.getOwnerUUID();
if (uuid != null) {
@ -451,55 +419,42 @@ public class EntityTamableFox extends EntityFox {
return entityfox;
}
@Override
public boolean mate(EntityAnimal entityanimal) {
if (entityanimal == this) {
return false;
} else if (!(entityanimal instanceof EntityTamableFox)) {
return false;
} else {
EntityTamableFox entityFox = (EntityTamableFox) entityanimal;
return (!entityFox.isSitting() && (this.isInLove() && entityFox.isInLove()));
}
}
@Nullable
public UUID getOwnerUUID() {
return (UUID) ((Optional) this.datawatcher().get(ownerUUID)).orElse(null);
return (UUID) ((Optional) this.entityData.get(ownerUUID)).orElse(null);
}
public void setOwnerUUID(@Nullable UUID ownerUuid) {
this.datawatcher().set(ownerUUID, Optional.ofNullable(ownerUuid));
this.entityData.set(ownerUUID, Optional.ofNullable(ownerUuid));
}
public void tame(EntityHuman owner) {
public void tame(Player owner) {
this.setTamed(true);
this.setOwnerUUID(owner.getUniqueID());
this.setOwnerUUID(owner.getUUID());
// Give the player the taming advancement.
if (owner instanceof EntityPlayer) {
CriterionTriggers.x.a((EntityPlayer)owner, this);
if (owner instanceof ServerPlayer) {
CriteriaTriggers.TAME_ANIMAL.trigger((ServerPlayer) owner, this);
}
}
@Nullable
public EntityLiving getOwner() {
public LivingEntity getOwner() {
try {
UUID ownerUuid = this.getOwnerUUID();
return ownerUuid == null ? null : this.getWorld().b(ownerUuid);
return ownerUuid == null ? null : this.getCommandSenderWorld().getPlayerByUUID(ownerUuid);
} catch (IllegalArgumentException var2) {
return null;
}
}
// Only attack entity if its not attacking owner.
// canAttack
@Override
public boolean c(EntityLiving entity) {
return !this.isOwnedBy(entity) && super.c(entity);
public boolean canAttack(LivingEntity entity) {
return !this.isOwnedBy(entity) && super.canAttack(entity);
}
public boolean isOwnedBy(EntityLiving entity) {
public boolean isOwnedBy(LivingEntity entity) {
return entity == this.getOwner();
}
@ -508,17 +463,17 @@ public class EntityTamableFox extends EntityFox {
This code being from EntityWolf also means that wolves will want to attack foxes
Our life would be so much easier if we could extend both EntityFox and EntityTameableAnimal
*/
public boolean wantsToAttack(EntityLiving entityliving, EntityLiving entityliving1) {
if (!(entityliving instanceof EntityCreeper) && !(entityliving instanceof EntityGhast)) {
public boolean wantsToAttack(LivingEntity entityliving, LivingEntity entityliving1) {
if (!(entityliving instanceof Creeper) && !(entityliving instanceof Ghast)) {
if (entityliving instanceof EntityTamableFox) {
EntityTamableFox entityFox = (EntityTamableFox) entityliving;
return !entityFox.isTamed() || entityFox.getOwner() != entityliving1;
} else {
return (!(entityliving instanceof EntityHuman)
|| !(entityliving1 instanceof EntityHuman) ||
((EntityHuman) entityliving1).a((EntityHuman) entityliving)) && ((!(entityliving instanceof EntityHorseAbstract)
|| !((EntityHorseAbstract) entityliving).isTamed()) && (!(entityliving instanceof EntityTameableAnimal)
|| !((EntityTameableAnimal) entityliving).isTamed()));
return (!(entityliving instanceof Player)
|| !(entityliving1 instanceof Player) ||
((Player) entityliving1).canHarmPlayer((Player) entityliving)) && ((!(entityliving instanceof AbstractHorse)
|| !((AbstractHorse) entityliving).isTamed()) && (!(entityliving instanceof TamableAnimal)
|| !((TamableAnimal) entityliving).isTame()));
}
} else {
return false;
@ -526,42 +481,44 @@ public class EntityTamableFox extends EntityFox {
}
// Set the scoreboard team to the same as the owner if its tamed.
public ScoreboardTeamBase getScoreboardTeam() {
@Override
public Team getTeam() {
if (this.isTamed()) {
EntityLiving var0 = this.getOwner();
LivingEntity var0 = this.getOwner();
if (var0 != null) {
return var0.getScoreboardTeam();
return var0.getTeam();
}
}
return super.getScoreboardTeam();
return super.getTeam();
}
// Override isAlliedTo (Entity::r(Entity))
public boolean r(Entity entity) {
@Override
public boolean isAlliedTo(Entity entity) {
if (this.isTamed()) {
EntityLiving entityOwner = this.getOwner();
LivingEntity entityOwner = this.getOwner();
if (entity == entityOwner) {
return true;
}
if (entityOwner != null) {
return entityOwner.r(entity);
return entityOwner.isAlliedTo(entity);
}
}
return super.r(entity);
return super.isAlliedTo(entity);
}
// When the fox dies, show a chat message.
@Override
public void die(DamageSource damageSource) {
// getWorld().y = getWorld().isClientSide; GameRules.m = GameRules.SHOW_DEATH_MESSAGES
if (!this.getWorld().y && this.getWorld().getGameRules().getBoolean(GameRules.m) && this.getOwner() instanceof EntityPlayer) {
if (!this.getCommandSenderWorld().isClientSide && this.getCommandSenderWorld().getGameRules().getBoolean(GameRules.RULE_SHOWDEATHMESSAGES) && this.getOwner() instanceof ServerPlayer) {
this.getOwner().sendMessage(this.getCombatTracker().getDeathMessage(), getOwnerUUID());
// Remove the amount of foxes the player has tamed if the limit is enabled.
if (Config.getMaxPlayerFoxTames() > 0) {
SQLiteHelper sqliteHelper = SQLiteHelper.getInstance(Utils.tamableFoxesPlugin);
sqliteHelper.removePlayerFoxAmount(this.getOwner().getUniqueID(), 1);
sqliteHelper.removePlayerFoxAmount(this.getOwner().getUUID(), 1);
}
}
@ -569,28 +526,19 @@ public class EntityTamableFox extends EntityFox {
}
private PathfinderGoal getFoxInnerPathfinderGoal(String innerName, List<Object> args, List<Class<?>> argTypes) {
return (PathfinderGoal) Utils.instantiatePrivateInnerClass(EntityFox.class, innerName, this, args, argTypes);
private Goal getFoxInnerPathfinderGoal(String innerName, List<Object> args, List<Class<?>> argTypes) {
return (Goal) Utils.instantiatePrivateInnerClass(Fox.class, innerName, this, args, argTypes);
}
private PathfinderGoal getFoxInnerPathfinderGoal(String innerName) {
return (PathfinderGoal) Utils.instantiatePrivateInnerClass(EntityFox.class, innerName, this, Arrays.asList(), Arrays.asList());
private Goal getFoxInnerPathfinderGoal(String innerName) {
return (Goal) Utils.instantiatePrivateInnerClass(Fox.class, innerName, this, Arrays.asList(), Arrays.asList());
}
private void clearPathFinderGoals() {
Set<?> goalSet = (Set<?>) getPrivateField("d", PathfinderGoalSelector.class, goalSelector());
Set<?> targetSet = (Set<?>) getPrivateField("d", PathfinderGoalSelector.class, targetSelector());
goalSet.clear();
targetSet.clear();
public boolean isOrderedToSit() { return this.goalSitWhenOrdered.isOrderedToSit(); }
Map<?, ?> goalMap = (Map<?, ?>) getPrivateField("c", PathfinderGoalSelector.class, goalSelector());
Map<?, ?> targetMap = (Map<?, ?>) getPrivateField("c", PathfinderGoalSelector.class, targetSelector());
goalMap.clear();
targetMap.clear();
public void setOrderedToSit(boolean flag) { this.goalSitWhenOrdered.setOrderedToSit(flag); }
EnumSet<?> goalEnumSet = (EnumSet<?>) getPrivateField("f", PathfinderGoalSelector.class, goalSelector());
EnumSet<?> targetEnumSet = (EnumSet<?>) getPrivateField("f", PathfinderGoalSelector.class, targetSelector());
goalEnumSet.clear();
targetEnumSet.clear();
}
public boolean isOrderedToSleep() { return this.goalSleepWhenOrdered.isOrderedToSleep(); }
public void setOrderedToSleep(boolean flag) { this.goalSleepWhenOrdered.setOrderedToSleep(flag); }
}

View File

@ -1,33 +1,24 @@
package net.seanomik.tamablefoxes.versions.version_1_17_R1;
import net.minecraft.world.entity.EntityTypes;
import net.minecraft.world.entity.animal.EntityFox;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.animal.Fox;
import net.seanomik.tamablefoxes.util.FieldHelper;
import net.seanomik.tamablefoxes.util.NMSInterface;
import net.seanomik.tamablefoxes.util.Utils;
import net.seanomik.tamablefoxes.util.io.Config;
import net.seanomik.tamablefoxes.util.io.LanguageConfig;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Location;
import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity;
import org.bukkit.entity.EntityType;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class NMSInterface_1_17_R1 implements NMSInterface {
@Override
public void registerCustomFoxEntity() {
try { // Replace the fox entity
Field field = EntityTypes.E.getClass().getDeclaredField("bm");
//FOX = a("fox", EntityTypes.Builder.a(EntityFox::new, EnumCreatureType.CREATURE).a(0.6F, 0.7F).trackingRange(8).a(Blocks.SWEET_BERRY_BUSH));
/*Method method = EntityTypes.class.getDeclaredMethod("a", String.class, EntityTypes.Builder.class);
method.setAccessible(true);
EntityTypes<EntityFox> type = method.invoke(null, "fox", EntityTypes.Builder.a(EntityTamableFox::new, EnumCreatureType.C))*/
FieldHelper.setField(field, EntityTypes.E, (EntityTypes.b<EntityFox>) EntityTamableFox::new);
Field field = EntityType.FOX.getClass().getDeclaredField("bm"); // bm = factory
FieldHelper.setField(field, EntityType.FOX, (EntityType.EntityFactory<Fox>) EntityTamableFox::new);
Bukkit.getServer().getConsoleSender().sendMessage(Config.getPrefix() + ChatColor.GREEN + LanguageConfig.getSuccessReplaced());
} catch (Exception e) {
Bukkit.getServer().getConsoleSender().sendMessage(Config.getPrefix() + ChatColor.RED + LanguageConfig.getFailureReplace());
@ -37,7 +28,7 @@ public class NMSInterface_1_17_R1 implements NMSInterface {
@Override
public void spawnTamableFox(Location loc, FoxType type) {
EntityTamableFox tamableFox = (EntityTamableFox) ((CraftEntity) loc.getWorld().spawnEntity(loc, EntityType.FOX)).getHandle();
tamableFox.setFoxType((type == FoxType.RED) ? EntityFox.Type.a : EntityFox.Type.b);
EntityTamableFox tamableFox = (EntityTamableFox) ((CraftEntity) loc.getWorld().spawnEntity(loc, org.bukkit.entity.EntityType.FOX)).getHandle();
tamableFox.setFoxType((type == FoxType.RED) ? Fox.Type.RED : Fox.Type.SNOW);
}
}

View File

@ -1,16 +1,16 @@
package net.seanomik.tamablefoxes.versions.version_1_17_R1.pathfinding;
import net.minecraft.core.BlockPosition;
import net.minecraft.world.entity.EntityLiving;
import net.minecraft.world.entity.ai.goal.PathfinderGoal;
import net.minecraft.world.entity.ai.navigation.Navigation;
import net.minecraft.world.entity.ai.navigation.NavigationAbstract;
import net.minecraft.world.entity.ai.navigation.NavigationFlying;
import net.minecraft.world.level.IWorldReader;
import net.minecraft.world.level.block.BlockLeaves;
import net.minecraft.world.level.block.state.IBlockData;
import net.minecraft.world.level.pathfinder.PathType;
import net.minecraft.world.level.pathfinder.PathfinderNormal;
import net.minecraft.core.BlockPos;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.ai.goal.Goal;
import net.minecraft.world.entity.ai.navigation.FlyingPathNavigation;
import net.minecraft.world.entity.ai.navigation.GroundPathNavigation;
import net.minecraft.world.entity.ai.navigation.PathNavigation;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.block.LeavesBlock;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.pathfinder.BlockPathTypes;
import net.minecraft.world.level.pathfinder.WalkNodeEvaluator;
import net.seanomik.tamablefoxes.versions.version_1_17_R1.EntityTamableFox;
import org.bukkit.Location;
import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity;
@ -18,88 +18,91 @@ import org.bukkit.event.entity.EntityTeleportEvent;
import java.util.EnumSet;
public class FoxPathfinderGoalFollowOwner extends PathfinderGoal {
private final EntityTamableFox a;
private EntityLiving b;
private final IWorldReader c;
private final double d;
private final NavigationAbstract e;
private int f;
private final float g;
private final float h;
private float i;
private final boolean j;
public class FoxPathfinderGoalFollowOwner extends Goal {
public static final int TELEPORT_WHEN_DISTANCE_IS = 12;
private static final int MIN_HORIZONTAL_DISTANCE_FROM_PLAYER_WHEN_TELEPORTING = 2;
private static final int MAX_HORIZONTAL_DISTANCE_FROM_PLAYER_WHEN_TELEPORTING = 3;
private static final int MAX_VERTICAL_DISTANCE_FROM_PLAYER_WHEN_TELEPORTING = 1;
private final EntityTamableFox tamableFox;
private LivingEntity owner;
private final LevelReader level;
private final double speedModifier;
private final PathNavigation navigation;
private int timeToRecalcPath;
private final float stopDistance;
private final float startDistance;
private float oldWaterCost;
private final boolean canFly;
public FoxPathfinderGoalFollowOwner(EntityTamableFox tamableFox, double d0, float f, float f1, boolean flag) {
this.a = tamableFox;
this.c = tamableFox.getWorld();
this.d = d0;
this.e = tamableFox.getNavigation();
this.h = f;
this.g = f1;
this.j = flag;
this.a(EnumSet.of(Type.a, Type.b)); // a = MOVE; b = LOOK
if (!(tamableFox.getNavigation() instanceof Navigation) && !(tamableFox.getNavigation() instanceof NavigationFlying)) {
throw new IllegalArgumentException("Unsupported mob type for FollowOwnerGoal");
public FoxPathfinderGoalFollowOwner(EntityTamableFox entityfox, double d0, float f, float f1, boolean flag) {
this.tamableFox = entityfox;
this.level = entityfox.level;
this.speedModifier = d0;
this.navigation = entityfox.getNavigation();
this.startDistance = f;
this.stopDistance = f1;
this.canFly = flag;
this.setFlags(EnumSet.of(Goal.Flag.MOVE, Flag.LOOK));
if (!(entityfox.getNavigation() instanceof GroundPathNavigation) && !(entityfox.getNavigation() instanceof FlyingPathNavigation)) {
throw new IllegalArgumentException("Unsupported mob type for FoxPathfinderGoalFollowOwner");
}
}
public boolean a() {
EntityLiving entityliving = this.a.getOwner();
public boolean canUse() {
LivingEntity entityliving = this.tamableFox.getOwner();
if (entityliving == null) {
return false;
} else if (entityliving.isSpectator()) {
return false;
} else if (this.a.isSitting()) { // this.a.isWillSit()
} else if (this.tamableFox.isOrderedToSit() || this.tamableFox.isOrderedToSleep()) {
return false;
} else if (this.a.f(entityliving) < (double)(this.h * this.h)) {
} else if (this.tamableFox.distanceToSqr(entityliving) < (double)(this.startDistance * this.startDistance)) {
return false;
} else {
this.b = entityliving;
this.owner = entityliving;
return true;
}
}
public boolean b() {
// Simplified with IntelliJ hints
return !this.e.m() && (!this.a.isSitting() && this.a.f(this.f) > (double) (this.g * this.g));
public boolean canContinueToUse() {
return !this.navigation.isDone() && (!this.tamableFox.isOrderedToSit() && !this.tamableFox.isOrderedToSleep() && this.tamableFox.distanceToSqr(this.owner) > (double) (this.stopDistance * this.stopDistance));
}
public void c() {
this.f = 0;
this.i = this.a.a(PathType.i);
this.a.a(PathType.i, 0.0F);
public void start() {
this.timeToRecalcPath = 0;
this.oldWaterCost = this.tamableFox.getPathfindingMalus(BlockPathTypes.WATER);
this.tamableFox.setPathfindingMalus(BlockPathTypes.WATER, 0.0F);
}
public void d() {
this.b = null;
this.e.o();
this.a.a(PathType.i, this.i);
public void stop() {
this.owner = null;
this.navigation.stop();
this.tamableFox.setPathfindingMalus(BlockPathTypes.WATER, this.oldWaterCost);
}
public void e() {
this.a.getControllerLook().a(this.b, 10.0F, (float)this.a.eY());
if (--this.f <= 0) {
this.f = 10;
if (!this.a.isLeashed() && !this.a.isPassenger()) {
if (this.a.f(this.b) >= 144.0D) {
this.g();
public void tick() {
this.tamableFox.getLookControl().setLookAt(this.owner, 10.0F, (float)this.tamableFox.getMaxHeadXRot());
if (--this.timeToRecalcPath <= 0) {
this.timeToRecalcPath = 10;
if (!this.tamableFox.isLeashed() && !this.tamableFox.isPassenger()) {
if (this.tamableFox.distanceToSqr(this.owner) >= 144.0D) {
this.teleportToOwner();
} else {
this.e.a(this.b, this.d);
this.navigation.moveTo(this.owner, this.speedModifier);
}
}
}
}
private void g() {
BlockPosition blockposition = this.b.getChunkCoordinates();
private void teleportToOwner() {
BlockPos blockposition = this.owner.blockPosition();
for(int i = 0; i < 10; ++i) {
int j = this.a(-3, 3);
int k = this.a(-1, 1);
int l = this.a(-3, 3);
boolean flag = this.a(blockposition.getX() + j, blockposition.getY() + k, blockposition.getZ() + l);
int j = this.randomIntInclusive(-3, 3);
int k = this.randomIntInclusive(-1, 1);
int l = this.randomIntInclusive(-3, 3);
boolean flag = this.maybeTeleportTo(blockposition.getX() + j, blockposition.getY() + k, blockposition.getZ() + l);
if (flag) {
return;
}
@ -107,43 +110,43 @@ public class FoxPathfinderGoalFollowOwner extends PathfinderGoal {
}
private boolean a(int i, int j, int k) {
if (Math.abs((double)i - this.b.locX()) < 2.0D && Math.abs((double)k - this.b.locZ()) < 2.0D) {
private boolean maybeTeleportTo(int i, int j, int k) {
if (Math.abs((double)i - this.owner.getX()) < 2.0D && Math.abs((double)k - this.owner.getZ()) < 2.0D) {
return false;
} else if (!this.a(new BlockPosition(i, j, k))) {
} else if (!this.canTeleportTo(new BlockPos(i, j, k))) {
return false;
} else {
CraftEntity entity = this.a.getBukkitEntity();
Location to = new Location(entity.getWorld(), (double)i + 0.5D, (double)j, (double)k + 0.5D, this.a.getYRot(), this.a.getXRot());
CraftEntity entity = this.tamableFox.getBukkitEntity();
Location to = new Location(entity.getWorld(), (double)i + 0.5D, (double)j, (double)k + 0.5D, this.tamableFox.getYRot(), this.tamableFox.getXRot());
EntityTeleportEvent event = new EntityTeleportEvent(entity, entity.getLocation(), to);
this.a.getWorld().getCraftServer().getPluginManager().callEvent(event);
this.tamableFox.level.getCraftServer().getPluginManager().callEvent(event);
if (event.isCancelled()) {
return false;
} else {
to = event.getTo();
this.a.setPositionRotation(to.getX(), to.getY(), to.getZ(), to.getYaw(), to.getPitch());
this.e.o();
this.tamableFox.moveTo(to.getX(), to.getY(), to.getZ(), to.getYaw(), to.getPitch());
this.navigation.stop();
return true;
}
}
}
private boolean a(BlockPosition blockposition) {
PathType pathtype = PathfinderNormal.a(this.c, blockposition.i());
if (pathtype != PathType.c) {
private boolean canTeleportTo(BlockPos blockposition) {
BlockPathTypes pathtype = WalkNodeEvaluator.getBlockPathTypeStatic(this.level, blockposition.mutable());
if (pathtype != BlockPathTypes.WALKABLE) {
return false;
} else {
IBlockData iblockdata = this.c.getType(blockposition.down());
if (!this.j && iblockdata.getBlock() instanceof BlockLeaves) {
BlockState iblockdata = this.level.getBlockState(blockposition.down());
if (!this.canFly && iblockdata.getBlock() instanceof LeavesBlock) {
return false;
} else {
BlockPosition blockposition1 = blockposition.e(this.a.getChunkCoordinates());
return this.c.getCubes(this.a, this.a.getBoundingBox().a(blockposition1));
BlockPos blockposition1 = blockposition.e(this.tamableFox.blockPosition());
return this.level.noCollision(this.tamableFox, this.tamableFox.getBoundingBox().move(blockposition1));
}
}
}
private int a(int i, int j) {
return this.a.getRandom().nextInt(j - i + 1) + i;
private int randomIntInclusive(int i, int j) {
return this.tamableFox.getRandom().nextInt(j - i + 1) + i;
}
}

View File

@ -1,13 +1,12 @@
package net.seanomik.tamablefoxes.versions.version_1_17_R1.pathfinding;
import net.minecraft.world.entity.EntityInsentient;
import net.minecraft.world.entity.EntityLiving;
import net.minecraft.world.entity.EntityTypes;
import net.minecraft.world.entity.IEntitySelector;
import net.minecraft.world.entity.ai.goal.target.PathfinderGoalTarget;
import net.minecraft.world.entity.ai.targeting.PathfinderTargetCondition;
import net.minecraft.world.entity.*;
import net.minecraft.world.entity.ai.goal.Goal;
import net.minecraft.world.entity.ai.goal.target.HurtByTargetGoal;
import net.minecraft.world.entity.ai.goal.target.TargetGoal;
import net.minecraft.world.entity.ai.targeting.TargetingConditions;
import net.minecraft.world.level.GameRules;
import net.minecraft.world.phys.AxisAlignedBB;
import net.minecraft.world.phys.AABB;
import net.seanomik.tamablefoxes.versions.version_1_17_R1.EntityTamableFox;
import org.bukkit.event.entity.EntityTargetEvent.TargetReason;
@ -15,27 +14,28 @@ import java.util.EnumSet;
import java.util.Iterator;
import java.util.List;
public class FoxPathfinderGoalHurtByTarget extends PathfinderGoalTarget {
private static final PathfinderTargetCondition a = PathfinderTargetCondition.a().d().e();
private boolean b;
private int c;
private final Class<?>[] d;
private Class<?>[] i;
public class FoxPathfinderGoalHurtByTarget extends TargetGoal {
private static final TargetingConditions HURT_BY_TARGETING = TargetingConditions.forCombat().ignoreLineOfSight().ignoreInvisibilityTesting();
private static final int ALERT_RANGE_Y = 10;
private boolean alertSameType;
private int timestamp;
private final Class<?>[] toIgnoreDamage;
private Class<?>[] toIgnoreAlert;
public FoxPathfinderGoalHurtByTarget(EntityTamableFox tamableFox, Class<?>... aclass) {
super(tamableFox, true);
this.d = aclass;
this.a(EnumSet.of(Type.d));
public FoxPathfinderGoalHurtByTarget(PathfinderMob entitycreature, Class<?>... aclass) {
super(entitycreature, true);
this.toIgnoreDamage = aclass;
this.setFlags(EnumSet.of(Flag.TARGET));
}
public boolean a() {
int i = this.e.dH();
EntityLiving entityliving = this.e.getLastDamager();
if (i != this.c && entityliving != null) {
if (entityliving.getEntityType() == EntityTypes.bi && this.e.getWorld().getGameRules().getBoolean(GameRules.I)) {
public boolean canUse() {
int i = this.mob.getLastHurtByMobTimestamp();
LivingEntity entityliving = this.mob.getLastHurtByMob();
if (i != this.timestamp && entityliving != null) {
if (entityliving.getType() == EntityType.PLAYER && this.mob.level.getGameRules().getBoolean(GameRules.RULE_UNIVERSAL_ANGER)) {
return false;
} else {
Class[] aclass = this.d;
Class[] aclass = this.toIgnoreDamage;
int j = aclass.length;
for(int k = 0; k < j; ++k) {
@ -45,39 +45,39 @@ public class FoxPathfinderGoalHurtByTarget extends PathfinderGoalTarget {
}
}
return this.a(entityliving, a);
return this.canAttack(entityliving, HURT_BY_TARGETING);
}
} else {
return false;
}
}
public FoxPathfinderGoalHurtByTarget a(Class<?>... aclass) {
this.b = true;
this.i = aclass;
public FoxPathfinderGoalHurtByTarget setAlertOthers(Class<?>... aclass) {
this.alertSameType = true;
this.toIgnoreAlert = aclass;
return this;
}
public void c() {
this.e.setGoalTarget(this.e.getLastDamager(), TargetReason.TARGET_ATTACKED_ENTITY, true);
this.g = this.e.getGoalTarget();
this.c = this.e.dH();
this.h = 300;
if (this.b) {
this.g();
public void start() {
this.mob.setGoalTarget(this.mob.getLastHurtByMob(), TargetReason.TARGET_ATTACKED_ENTITY, true);
this.targetMob = this.mob.getTarget();
this.timestamp = this.mob.getLastHurtByMobTimestamp();
this.unseenMemoryTicks = 300;
if (this.alertSameType) {
this.alertOthers();
}
super.c();
super.start();
}
protected void g() {
double d0 = this.k();
AxisAlignedBB axisalignedbb = AxisAlignedBB.a(this.e.getPositionVector()).grow(d0, 10.0D, d0);
List<? extends EntityInsentient> list = this.e.getWorld().a(this.e.getClass(), axisalignedbb, IEntitySelector.f);
protected void alertOthers() {
double d0 = this.getFollowDistance();
AABB axisalignedbb = AABB.unitCubeFromLowerCorner(this.mob.position()).inflate(d0, 10.0D, d0);
List<? extends Mob> list = this.mob.level.getEntitiesOfClass(this.mob.getClass(), axisalignedbb, EntitySelector.NO_SPECTATORS);
Iterator iterator = list.iterator();
while(true) {
EntityInsentient entityinsentient;
Mob entityinsentient;
boolean flag;
do {
do {
@ -88,18 +88,18 @@ public class FoxPathfinderGoalHurtByTarget extends PathfinderGoalTarget {
return;
}
entityinsentient = (EntityInsentient)iterator.next();
} while(this.e == entityinsentient);
} while(entityinsentient.getGoalTarget() != null);
} while(this.e instanceof EntityTamableFox && ((EntityTamableFox)this.e).getOwner() != ((EntityTamableFox)entityinsentient).getOwner());
} while(entityinsentient.r(this.e.getLastDamager()));
entityinsentient = (Mob)iterator.next();
} while(this.mob == entityinsentient);
} while(entityinsentient.getTarget() != null);
} while(this.mob instanceof EntityTamableFox && ((EntityTamableFox)this.mob).getOwner() != ((EntityTamableFox)entityinsentient).getOwner());
} while(entityinsentient.isAlliedTo(this.mob.getLastHurtByMob()));
if (this.i == null) {
if (this.toIgnoreAlert == null) {
break;
}
flag = false;
Class[] aclass = this.i;
Class[] aclass = this.toIgnoreAlert;
int i = aclass.length;
for(int j = 0; j < i; ++j) {
@ -111,11 +111,11 @@ public class FoxPathfinderGoalHurtByTarget extends PathfinderGoalTarget {
}
} while(flag);
this.a(entityinsentient, this.e.getLastDamager());
this.alertOther(entityinsentient, this.mob.getLastHurtByMob());
}
}
protected void a(EntityInsentient entityinsentient, EntityLiving entityliving) {
protected void alertOther(Mob entityinsentient, LivingEntity entityliving) {
entityinsentient.setGoalTarget(entityliving, TargetReason.TARGET_ATTACKED_NEARBY_ENTITY, true);
}
}

View File

@ -1,46 +1,47 @@
package net.seanomik.tamablefoxes.versions.version_1_17_R1.pathfinding;
import net.minecraft.world.entity.EntityLiving;
import net.minecraft.world.entity.ai.goal.target.PathfinderGoalTarget;
import net.minecraft.world.entity.ai.targeting.PathfinderTargetCondition;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.ai.goal.Goal;
import net.minecraft.world.entity.ai.goal.target.TargetGoal;
import net.minecraft.world.entity.ai.targeting.TargetingConditions;
import net.seanomik.tamablefoxes.versions.version_1_17_R1.EntityTamableFox;
import org.bukkit.event.entity.EntityTargetEvent.TargetReason;
import java.util.EnumSet;
public class FoxPathfinderGoalOwnerHurtByTarget extends PathfinderGoalTarget {
private final EntityTamableFox a;
private EntityLiving b;
private int c;
public class FoxPathfinderGoalOwnerHurtByTarget extends TargetGoal {
private final EntityTamableFox tameAnimal;
private LivingEntity ownerLastHurtBy;
private int timestamp;
public FoxPathfinderGoalOwnerHurtByTarget(EntityTamableFox tamableFox) {
super(tamableFox, false);
this.a = tamableFox;
this.a(EnumSet.of(Type.d));
public FoxPathfinderGoalOwnerHurtByTarget(EntityTamableFox entitytameableanimal) {
super(entitytameableanimal, false);
this.tameAnimal = entitytameableanimal;
this.setFlags(EnumSet.of(Goal.Flag.TARGET));
}
public boolean a() {
if (this.a.isTamed() && !this.a.isSitting()) { //!this.a.isWillSit
EntityLiving entityliving = this.a.getOwner();
public boolean canUse() {
if (this.tameAnimal.isTamed() && !this.tameAnimal.isOrderedToSit() && !this.tameAnimal.isOrderedToSleep()) {
LivingEntity entityliving = this.tameAnimal.getOwner();
if (entityliving == null) {
return false;
} else {
this.b = entityliving.getLastDamager();
int i = entityliving.dH();
return i != this.c && this.a(this.b, PathfinderTargetCondition.a) && this.a.wantsToAttack(this.b, entityliving);
this.ownerLastHurtBy = entityliving.getLastHurtByMob();
int i = entityliving.getLastHurtByMobTimestamp();
return i != this.timestamp && this.canAttack(this.ownerLastHurtBy, TargetingConditions.DEFAULT) && this.tameAnimal.wantsToAttack(this.ownerLastHurtBy, entityliving);
}
} else {
return false;
}
}
public void c() {
this.e.setGoalTarget(this.b, TargetReason.TARGET_ATTACKED_OWNER, true);
EntityLiving entityliving = this.a.getOwner();
public void start() {
this.mob.setGoalTarget(this.ownerLastHurtBy, TargetReason.TARGET_ATTACKED_OWNER, true);
LivingEntity entityliving = this.tameAnimal.getOwner();
if (entityliving != null) {
this.c = entityliving.dH();
this.timestamp = entityliving.getLastHurtByMobTimestamp();
}
super.c();
super.start();
}
}

View File

@ -1,46 +1,47 @@
package net.seanomik.tamablefoxes.versions.version_1_17_R1.pathfinding;
import net.minecraft.world.entity.EntityLiving;
import net.minecraft.world.entity.ai.goal.target.PathfinderGoalTarget;
import net.minecraft.world.entity.ai.targeting.PathfinderTargetCondition;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.ai.goal.Goal;
import net.minecraft.world.entity.ai.goal.target.TargetGoal;
import net.minecraft.world.entity.ai.targeting.TargetingConditions;
import net.seanomik.tamablefoxes.versions.version_1_17_R1.EntityTamableFox;
import org.bukkit.event.entity.EntityTargetEvent.TargetReason;
import java.util.EnumSet;
public class FoxPathfinderGoalOwnerHurtTarget extends PathfinderGoalTarget {
private final EntityTamableFox a;
private EntityLiving b;
private int c;
public class FoxPathfinderGoalOwnerHurtTarget extends TargetGoal {
private final EntityTamableFox tameAnimal;
private LivingEntity ownerLastHurt;
private int timestamp;
public FoxPathfinderGoalOwnerHurtTarget(EntityTamableFox tamableFox) {
super(tamableFox, false);
this.a = tamableFox;
this.a(EnumSet.of(Type.d));
public FoxPathfinderGoalOwnerHurtTarget(EntityTamableFox entitytameableanimal) {
super(entitytameableanimal, false);
this.tameAnimal = entitytameableanimal;
this.setFlags(EnumSet.of(Goal.Flag.TARGET));
}
public boolean a() {
if (this.a.isTamed() && !this.a.isSitting()) { // !this.a.isWillSit()
EntityLiving entityliving = this.a.getOwner();
public boolean canUse() {
if (this.tameAnimal.isTamed() && !this.tameAnimal.isOrderedToSit() && !this.tameAnimal.isOrderedToSleep()) {
LivingEntity entityliving = this.tameAnimal.getOwner();
if (entityliving == null) {
return false;
} else {
this.b = entityliving.dI();
int i = entityliving.dJ();
return i != this.c && this.a(this.b, PathfinderTargetCondition.a) && this.a.wantsToAttack(this.b, entityliving);
this.ownerLastHurt = entityliving.getLastHurtMob();
int i = entityliving.getLastHurtMobTimestamp();
return i != this.timestamp && this.canAttack(this.ownerLastHurt, TargetingConditions.DEFAULT) && this.tameAnimal.wantsToAttack(this.ownerLastHurt, entityliving);
}
} else {
return false;
}
}
public void c() {
this.e.setGoalTarget(this.b, TargetReason.OWNER_ATTACKED_TARGET, true);
EntityLiving entityliving = this.a.getOwner();
public void start() {
this.mob.setGoalTarget(this.ownerLastHurt, TargetReason.OWNER_ATTACKED_TARGET, true);
LivingEntity entityliving = this.tameAnimal.getOwner();
if (entityliving != null) {
this.c = entityliving.dJ();
this.timestamp = entityliving.getLastHurtMobTimestamp();
}
super.c();
super.start();
}
}

View File

@ -1,17 +0,0 @@
package net.seanomik.tamablefoxes.versions.version_1_17_R1.pathfinding;
import net.minecraft.world.entity.ai.goal.PathfinderGoalPanic;
import net.seanomik.tamablefoxes.versions.version_1_17_R1.EntityTamableFox;
public class FoxPathfinderGoalPanic extends PathfinderGoalPanic {
EntityTamableFox tamableFox;
public FoxPathfinderGoalPanic(EntityTamableFox tamableFox, double d0) {
super(tamableFox, d0);
this.tamableFox = tamableFox;
}
public boolean a() {
return !tamableFox.isDefending() && super.a();
}
}

View File

@ -1,59 +0,0 @@
package net.seanomik.tamablefoxes.versions.version_1_17_R1.pathfinding;
import net.minecraft.world.entity.EntityLiving;
import net.minecraft.world.entity.ai.goal.PathfinderGoal;
import net.minecraft.world.level.block.Blocks;
import net.seanomik.tamablefoxes.util.Utils;
import net.seanomik.tamablefoxes.versions.version_1_17_R1.EntityTamableFox;
import org.bukkit.Bukkit;
import java.util.EnumSet;
public class FoxPathfinderGoalSit extends PathfinderGoal {
private final EntityTamableFox entity;
private boolean willSit;
public FoxPathfinderGoalSit(EntityTamableFox tamableFox) {
this.entity = tamableFox;
this.a(EnumSet.of(Type.c, Type.a)); // c = JUMP; a = MOVE
}
public boolean b() {
return this.willSit;
}
private boolean isInBubbleColumn() {
return this.entity.getWorld().getType(this.entity.getChunkCoordinates()).a(Blocks.lq);
}
public boolean a() {
if (!this.entity.isTamed()) {
return this.willSit && this.entity.getGoalTarget() == null;
} else if (this.entity.aO()) {
return false;
} else if (!this.entity.isOnGround()) {
return false;
} else {
EntityLiving entityliving = this.entity.getOwner();
return entityliving == null || ((!(this.entity.f(entityliving) < 144.0D) || entityliving.getLastDamager() == null) && this.willSit);
}
}
public void c() {
// For some reason it needs to be ran later to not have the fox slide across the floor.
Bukkit.getScheduler().runTaskLater(Utils.tamableFoxesPlugin, () -> {
this.entity.setSitting(true);
this.entity.getNavigation().o();
}, 1L);
}
public void d() {
this.entity.setSitting(false);
}
public boolean isWillSit() { return this.willSit; }
public void setSitting(boolean flag) {
this.willSit = flag;
}
}

View File

@ -0,0 +1,56 @@
package net.seanomik.tamablefoxes.versions.version_1_17_R1.pathfinding;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.ai.goal.Goal;
import net.seanomik.tamablefoxes.util.Utils;
import net.seanomik.tamablefoxes.versions.version_1_17_R1.EntityTamableFox;
import org.bukkit.Bukkit;
import java.util.EnumSet;
public class FoxPathfinderGoalSitWhenOrdered extends Goal {
private final EntityTamableFox mob;
private boolean orderedToSit;
public FoxPathfinderGoalSitWhenOrdered(EntityTamableFox entitytameableanimal) {
this.mob = entitytameableanimal;
this.setFlags(EnumSet.of(Goal.Flag.JUMP, Goal.Flag.MOVE));
}
public boolean canContinueToUse() {
return this.orderedToSit;
}
public boolean canUse() {
if (!this.mob.isTamed()) {
return this.orderedToSit && this.mob.getTarget() == null;
} else if (this.mob.isInWaterOrBubble()) {
return false;
} else if (!this.mob.isOnGround()) {
return false;
} else {
LivingEntity entityliving = this.mob.getOwner();
return entityliving == null || ((!(this.mob.distanceToSqr(entityliving) < 144.0D) || entityliving.getLastHurtByMob() == null) && this.mob.isOrderedToSit());
}
}
public void start() {
// For some reason it needs to be ran later to not have the fox slide across the floor.
Bukkit.getScheduler().runTaskLater(Utils.tamableFoxesPlugin, () -> {
this.mob.getNavigation().stop();
this.mob.setSitting(true);
this.orderedToSit = true;
}, 1L);
}
public void stop() {
this.mob.setSitting(false);
this.orderedToSit = false;
}
public boolean isOrderedToSit() { return this.orderedToSit; }
public void setOrderedToSit(boolean flag) {
this.orderedToSit = flag;
}
}

View File

@ -0,0 +1,51 @@
package net.seanomik.tamablefoxes.versions.version_1_17_R1.pathfinding;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.ai.goal.Goal;
import net.seanomik.tamablefoxes.versions.version_1_17_R1.EntityTamableFox;
import java.util.EnumSet;
public class FoxPathfinderGoalSleepWhenOrdered extends Goal {
private final EntityTamableFox mob;
private boolean orderedToSleep;
public FoxPathfinderGoalSleepWhenOrdered(EntityTamableFox entitytameableanimal) {
this.mob = entitytameableanimal;
this.setFlags(EnumSet.of(Flag.JUMP, Flag.MOVE));
}
public boolean canContinueToUse() {
return this.orderedToSleep;
}
public boolean canUse() {
if (!this.mob.isTamed()) {
return this.orderedToSleep && this.mob.getTarget() == null;
} else if (this.mob.isInWaterOrBubble()) {
return false;
} else if (!this.mob.isOnGround()) {
return false;
} else {
LivingEntity entityliving = this.mob.getOwner();
return entityliving == null || ((!(this.mob.distanceToSqr(entityliving) < 144.0D) || entityliving.getLastHurtByMob() == null) && this.mob.isOrderedToSleep());
}
}
public void start() {
this.mob.getNavigation().stop();
this.mob.setSleeping(true);
this.orderedToSleep = true;
}
public void stop() {
this.mob.setSleeping(false);
this.orderedToSleep = false;
}
public boolean isOrderedToSleep() { return this.orderedToSleep; }
public void setOrderedToSleep(boolean flag) {
this.orderedToSleep = flag;
}
}

View File

@ -1,21 +1,22 @@
package net.seanomik.tamablefoxes.versions.version_1_17_R1.pathfinding;
import net.minecraft.core.BlockPosition;
import net.minecraft.server.level.WorldServer;
import net.minecraft.tags.TagsBlock;
import net.minecraft.util.MathHelper;
import net.minecraft.world.entity.EntityLiving;
import net.minecraft.world.entity.ai.goal.PathfinderGoal;
import net.minecraft.world.entity.item.EntityItem;
import net.minecraft.world.entity.player.EntityHuman;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.tags.BlockTags;
import net.minecraft.util.Mth;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.ai.goal.Goal;
import net.minecraft.world.entity.animal.Cat;
import net.minecraft.world.entity.item.ItemEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.block.BlockBed;
import net.minecraft.world.level.block.state.IBlockData;
import net.minecraft.world.level.block.BedBlock;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.storage.loot.BuiltInLootTables;
import net.minecraft.world.level.storage.loot.LootTable;
import net.minecraft.world.level.storage.loot.LootTables;
import net.minecraft.world.level.storage.loot.parameters.LootContextParameterSets;
import net.minecraft.world.level.storage.loot.parameters.LootContextParameters;
import net.minecraft.world.phys.AxisAlignedBB;
import net.minecraft.world.level.storage.loot.parameters.LootContextParamSets;
import net.minecraft.world.level.storage.loot.parameters.LootContextParams;
import net.minecraft.world.phys.AABB;
import net.seanomik.tamablefoxes.versions.version_1_17_R1.EntityTamableFox;
import org.bukkit.event.entity.EntityDropItemEvent;
@ -24,130 +25,127 @@ import java.util.List;
import java.util.Random;
// From class EntityCat#b
public class FoxPathfinderGoalSleepWithOwner extends PathfinderGoal {
private final EntityTamableFox a;
private EntityHuman b;
private BlockPosition c;
private int d;
public class FoxPathfinderGoalSleepWithOwner extends Goal {
private final EntityTamableFox fox;
private Player ownerPlayer;
private BlockPos goalPos;
private int onBedTicks;
public FoxPathfinderGoalSleepWithOwner(EntityTamableFox entitycat) {
this.a = entitycat;
public FoxPathfinderGoalSleepWithOwner(EntityTamableFox entityTamableFox) {
this.fox = entityTamableFox;
}
public boolean a() {
if (!this.a.isTamed()) {
public boolean canUse() {
if (!this.fox.isTamed()) {
return false;
} else if (this.a.isSitting()) {
} else if (this.fox.isOrderedToSleep()) {
return false;
} else {
EntityLiving entityliving = this.a.getOwner();
if (entityliving instanceof EntityHuman) {
this.b = (EntityHuman) entityliving;
LivingEntity entityliving = this.fox.getOwner();
if (entityliving instanceof Player) {
this.ownerPlayer = (Player)entityliving;
if (!entityliving.isSleeping()) {
return false;
}
if (this.a.f(this.b) > 100.0D) {
if (this.fox.distanceToSqr(this.ownerPlayer) > 100.0D) {
return false;
}
BlockPosition blockposition = this.b.getChunkCoordinates();
IBlockData iblockdata = this.a.getWorld().getType(blockposition);
if (iblockdata.a(TagsBlock.L)) {
this.c = (BlockPosition) iblockdata.d(BlockBed.aE).map((enumdirection) -> {
return blockposition.shift(enumdirection.opposite());
BlockPos blockposition = this.ownerPlayer.blockPosition();
BlockState iblockdata = this.fox.level.getBlockState(blockposition);
if (iblockdata.is(BlockTags.BEDS)) {
this.goalPos = (BlockPos)iblockdata.getOptionalValue(BedBlock.FACING).map((enumdirection) -> {
return blockposition.shift(enumdirection.getOpposite());
}).orElseGet(() -> {
return new BlockPosition(blockposition);
return new BlockPos(blockposition);
});
return !this.g();
return !this.spaceIsOccupied();
}
}
}
return false;
}
}
private boolean g() {
List<EntityTamableFox> list = this.a.getWorld().a(EntityTamableFox.class, (new AxisAlignedBB(this.c)).g(2.0D));
private boolean spaceIsOccupied() {
List<EntityTamableFox> list = this.fox.level.getEntitiesOfClass(EntityTamableFox.class, (new AABB(this.goalPos)).inflate(2.0D));
Iterator iterator = list.iterator();
EntityTamableFox entitycat;
EntityTamableFox entityTamableFox;
do {
do {
if (!iterator.hasNext()) {
return false;
}
entitycat = (EntityTamableFox)iterator.next();
} while(entitycat == this.a);
} while(!entitycat.isSleeping());
entityTamableFox = (EntityTamableFox)iterator.next();
} while(entityTamableFox == this.fox);
} while(!entityTamableFox.isSleeping());// && !entityTamableFox.isRelaxStateOne());
return true;
}
public boolean b() {
return this.a.isTamed() && this.b != null && this.b.isSleeping() && this.c != null && !this.g();
public boolean canContinueToUse() {
return this.fox.isTamed() && !this.fox.isOrderedToSleep() && this.ownerPlayer != null && this.ownerPlayer.isSleeping() && this.goalPos != null && !this.spaceIsOccupied();
}
public void c() {
if (this.c != null) {
this.a.setSitting(false);
this.a.getNavigation().a((double)this.c.getX(), (double)this.c.getY(), (double)this.c.getZ(), 1.100000023841858D);
public void start() {
if (this.goalPos != null) {
this.fox.setSitting(false);
this.fox.getNavigation().moveTo((double)this.goalPos.getX(), (double)this.goalPos.getY(), (double)this.goalPos.getZ(), 1.100000023841858D);
}
}
public void d() {
this.a.setSleeping(false);
float f = this.a.getWorld().f(1.0F);
if (this.b.fm() >= 100 && (double)f > 0.77D && (double)f < 0.8D && (double)this.a.getWorld().getRandom().nextFloat() < 0.7D) {
this.h();
public void stop() {
this.fox.setSleeping(false);
float f = this.fox.level.getTimeOfDay(1.0F);
if (this.ownerPlayer.getSleepTimer() >= 100 && (double)f > 0.77D && (double)f < 0.8D && (double)this.fox.level.getRandom().nextFloat() < 0.7D) {
this.giveMorningGift();
}
this.d = 0;
//this.a.y(false);
this.a.getNavigation().o();
this.onBedTicks = 0;
this.fox.getNavigation().stop();
}
private void h() {
Random random = this.a.getRandom();
BlockPosition.MutableBlockPosition blockposition_mutableblockposition = new BlockPosition.MutableBlockPosition();
blockposition_mutableblockposition.g(this.a.getChunkCoordinates());
this.a.a((double)(blockposition_mutableblockposition.getX() + random.nextInt(11) - 5), (double)(blockposition_mutableblockposition.getY() + random.nextInt(5) - 2), (double)(blockposition_mutableblockposition.getZ() + random.nextInt(11) - 5), false);
blockposition_mutableblockposition.g(this.a.getChunkCoordinates());
LootTable loottable = this.a.t.getMinecraftServer().getLootTableRegistry().getLootTable(LootTables.ak);
net.minecraft.world.level.storage.loot.LootTableInfo.Builder loottableinfo_builder = (new net.minecraft.world.level.storage.loot.LootTableInfo.Builder((WorldServer)this.a.t)).set(LootContextParameters.f, this.a.getPositionVector()).set(LootContextParameters.a, this.a).a(random);
List<ItemStack> list = loottable.populateLoot(loottableinfo_builder.build(LootContextParameterSets.g));
private void giveMorningGift() {
Random random = this.fox.getRandom();
BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos();
blockposition_mutableblockposition.set(this.fox.blockPosition());
this.fox.randomTeleport((double)(blockposition_mutableblockposition.getX() + random.nextInt(11) - 5), (double)(blockposition_mutableblockposition.getY() + random.nextInt(5) - 2), (double)(blockposition_mutableblockposition.getZ() + random.nextInt(11) - 5), false);
blockposition_mutableblockposition.set(this.fox.blockPosition());
LootTable loottable = this.fox.level.getServer().getLootTables().get(BuiltInLootTables.CAT_MORNING_GIFT);
net.minecraft.world.level.storage.loot.LootContext.Builder loottableinfo_builder = (new net.minecraft.world.level.storage.loot.LootContext.Builder((ServerLevel)this.fox.level)).withParameter(LootContextParams.ORIGIN, this.fox.position()).withParameter(LootContextParams.THIS_ENTITY, this.fox).withRandom(random);
List<ItemStack> list = loottable.getRandomItems(loottableinfo_builder.create(LootContextParamSets.GIFT));
Iterator iterator = list.iterator();
while(iterator.hasNext()) {
ItemStack itemstack = (ItemStack)iterator.next();
EntityItem entityitem = new EntityItem(this.a.t, (double)blockposition_mutableblockposition.getX() - (double) MathHelper.sin(this.a.aX * 0.017453292F), (double)blockposition_mutableblockposition.getY(), (double)blockposition_mutableblockposition.getZ() + (double)MathHelper.cos(this.a.aX * 0.017453292F), itemstack);
EntityDropItemEvent event = new EntityDropItemEvent(this.a.getBukkitEntity(), (org.bukkit.entity.Item)entityitem.getBukkitEntity());
entityitem.t.getCraftServer().getPluginManager().callEvent(event);
ItemEntity entityitem = new ItemEntity(this.fox.level, (double)blockposition_mutableblockposition.getX() - (double) Mth.sin(this.fox.yBodyRot * 0.017453292F), (double)blockposition_mutableblockposition.getY(), (double)blockposition_mutableblockposition.getZ() + (double)Mth.cos(this.fox.yBodyRot * 0.017453292F), itemstack);
EntityDropItemEvent event = new EntityDropItemEvent(this.fox.getBukkitEntity(), (org.bukkit.entity.Item)entityitem.getBukkitEntity());
entityitem.level.getCraftServer().getPluginManager().callEvent(event);
if (!event.isCancelled()) {
this.a.t.addEntity(entityitem);
}
}
}
public void e() {
if (this.b != null && this.c != null) {
this.a.setSitting(false);
this.a.getNavigation().a((double)this.c.getX(), (double)this.c.getY(), (double)this.c.getZ(), 1.100000023841858D);
if (this.a.f(this.b) < 2.5D) {
++this.d;
if (this.d > 16) {
this.a.setSleeping(true);
//this.a.y(false);
} else {
this.a.a(this.b, 45.0F, 45.0F);
//this.a.y(true);
}
} else {
this.a.setSleeping(false);
this.fox.level.addFreshEntity(entityitem);
}
}
}
public void tick() {
if (this.ownerPlayer != null && this.goalPos != null) {
this.fox.setSitting(false);
this.fox.getNavigation().moveTo((double)this.goalPos.getX(), (double)this.goalPos.getY(), (double)this.goalPos.getZ(), 1.100000023841858D);
if (this.fox.distanceToSqr(this.ownerPlayer) < 2.5D) {
++this.onBedTicks;
if (this.onBedTicks > 16) {
this.fox.setSleeping(true);
} else {
this.fox.lookAt(this.ownerPlayer, 45.0F, 45.0F);
}
} else {
this.fox.setSleeping(false);
}
}
}
}