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; return flag;
} else if (entityhuman.isSneaking()) { // Swap/Put/Take item from fox. } else if (entityhuman.isSneaking()) { // Swap/Put/Take item from fox.
// Ignore buckets since they can be easily duplicated. // 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()) { if (!this.getEquipment(EnumItemSlot.MAINHAND).isEmpty()) {
getBukkitEntity().getWorld().dropItem(getBukkitEntity().getLocation(), CraftItemStack.asBukkitCopy(this.getEquipment(EnumItemSlot.MAINHAND))); 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));
} // 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. // 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; return flag;
} else if (entityhuman.isSneaking()) { // Swap/Put/Take item from fox. } else if (entityhuman.isSneaking()) { // Swap/Put/Take item from fox.
// Ignore buckets since they can be easily duplicated. // 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()) { if (!this.getEquipment(EnumItemSlot.MAINHAND).isEmpty()) {
getBukkitEntity().getWorld().dropItem(getBukkitEntity().getLocation(), CraftItemStack.asBukkitCopy(this.getEquipment(EnumItemSlot.MAINHAND))); 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));
} // 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. // 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; return flag;
} else if (entityhuman.isSneaking()) { // Swap/Put/Take item from fox. } else if (entityhuman.isSneaking()) { // Swap/Put/Take item from fox.
// Ignore buckets since they can be easily duplicated. // 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; 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()) { if (!this.getEquipment(EnumItemSlot.MAINHAND).isEmpty()) {
getBukkitEntity().getWorld().dropItem(getBukkitEntity().getLocation(), CraftItemStack.asBukkitCopy(this.getEquipment(EnumItemSlot.MAINHAND))); 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));
} // 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. // 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; return flag;
} else if (entityhuman.isSneaking()) { // Swap/Put/Take item from fox. } else if (entityhuman.isSneaking()) { // Swap/Put/Take item from fox.
// Ignore buckets since they can be easily duplicated. // 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; 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()) { if (!this.getEquipment(EnumItemSlot.MAINHAND).isEmpty()) {
getBukkitEntity().getWorld().dropItem(getBukkitEntity().getLocation(), CraftItemStack.asBukkitCopy(this.getEquipment(EnumItemSlot.MAINHAND))); 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));
} // 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. // 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); 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); }, (long) 0.1);
return EnumInteractionResult.SUCCESS; return EnumInteractionResult.SUCCESS;

View File

@ -261,7 +261,7 @@ public class EntityTamableFox extends EntityFox {
return EnumInteractionResult.CONSUME; return EnumInteractionResult.CONSUME;
} }
if (isOwnedBy(entityhuman)) { if (isOwnedBy(entityhuman) && enumhand == EnumHand.MAIN_HAND) {
// This super method checks if the fox can breed or not. // This super method checks if the fox can breed or not.
EnumInteractionResult flag = super.b(entityhuman, enumhand); EnumInteractionResult flag = super.b(entityhuman, enumhand);
@ -271,16 +271,22 @@ public class EntityTamableFox extends EntityFox {
this.setSleeping(false); this.setSleeping(false);
this.goalSit.setSitting(!this.isSitting()); this.goalSit.setSitting(!this.isSitting());
return flag; 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. // 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; 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()) { if (!this.getEquipment(EnumItemSlot.MAINHAND).isEmpty()) {
getBukkitEntity().getWorld().dropItem(getBukkitEntity().getLocation(), CraftItemStack.asBukkitCopy(this.getEquipment(EnumItemSlot.MAINHAND))); 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. // 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); 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); }, (long) 0.1);
return EnumInteractionResult.SUCCESS; return EnumInteractionResult.SUCCESS;

View File

@ -10,6 +10,44 @@
<version>2.0.0-SNAPSHOT</version> <version>2.0.0-SNAPSHOT</version>
</parent> </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> <artifactId>tamablefoxes_v1_17_R1</artifactId>
<repositories> <repositories>
@ -34,6 +72,7 @@
<groupId>org.spigotmc</groupId> <groupId>org.spigotmc</groupId>
<artifactId>spigot</artifactId> <artifactId>spigot</artifactId>
<version>1.17-R0.1-SNAPSHOT</version> <version>1.17-R0.1-SNAPSHOT</version>
<classifier>remapped-mojang</classifier>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
<dependency> <dependency>

View File

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

View File

@ -1,33 +1,24 @@
package net.seanomik.tamablefoxes.versions.version_1_17_R1; package net.seanomik.tamablefoxes.versions.version_1_17_R1;
import net.minecraft.world.entity.EntityTypes; import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.animal.EntityFox; import net.minecraft.world.entity.animal.Fox;
import net.seanomik.tamablefoxes.util.FieldHelper; import net.seanomik.tamablefoxes.util.FieldHelper;
import net.seanomik.tamablefoxes.util.NMSInterface; 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.Config;
import net.seanomik.tamablefoxes.util.io.LanguageConfig; import net.seanomik.tamablefoxes.util.io.LanguageConfig;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.ChatColor; import org.bukkit.ChatColor;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity;
import org.bukkit.entity.EntityType;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class NMSInterface_1_17_R1 implements NMSInterface { public class NMSInterface_1_17_R1 implements NMSInterface {
@Override @Override
public void registerCustomFoxEntity() { public void registerCustomFoxEntity() {
try { // Replace the fox entity try { // Replace the fox entity
Field field = EntityTypes.E.getClass().getDeclaredField("bm"); Field field = EntityType.FOX.getClass().getDeclaredField("bm"); // bm = factory
FieldHelper.setField(field, EntityType.FOX, (EntityType.EntityFactory<Fox>) EntityTamableFox::new);
//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);
Bukkit.getServer().getConsoleSender().sendMessage(Config.getPrefix() + ChatColor.GREEN + LanguageConfig.getSuccessReplaced()); Bukkit.getServer().getConsoleSender().sendMessage(Config.getPrefix() + ChatColor.GREEN + LanguageConfig.getSuccessReplaced());
} catch (Exception e) { } catch (Exception e) {
Bukkit.getServer().getConsoleSender().sendMessage(Config.getPrefix() + ChatColor.RED + LanguageConfig.getFailureReplace()); Bukkit.getServer().getConsoleSender().sendMessage(Config.getPrefix() + ChatColor.RED + LanguageConfig.getFailureReplace());
@ -37,7 +28,7 @@ public class NMSInterface_1_17_R1 implements NMSInterface {
@Override @Override
public void spawnTamableFox(Location loc, FoxType type) { public void spawnTamableFox(Location loc, FoxType type) {
EntityTamableFox tamableFox = (EntityTamableFox) ((CraftEntity) loc.getWorld().spawnEntity(loc, EntityType.FOX)).getHandle(); EntityTamableFox tamableFox = (EntityTamableFox) ((CraftEntity) loc.getWorld().spawnEntity(loc, org.bukkit.entity.EntityType.FOX)).getHandle();
tamableFox.setFoxType((type == FoxType.RED) ? EntityFox.Type.a : EntityFox.Type.b); 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; package net.seanomik.tamablefoxes.versions.version_1_17_R1.pathfinding;
import net.minecraft.core.BlockPosition; import net.minecraft.core.BlockPos;
import net.minecraft.world.entity.EntityLiving; import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.ai.goal.PathfinderGoal; import net.minecraft.world.entity.ai.goal.Goal;
import net.minecraft.world.entity.ai.navigation.Navigation; import net.minecraft.world.entity.ai.navigation.FlyingPathNavigation;
import net.minecraft.world.entity.ai.navigation.NavigationAbstract; import net.minecraft.world.entity.ai.navigation.GroundPathNavigation;
import net.minecraft.world.entity.ai.navigation.NavigationFlying; import net.minecraft.world.entity.ai.navigation.PathNavigation;
import net.minecraft.world.level.IWorldReader; import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.block.BlockLeaves; import net.minecraft.world.level.block.LeavesBlock;
import net.minecraft.world.level.block.state.IBlockData; import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.pathfinder.PathType; import net.minecraft.world.level.pathfinder.BlockPathTypes;
import net.minecraft.world.level.pathfinder.PathfinderNormal; import net.minecraft.world.level.pathfinder.WalkNodeEvaluator;
import net.seanomik.tamablefoxes.versions.version_1_17_R1.EntityTamableFox; import net.seanomik.tamablefoxes.versions.version_1_17_R1.EntityTamableFox;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity;
@ -18,88 +18,91 @@ import org.bukkit.event.entity.EntityTeleportEvent;
import java.util.EnumSet; import java.util.EnumSet;
public class FoxPathfinderGoalFollowOwner extends PathfinderGoal { public class FoxPathfinderGoalFollowOwner extends Goal {
private final EntityTamableFox a; public static final int TELEPORT_WHEN_DISTANCE_IS = 12;
private EntityLiving b; private static final int MIN_HORIZONTAL_DISTANCE_FROM_PLAYER_WHEN_TELEPORTING = 2;
private final IWorldReader c; private static final int MAX_HORIZONTAL_DISTANCE_FROM_PLAYER_WHEN_TELEPORTING = 3;
private final double d; private static final int MAX_VERTICAL_DISTANCE_FROM_PLAYER_WHEN_TELEPORTING = 1;
private final NavigationAbstract e; private final EntityTamableFox tamableFox;
private int f; private LivingEntity owner;
private final float g; private final LevelReader level;
private final float h; private final double speedModifier;
private float i; private final PathNavigation navigation;
private final boolean j; 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) { public FoxPathfinderGoalFollowOwner(EntityTamableFox entityfox, double d0, float f, float f1, boolean flag) {
this.a = tamableFox; this.tamableFox = entityfox;
this.c = tamableFox.getWorld(); this.level = entityfox.level;
this.d = d0; this.speedModifier = d0;
this.e = tamableFox.getNavigation(); this.navigation = entityfox.getNavigation();
this.h = f; this.startDistance = f;
this.g = f1; this.stopDistance = f1;
this.j = flag; this.canFly = flag;
this.a(EnumSet.of(Type.a, Type.b)); // a = MOVE; b = LOOK this.setFlags(EnumSet.of(Goal.Flag.MOVE, Flag.LOOK));
if (!(tamableFox.getNavigation() instanceof Navigation) && !(tamableFox.getNavigation() instanceof NavigationFlying)) { if (!(entityfox.getNavigation() instanceof GroundPathNavigation) && !(entityfox.getNavigation() instanceof FlyingPathNavigation)) {
throw new IllegalArgumentException("Unsupported mob type for FollowOwnerGoal"); throw new IllegalArgumentException("Unsupported mob type for FoxPathfinderGoalFollowOwner");
} }
} }
public boolean a() { public boolean canUse() {
EntityLiving entityliving = this.a.getOwner(); LivingEntity entityliving = this.tamableFox.getOwner();
if (entityliving == null) { if (entityliving == null) {
return false; return false;
} else if (entityliving.isSpectator()) { } else if (entityliving.isSpectator()) {
return false; return false;
} else if (this.a.isSitting()) { // this.a.isWillSit() } else if (this.tamableFox.isOrderedToSit() || this.tamableFox.isOrderedToSleep()) {
return false; 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; return false;
} else { } else {
this.b = entityliving; this.owner = entityliving;
return true; return true;
} }
} }
public boolean b() { public boolean canContinueToUse() {
// Simplified with IntelliJ hints return !this.navigation.isDone() && (!this.tamableFox.isOrderedToSit() && !this.tamableFox.isOrderedToSleep() && this.tamableFox.distanceToSqr(this.owner) > (double) (this.stopDistance * this.stopDistance));
return !this.e.m() && (!this.a.isSitting() && this.a.f(this.f) > (double) (this.g * this.g));
} }
public void c() { public void start() {
this.f = 0; this.timeToRecalcPath = 0;
this.i = this.a.a(PathType.i); this.oldWaterCost = this.tamableFox.getPathfindingMalus(BlockPathTypes.WATER);
this.a.a(PathType.i, 0.0F); this.tamableFox.setPathfindingMalus(BlockPathTypes.WATER, 0.0F);
} }
public void d() { public void stop() {
this.b = null; this.owner = null;
this.e.o(); this.navigation.stop();
this.a.a(PathType.i, this.i); this.tamableFox.setPathfindingMalus(BlockPathTypes.WATER, this.oldWaterCost);
} }
public void e() { public void tick() {
this.a.getControllerLook().a(this.b, 10.0F, (float)this.a.eY()); this.tamableFox.getLookControl().setLookAt(this.owner, 10.0F, (float)this.tamableFox.getMaxHeadXRot());
if (--this.f <= 0) { if (--this.timeToRecalcPath <= 0) {
this.f = 10; this.timeToRecalcPath = 10;
if (!this.a.isLeashed() && !this.a.isPassenger()) { if (!this.tamableFox.isLeashed() && !this.tamableFox.isPassenger()) {
if (this.a.f(this.b) >= 144.0D) { if (this.tamableFox.distanceToSqr(this.owner) >= 144.0D) {
this.g(); this.teleportToOwner();
} else { } else {
this.e.a(this.b, this.d); this.navigation.moveTo(this.owner, this.speedModifier);
} }
} }
} }
} }
private void g() { private void teleportToOwner() {
BlockPosition blockposition = this.b.getChunkCoordinates(); BlockPos blockposition = this.owner.blockPosition();
for(int i = 0; i < 10; ++i) { for(int i = 0; i < 10; ++i) {
int j = this.a(-3, 3); int j = this.randomIntInclusive(-3, 3);
int k = this.a(-1, 1); int k = this.randomIntInclusive(-1, 1);
int l = this.a(-3, 3); int l = this.randomIntInclusive(-3, 3);
boolean flag = this.a(blockposition.getX() + j, blockposition.getY() + k, blockposition.getZ() + l); boolean flag = this.maybeTeleportTo(blockposition.getX() + j, blockposition.getY() + k, blockposition.getZ() + l);
if (flag) { if (flag) {
return; return;
} }
@ -107,43 +110,43 @@ public class FoxPathfinderGoalFollowOwner extends PathfinderGoal {
} }
private boolean a(int i, int j, int k) { private boolean maybeTeleportTo(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) { if (Math.abs((double)i - this.owner.getX()) < 2.0D && Math.abs((double)k - this.owner.getZ()) < 2.0D) {
return false; return false;
} else if (!this.a(new BlockPosition(i, j, k))) { } else if (!this.canTeleportTo(new BlockPos(i, j, k))) {
return false; return false;
} else { } else {
CraftEntity entity = this.a.getBukkitEntity(); CraftEntity entity = this.tamableFox.getBukkitEntity();
Location to = new Location(entity.getWorld(), (double)i + 0.5D, (double)j, (double)k + 0.5D, this.a.getYRot(), this.a.getXRot()); 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); 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()) { if (event.isCancelled()) {
return false; return false;
} else { } else {
to = event.getTo(); to = event.getTo();
this.a.setPositionRotation(to.getX(), to.getY(), to.getZ(), to.getYaw(), to.getPitch()); this.tamableFox.moveTo(to.getX(), to.getY(), to.getZ(), to.getYaw(), to.getPitch());
this.e.o(); this.navigation.stop();
return true; return true;
} }
} }
} }
private boolean a(BlockPosition blockposition) { private boolean canTeleportTo(BlockPos blockposition) {
PathType pathtype = PathfinderNormal.a(this.c, blockposition.i()); BlockPathTypes pathtype = WalkNodeEvaluator.getBlockPathTypeStatic(this.level, blockposition.mutable());
if (pathtype != PathType.c) { if (pathtype != BlockPathTypes.WALKABLE) {
return false; return false;
} else { } else {
IBlockData iblockdata = this.c.getType(blockposition.down()); BlockState iblockdata = this.level.getBlockState(blockposition.down());
if (!this.j && iblockdata.getBlock() instanceof BlockLeaves) { if (!this.canFly && iblockdata.getBlock() instanceof LeavesBlock) {
return false; return false;
} else { } else {
BlockPosition blockposition1 = blockposition.e(this.a.getChunkCoordinates()); BlockPos blockposition1 = blockposition.e(this.tamableFox.blockPosition());
return this.c.getCubes(this.a, this.a.getBoundingBox().a(blockposition1)); return this.level.noCollision(this.tamableFox, this.tamableFox.getBoundingBox().move(blockposition1));
} }
} }
} }
private int a(int i, int j) { private int randomIntInclusive(int i, int j) {
return this.a.getRandom().nextInt(j - i + 1) + i; 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; package net.seanomik.tamablefoxes.versions.version_1_17_R1.pathfinding;
import net.minecraft.world.entity.EntityInsentient; import net.minecraft.world.entity.*;
import net.minecraft.world.entity.EntityLiving; import net.minecraft.world.entity.ai.goal.Goal;
import net.minecraft.world.entity.EntityTypes; import net.minecraft.world.entity.ai.goal.target.HurtByTargetGoal;
import net.minecraft.world.entity.IEntitySelector; import net.minecraft.world.entity.ai.goal.target.TargetGoal;
import net.minecraft.world.entity.ai.goal.target.PathfinderGoalTarget; import net.minecraft.world.entity.ai.targeting.TargetingConditions;
import net.minecraft.world.entity.ai.targeting.PathfinderTargetCondition;
import net.minecraft.world.level.GameRules; 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 net.seanomik.tamablefoxes.versions.version_1_17_R1.EntityTamableFox;
import org.bukkit.event.entity.EntityTargetEvent.TargetReason; import org.bukkit.event.entity.EntityTargetEvent.TargetReason;
@ -15,27 +14,28 @@ import java.util.EnumSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
public class FoxPathfinderGoalHurtByTarget extends PathfinderGoalTarget { public class FoxPathfinderGoalHurtByTarget extends TargetGoal {
private static final PathfinderTargetCondition a = PathfinderTargetCondition.a().d().e(); private static final TargetingConditions HURT_BY_TARGETING = TargetingConditions.forCombat().ignoreLineOfSight().ignoreInvisibilityTesting();
private boolean b; private static final int ALERT_RANGE_Y = 10;
private int c; private boolean alertSameType;
private final Class<?>[] d; private int timestamp;
private Class<?>[] i; private final Class<?>[] toIgnoreDamage;
private Class<?>[] toIgnoreAlert;
public FoxPathfinderGoalHurtByTarget(EntityTamableFox tamableFox, Class<?>... aclass) { public FoxPathfinderGoalHurtByTarget(PathfinderMob entitycreature, Class<?>... aclass) {
super(tamableFox, true); super(entitycreature, true);
this.d = aclass; this.toIgnoreDamage = aclass;
this.a(EnumSet.of(Type.d)); this.setFlags(EnumSet.of(Flag.TARGET));
} }
public boolean a() { public boolean canUse() {
int i = this.e.dH(); int i = this.mob.getLastHurtByMobTimestamp();
EntityLiving entityliving = this.e.getLastDamager(); LivingEntity entityliving = this.mob.getLastHurtByMob();
if (i != this.c && entityliving != null) { if (i != this.timestamp && entityliving != null) {
if (entityliving.getEntityType() == EntityTypes.bi && this.e.getWorld().getGameRules().getBoolean(GameRules.I)) { if (entityliving.getType() == EntityType.PLAYER && this.mob.level.getGameRules().getBoolean(GameRules.RULE_UNIVERSAL_ANGER)) {
return false; return false;
} else { } else {
Class[] aclass = this.d; Class[] aclass = this.toIgnoreDamage;
int j = aclass.length; int j = aclass.length;
for(int k = 0; k < j; ++k) { 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 { } else {
return false; return false;
} }
} }
public FoxPathfinderGoalHurtByTarget a(Class<?>... aclass) { public FoxPathfinderGoalHurtByTarget setAlertOthers(Class<?>... aclass) {
this.b = true; this.alertSameType = true;
this.i = aclass; this.toIgnoreAlert = aclass;
return this; return this;
} }
public void c() { public void start() {
this.e.setGoalTarget(this.e.getLastDamager(), TargetReason.TARGET_ATTACKED_ENTITY, true); this.mob.setGoalTarget(this.mob.getLastHurtByMob(), TargetReason.TARGET_ATTACKED_ENTITY, true);
this.g = this.e.getGoalTarget(); this.targetMob = this.mob.getTarget();
this.c = this.e.dH(); this.timestamp = this.mob.getLastHurtByMobTimestamp();
this.h = 300; this.unseenMemoryTicks = 300;
if (this.b) { if (this.alertSameType) {
this.g(); this.alertOthers();
} }
super.c(); super.start();
} }
protected void g() { protected void alertOthers() {
double d0 = this.k(); double d0 = this.getFollowDistance();
AxisAlignedBB axisalignedbb = AxisAlignedBB.a(this.e.getPositionVector()).grow(d0, 10.0D, d0); AABB axisalignedbb = AABB.unitCubeFromLowerCorner(this.mob.position()).inflate(d0, 10.0D, d0);
List<? extends EntityInsentient> list = this.e.getWorld().a(this.e.getClass(), axisalignedbb, IEntitySelector.f); List<? extends Mob> list = this.mob.level.getEntitiesOfClass(this.mob.getClass(), axisalignedbb, EntitySelector.NO_SPECTATORS);
Iterator iterator = list.iterator(); Iterator iterator = list.iterator();
while(true) { while(true) {
EntityInsentient entityinsentient; Mob entityinsentient;
boolean flag; boolean flag;
do { do {
do { do {
@ -88,18 +88,18 @@ public class FoxPathfinderGoalHurtByTarget extends PathfinderGoalTarget {
return; return;
} }
entityinsentient = (EntityInsentient)iterator.next(); entityinsentient = (Mob)iterator.next();
} while(this.e == entityinsentient); } while(this.mob == entityinsentient);
} while(entityinsentient.getGoalTarget() != null); } while(entityinsentient.getTarget() != null);
} while(this.e instanceof EntityTamableFox && ((EntityTamableFox)this.e).getOwner() != ((EntityTamableFox)entityinsentient).getOwner()); } while(this.mob instanceof EntityTamableFox && ((EntityTamableFox)this.mob).getOwner() != ((EntityTamableFox)entityinsentient).getOwner());
} while(entityinsentient.r(this.e.getLastDamager())); } while(entityinsentient.isAlliedTo(this.mob.getLastHurtByMob()));
if (this.i == null) { if (this.toIgnoreAlert == null) {
break; break;
} }
flag = false; flag = false;
Class[] aclass = this.i; Class[] aclass = this.toIgnoreAlert;
int i = aclass.length; int i = aclass.length;
for(int j = 0; j < i; ++j) { for(int j = 0; j < i; ++j) {
@ -111,11 +111,11 @@ public class FoxPathfinderGoalHurtByTarget extends PathfinderGoalTarget {
} }
} while(flag); } 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); 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; package net.seanomik.tamablefoxes.versions.version_1_17_R1.pathfinding;
import net.minecraft.world.entity.EntityLiving; import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.ai.goal.target.PathfinderGoalTarget; import net.minecraft.world.entity.ai.goal.Goal;
import net.minecraft.world.entity.ai.targeting.PathfinderTargetCondition; 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 net.seanomik.tamablefoxes.versions.version_1_17_R1.EntityTamableFox;
import org.bukkit.event.entity.EntityTargetEvent.TargetReason; import org.bukkit.event.entity.EntityTargetEvent.TargetReason;
import java.util.EnumSet; import java.util.EnumSet;
public class FoxPathfinderGoalOwnerHurtByTarget extends PathfinderGoalTarget { public class FoxPathfinderGoalOwnerHurtByTarget extends TargetGoal {
private final EntityTamableFox a; private final EntityTamableFox tameAnimal;
private EntityLiving b; private LivingEntity ownerLastHurtBy;
private int c; private int timestamp;
public FoxPathfinderGoalOwnerHurtByTarget(EntityTamableFox tamableFox) { public FoxPathfinderGoalOwnerHurtByTarget(EntityTamableFox entitytameableanimal) {
super(tamableFox, false); super(entitytameableanimal, false);
this.a = tamableFox; this.tameAnimal = entitytameableanimal;
this.a(EnumSet.of(Type.d)); this.setFlags(EnumSet.of(Goal.Flag.TARGET));
} }
public boolean a() { public boolean canUse() {
if (this.a.isTamed() && !this.a.isSitting()) { //!this.a.isWillSit if (this.tameAnimal.isTamed() && !this.tameAnimal.isOrderedToSit() && !this.tameAnimal.isOrderedToSleep()) {
EntityLiving entityliving = this.a.getOwner(); LivingEntity entityliving = this.tameAnimal.getOwner();
if (entityliving == null) { if (entityliving == null) {
return false; return false;
} else { } else {
this.b = entityliving.getLastDamager(); this.ownerLastHurtBy = entityliving.getLastHurtByMob();
int i = entityliving.dH(); int i = entityliving.getLastHurtByMobTimestamp();
return i != this.c && this.a(this.b, PathfinderTargetCondition.a) && this.a.wantsToAttack(this.b, entityliving); return i != this.timestamp && this.canAttack(this.ownerLastHurtBy, TargetingConditions.DEFAULT) && this.tameAnimal.wantsToAttack(this.ownerLastHurtBy, entityliving);
} }
} else { } else {
return false; return false;
} }
} }
public void c() { public void start() {
this.e.setGoalTarget(this.b, TargetReason.TARGET_ATTACKED_OWNER, true); this.mob.setGoalTarget(this.ownerLastHurtBy, TargetReason.TARGET_ATTACKED_OWNER, true);
EntityLiving entityliving = this.a.getOwner(); LivingEntity entityliving = this.tameAnimal.getOwner();
if (entityliving != null) { 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; package net.seanomik.tamablefoxes.versions.version_1_17_R1.pathfinding;
import net.minecraft.world.entity.EntityLiving; import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.ai.goal.target.PathfinderGoalTarget; import net.minecraft.world.entity.ai.goal.Goal;
import net.minecraft.world.entity.ai.targeting.PathfinderTargetCondition; 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 net.seanomik.tamablefoxes.versions.version_1_17_R1.EntityTamableFox;
import org.bukkit.event.entity.EntityTargetEvent.TargetReason; import org.bukkit.event.entity.EntityTargetEvent.TargetReason;
import java.util.EnumSet; import java.util.EnumSet;
public class FoxPathfinderGoalOwnerHurtTarget extends PathfinderGoalTarget { public class FoxPathfinderGoalOwnerHurtTarget extends TargetGoal {
private final EntityTamableFox a; private final EntityTamableFox tameAnimal;
private EntityLiving b; private LivingEntity ownerLastHurt;
private int c; private int timestamp;
public FoxPathfinderGoalOwnerHurtTarget(EntityTamableFox tamableFox) { public FoxPathfinderGoalOwnerHurtTarget(EntityTamableFox entitytameableanimal) {
super(tamableFox, false); super(entitytameableanimal, false);
this.a = tamableFox; this.tameAnimal = entitytameableanimal;
this.a(EnumSet.of(Type.d)); this.setFlags(EnumSet.of(Goal.Flag.TARGET));
} }
public boolean a() { public boolean canUse() {
if (this.a.isTamed() && !this.a.isSitting()) { // !this.a.isWillSit() if (this.tameAnimal.isTamed() && !this.tameAnimal.isOrderedToSit() && !this.tameAnimal.isOrderedToSleep()) {
EntityLiving entityliving = this.a.getOwner(); LivingEntity entityliving = this.tameAnimal.getOwner();
if (entityliving == null) { if (entityliving == null) {
return false; return false;
} else { } else {
this.b = entityliving.dI(); this.ownerLastHurt = entityliving.getLastHurtMob();
int i = entityliving.dJ(); int i = entityliving.getLastHurtMobTimestamp();
return i != this.c && this.a(this.b, PathfinderTargetCondition.a) && this.a.wantsToAttack(this.b, entityliving); return i != this.timestamp && this.canAttack(this.ownerLastHurt, TargetingConditions.DEFAULT) && this.tameAnimal.wantsToAttack(this.ownerLastHurt, entityliving);
} }
} else { } else {
return false; return false;
} }
} }
public void c() { public void start() {
this.e.setGoalTarget(this.b, TargetReason.OWNER_ATTACKED_TARGET, true); this.mob.setGoalTarget(this.ownerLastHurt, TargetReason.OWNER_ATTACKED_TARGET, true);
EntityLiving entityliving = this.a.getOwner(); LivingEntity entityliving = this.tameAnimal.getOwner();
if (entityliving != null) { 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; package net.seanomik.tamablefoxes.versions.version_1_17_R1.pathfinding;
import net.minecraft.core.BlockPosition; import net.minecraft.core.BlockPos;
import net.minecraft.server.level.WorldServer; import net.minecraft.server.level.ServerLevel;
import net.minecraft.tags.TagsBlock; import net.minecraft.tags.BlockTags;
import net.minecraft.util.MathHelper; import net.minecraft.util.Mth;
import net.minecraft.world.entity.EntityLiving; import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.ai.goal.PathfinderGoal; import net.minecraft.world.entity.ai.goal.Goal;
import net.minecraft.world.entity.item.EntityItem; import net.minecraft.world.entity.animal.Cat;
import net.minecraft.world.entity.player.EntityHuman; import net.minecraft.world.entity.item.ItemEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.block.BlockBed; import net.minecraft.world.level.block.BedBlock;
import net.minecraft.world.level.block.state.IBlockData; 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.LootTable;
import net.minecraft.world.level.storage.loot.LootTables; import net.minecraft.world.level.storage.loot.parameters.LootContextParamSets;
import net.minecraft.world.level.storage.loot.parameters.LootContextParameterSets; import net.minecraft.world.level.storage.loot.parameters.LootContextParams;
import net.minecraft.world.level.storage.loot.parameters.LootContextParameters; import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.AxisAlignedBB;
import net.seanomik.tamablefoxes.versions.version_1_17_R1.EntityTamableFox; import net.seanomik.tamablefoxes.versions.version_1_17_R1.EntityTamableFox;
import org.bukkit.event.entity.EntityDropItemEvent; import org.bukkit.event.entity.EntityDropItemEvent;
@ -24,130 +25,127 @@ import java.util.List;
import java.util.Random; import java.util.Random;
// From class EntityCat#b // From class EntityCat#b
public class FoxPathfinderGoalSleepWithOwner extends PathfinderGoal { public class FoxPathfinderGoalSleepWithOwner extends Goal {
private final EntityTamableFox a; private final EntityTamableFox fox;
private EntityHuman b; private Player ownerPlayer;
private BlockPosition c; private BlockPos goalPos;
private int d; private int onBedTicks;
public FoxPathfinderGoalSleepWithOwner(EntityTamableFox entitycat) { public FoxPathfinderGoalSleepWithOwner(EntityTamableFox entityTamableFox) {
this.a = entitycat; this.fox = entityTamableFox;
} }
public boolean a() { public boolean canUse() {
if (!this.a.isTamed()) { if (!this.fox.isTamed()) {
return false; return false;
} else if (this.a.isSitting()) { } else if (this.fox.isOrderedToSleep()) {
return false; return false;
} else { } else {
EntityLiving entityliving = this.a.getOwner(); LivingEntity entityliving = this.fox.getOwner();
if (entityliving instanceof EntityHuman) { if (entityliving instanceof Player) {
this.b = (EntityHuman) entityliving; this.ownerPlayer = (Player)entityliving;
if (!entityliving.isSleeping()) { if (!entityliving.isSleeping()) {
return false; return false;
} }
if (this.a.f(this.b) > 100.0D) { if (this.fox.distanceToSqr(this.ownerPlayer) > 100.0D) {
return false; return false;
} }
BlockPosition blockposition = this.b.getChunkCoordinates(); BlockPos blockposition = this.ownerPlayer.blockPosition();
IBlockData iblockdata = this.a.getWorld().getType(blockposition); BlockState iblockdata = this.fox.level.getBlockState(blockposition);
if (iblockdata.a(TagsBlock.L)) { if (iblockdata.is(BlockTags.BEDS)) {
this.c = (BlockPosition) iblockdata.d(BlockBed.aE).map((enumdirection) -> { this.goalPos = (BlockPos)iblockdata.getOptionalValue(BedBlock.FACING).map((enumdirection) -> {
return blockposition.shift(enumdirection.opposite()); return blockposition.shift(enumdirection.getOpposite());
}).orElseGet(() -> { }).orElseGet(() -> {
return new BlockPosition(blockposition); return new BlockPos(blockposition);
}); });
return !this.g(); return !this.spaceIsOccupied();
} }
} }
return false;
} }
return false;
} }
private boolean g() { private boolean spaceIsOccupied() {
List<EntityTamableFox> list = this.a.getWorld().a(EntityTamableFox.class, (new AxisAlignedBB(this.c)).g(2.0D)); List<EntityTamableFox> list = this.fox.level.getEntitiesOfClass(EntityTamableFox.class, (new AABB(this.goalPos)).inflate(2.0D));
Iterator iterator = list.iterator(); Iterator iterator = list.iterator();
EntityTamableFox entitycat; EntityTamableFox entityTamableFox;
do { do {
do { do {
if (!iterator.hasNext()) { if (!iterator.hasNext()) {
return false; return false;
} }
entitycat = (EntityTamableFox)iterator.next(); entityTamableFox = (EntityTamableFox)iterator.next();
} while(entitycat == this.a); } while(entityTamableFox == this.fox);
} while(!entitycat.isSleeping()); } while(!entityTamableFox.isSleeping());// && !entityTamableFox.isRelaxStateOne());
return true; return true;
} }
public boolean b() { public boolean canContinueToUse() {
return this.a.isTamed() && this.b != null && this.b.isSleeping() && this.c != null && !this.g(); return this.fox.isTamed() && !this.fox.isOrderedToSleep() && this.ownerPlayer != null && this.ownerPlayer.isSleeping() && this.goalPos != null && !this.spaceIsOccupied();
} }
public void c() { public void start() {
if (this.c != null) { if (this.goalPos != null) {
this.a.setSitting(false); this.fox.setSitting(false);
this.a.getNavigation().a((double)this.c.getX(), (double)this.c.getY(), (double)this.c.getZ(), 1.100000023841858D); this.fox.getNavigation().moveTo((double)this.goalPos.getX(), (double)this.goalPos.getY(), (double)this.goalPos.getZ(), 1.100000023841858D);
} }
} }
public void d() { public void stop() {
this.a.setSleeping(false); this.fox.setSleeping(false);
float f = this.a.getWorld().f(1.0F); float f = this.fox.level.getTimeOfDay(1.0F);
if (this.b.fm() >= 100 && (double)f > 0.77D && (double)f < 0.8D && (double)this.a.getWorld().getRandom().nextFloat() < 0.7D) { if (this.ownerPlayer.getSleepTimer() >= 100 && (double)f > 0.77D && (double)f < 0.8D && (double)this.fox.level.getRandom().nextFloat() < 0.7D) {
this.h(); this.giveMorningGift();
} }
this.d = 0; this.onBedTicks = 0;
//this.a.y(false); this.fox.getNavigation().stop();
this.a.getNavigation().o();
} }
private void h() { private void giveMorningGift() {
Random random = this.a.getRandom(); Random random = this.fox.getRandom();
BlockPosition.MutableBlockPosition blockposition_mutableblockposition = new BlockPosition.MutableBlockPosition(); BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos();
blockposition_mutableblockposition.g(this.a.getChunkCoordinates()); blockposition_mutableblockposition.set(this.fox.blockPosition());
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); 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.g(this.a.getChunkCoordinates()); blockposition_mutableblockposition.set(this.fox.blockPosition());
LootTable loottable = this.a.t.getMinecraftServer().getLootTableRegistry().getLootTable(LootTables.ak); LootTable loottable = this.fox.level.getServer().getLootTables().get(BuiltInLootTables.CAT_MORNING_GIFT);
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); 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.populateLoot(loottableinfo_builder.build(LootContextParameterSets.g)); List<ItemStack> list = loottable.getRandomItems(loottableinfo_builder.create(LootContextParamSets.GIFT));
Iterator iterator = list.iterator(); Iterator iterator = list.iterator();
while(iterator.hasNext()) { while(iterator.hasNext()) {
ItemStack itemstack = (ItemStack)iterator.next(); 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); 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.a.getBukkitEntity(), (org.bukkit.entity.Item)entityitem.getBukkitEntity()); EntityDropItemEvent event = new EntityDropItemEvent(this.fox.getBukkitEntity(), (org.bukkit.entity.Item)entityitem.getBukkitEntity());
entityitem.t.getCraftServer().getPluginManager().callEvent(event); entityitem.level.getCraftServer().getPluginManager().callEvent(event);
if (!event.isCancelled()) { if (!event.isCancelled()) {
this.a.t.addEntity(entityitem); this.fox.level.addFreshEntity(entityitem);
} }
} }
} }
public void e() { public void tick() {
if (this.b != null && this.c != null) { if (this.ownerPlayer != null && this.goalPos != null) {
this.a.setSitting(false); this.fox.setSitting(false);
this.a.getNavigation().a((double)this.c.getX(), (double)this.c.getY(), (double)this.c.getZ(), 1.100000023841858D); this.fox.getNavigation().moveTo((double)this.goalPos.getX(), (double)this.goalPos.getY(), (double)this.goalPos.getZ(), 1.100000023841858D);
if (this.a.f(this.b) < 2.5D) { if (this.fox.distanceToSqr(this.ownerPlayer) < 2.5D) {
++this.d; ++this.onBedTicks;
if (this.d > 16) { if (this.onBedTicks > 16) {
this.a.setSleeping(true); this.fox.setSleeping(true);
//this.a.y(false);
} else { } else {
this.a.a(this.b, 45.0F, 45.0F); this.fox.lookAt(this.ownerPlayer, 45.0F, 45.0F);
//this.a.y(true);
} }
} else { } else {
this.a.setSleeping(false); this.fox.setSleeping(false);
} }
} }
} }
} }