diff --git a/pom.xml b/pom.xml
index 150e4ea..54557f2 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,7 +6,7 @@
net.seanomik
tamablefoxes
- 1.7.9-SNAPSHOT
+ 1.8-SNAPSHOT
jar
Tamablefoxes
@@ -45,7 +45,8 @@
- D:\Code\java\spigotPlugins\_TEST_SERVER_1.16.3_\plugins\TamableFoxes_v${project.version}.jar
+
+ D:\Code\java\spigotPlugins\_TEST_SERVER_1.16.4_\plugins\TamableFoxes_v${project.version}.jar
false
@@ -81,7 +82,7 @@
AllSpigotNMS
LATEST
system
- ${project.basedir}/spigot-14-15-16_R1-16_R2.jar
+ ${project.basedir}/spigot v14 v15 v16_R1-R2-R3.jar
org.spigotmc
@@ -92,7 +93,7 @@
com.github.WesJD.AnvilGUI
anvilgui
- master-cee0befbaf-1
+ master-5d0f592c63-1
diff --git a/spigot-14-15-16_R1-16_R2.jar b/spigot v14 v15 v16_R1-R2-R3.jar
similarity index 79%
rename from spigot-14-15-16_R1-16_R2.jar
rename to spigot v14 v15 v16_R1-R2-R3.jar
index 2c1db07..b7456d9 100644
Binary files a/spigot-14-15-16_R1-16_R2.jar and b/spigot v14 v15 v16_R1-R2-R3.jar differ
diff --git a/src/main/java/net/seanomik/tamablefoxes/TamableFoxes.java b/src/main/java/net/seanomik/tamablefoxes/TamableFoxes.java
index 1c2f9bf..9686079 100644
--- a/src/main/java/net/seanomik/tamablefoxes/TamableFoxes.java
+++ b/src/main/java/net/seanomik/tamablefoxes/TamableFoxes.java
@@ -1,13 +1,14 @@
package net.seanomik.tamablefoxes;
+import net.minecraft.server.v1_15_R1.EntityWolf;
import net.seanomik.tamablefoxes.io.Config;
-import net.seanomik.tamablefoxes.io.sqlite.SQLiteHandler;
import net.seanomik.tamablefoxes.io.sqlite.SQLiteHelper;
import net.seanomik.tamablefoxes.versions.NMSInterface;
import net.seanomik.tamablefoxes.versions.version_1_14_R1.NMSInterface_1_14_R1;
import net.seanomik.tamablefoxes.versions.version_1_15_R1.NMSInterface_1_15_R1;
import net.seanomik.tamablefoxes.versions.version_1_16_R1.NMSInterface_1_16_R1;
import net.seanomik.tamablefoxes.versions.version_1_16_R2.NMSInterface_1_16_R2;
+import net.seanomik.tamablefoxes.versions.version_1_16_R3.NMSInterface_1_16_R3;
import net.seanomik.tamablefoxes.io.LanguageConfig;
import org.bukkit.*;
import org.bukkit.event.Listener;
@@ -46,6 +47,9 @@ public final class TamableFoxes extends JavaPlugin implements Listener {
case "v1_16_R2":
nmsInterface = new NMSInterface_1_16_R2();
break;
+ case "v1_16_R3":
+ nmsInterface = new NMSInterface_1_16_R3();
+ break;
default:
Bukkit.getServer().getConsoleSender().sendMessage(Utils.getPrefix() + ChatColor.RED + LanguageConfig.getUnsupportedMCVersionRegister());
versionSupported = false;
diff --git a/src/main/java/net/seanomik/tamablefoxes/versions/version_1_14_R1/EntityTamableFox.java b/src/main/java/net/seanomik/tamablefoxes/versions/version_1_14_R1/EntityTamableFox.java
index 45411e3..b3e6635 100644
--- a/src/main/java/net/seanomik/tamablefoxes/versions/version_1_14_R1/EntityTamableFox.java
+++ b/src/main/java/net/seanomik/tamablefoxes/versions/version_1_14_R1/EntityTamableFox.java
@@ -74,7 +74,7 @@ public class EntityTamableFox extends EntityFox {
this.goalSelector.a(0, getFoxInnerPathfinderGoal("g")); // FoxFloatGoal
this.goalSelector.a(1, getFoxInnerPathfinderGoal("b")); // FaceplantGoal
this.goalSelector.a(2, new FoxPathfinderGoalPanic(this, 2.2D));
- this.goalSelector.a(2, new FoxPathfinderGoalRelaxOnOwner(this));
+ this.goalSelector.a(2, new FoxPathfinderGoalSleepWithOwner(this));
this.goalSelector.a(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) -> {
diff --git a/src/main/java/net/seanomik/tamablefoxes/versions/version_1_14_R1/pathfinding/FoxPathfinderGoalRelaxOnOwner.java b/src/main/java/net/seanomik/tamablefoxes/versions/version_1_14_R1/pathfinding/FoxPathfinderGoalRelaxOnOwner.java
deleted file mode 100644
index 9e5a2ce..0000000
--- a/src/main/java/net/seanomik/tamablefoxes/versions/version_1_14_R1/pathfinding/FoxPathfinderGoalRelaxOnOwner.java
+++ /dev/null
@@ -1,129 +0,0 @@
-package net.seanomik.tamablefoxes.versions.version_1_14_R1.pathfinding;
-
-import net.minecraft.server.v1_14_R1.*;
-import net.seanomik.tamablefoxes.versions.version_1_14_R1.EntityTamableFox;
-
-import java.util.Iterator;
-import java.util.List;
-import java.util.Random;
-
-public class FoxPathfinderGoalRelaxOnOwner extends PathfinderGoal {
- private final EntityTamableFox a;
- private EntityHuman b;
- private BlockPosition c;
- private int d;
-
- public FoxPathfinderGoalRelaxOnOwner(EntityTamableFox entityTamableFox) {
- this.a = entityTamableFox;
- }
-
- public boolean a() {
- if (!this.a.isTamed()) {
- return false;
- } else if (this.a.isSitting()) {
- return false;
- } else {
- EntityLiving entityliving = this.a.getOwner();
- if (entityliving instanceof EntityHuman) {
- this.b = (EntityHuman)entityliving;
- if (!entityliving.isSleeping()) {
- return false;
- }
-
- if (this.a.h(this.b) > 100.0D) {
- return false;
- }
-
- BlockPosition blockposition = new BlockPosition(this.b);
- IBlockData iblockdata = this.a.world.getType(blockposition);
- if (iblockdata.getBlock().a(TagsBlock.BEDS)) {
- EnumDirection enumdirection = (EnumDirection)iblockdata.get(BlockBed.FACING);
- this.c = new BlockPosition(blockposition.getX() - enumdirection.getAdjacentX(), blockposition.getY(), blockposition.getZ() - enumdirection.getAdjacentZ());
- return !this.g();
- }
- }
-
- return false;
- }
- }
-
- private boolean g() {
- List list = this.a.world.a(EntityTamableFox.class, (new AxisAlignedBB(this.c)).g(2.0D));
- Iterator iterator = list.iterator();
-
- EntityTamableFox entityTamableFox;
- do {
- do {
- if (!iterator.hasNext()) {
- return false;
- }
-
- entityTamableFox = (EntityTamableFox) iterator.next();
- } while(entityTamableFox == this.a);
- } while(!entityTamableFox.isSleeping());
-
- return true;
- }
-
- public boolean b() {
- return this.a.isTamed() && !this.a.isSitting() && this.b != null && this.b.isSleeping() && this.c != null && !this.g();
- }
-
- public void c() {
- if (this.c != null) {
- this.a.getGoalSit().setSitting(false);
- this.a.getNavigation().a((double)this.c.getX(), (double)this.c.getY(), (double)this.c.getZ(), 1.100000023841858D);
- }
-
- }
-
- public void d() {
- this.a.u(false);
- float f = this.a.world.j(1.0F);
- if (this.b.dJ() >= 100 && (double)f > 0.77D && (double)f < 0.8D && (double)this.a.world.getRandom().nextFloat() < 0.7D) {
- this.h();
- }
-
- this.d = 0;
- //this.a.v(false);
- this.a.getNavigation().o();
- }
-
- private void h() {
- Random random = this.a.getRandom();
- BlockPosition.MutableBlockPosition blockposition_mutableblockposition = new BlockPosition.MutableBlockPosition();
- blockposition_mutableblockposition.a(this.a);
- this.a.a((double)(blockposition_mutableblockposition.getX() + random.nextInt(11) - 5), (double)(blockposition_mutableblockposition.getY() + random.nextInt(5) - 2), (double)(blockposition_mutableblockposition.getZ() + random.nextInt(11) - 5), false);
- blockposition_mutableblockposition.a(this.a);
- LootTable loottable = this.a.world.getMinecraftServer().getLootTableRegistry().getLootTable(LootTables.af);
- LootTableInfo.Builder loottableinfo_builder = (new LootTableInfo.Builder((WorldServer)this.a.world)).set(LootContextParameters.POSITION, blockposition_mutableblockposition).set(LootContextParameters.THIS_ENTITY, this.a).a(random);
- List list = loottable.populateLoot(loottableinfo_builder.build(LootContextParameterSets.GIFT));
- Iterator iterator = list.iterator();
-
- while(iterator.hasNext()) {
- ItemStack itemstack = (ItemStack)iterator.next();
- this.a.world.addEntity(new EntityItem(this.a.world, (double)((float)blockposition_mutableblockposition.getX() - MathHelper.sin(this.a.aK * 0.017453292F)), (double)blockposition_mutableblockposition.getY(), (double)((float)blockposition_mutableblockposition.getZ() + MathHelper.cos(this.a.aK * 0.017453292F)), itemstack));
- }
-
- }
-
- public void e() {
- if (this.b != null && this.c != null) {
- this.a.getGoalSit().setSitting(false);
- this.a.getNavigation().a((double)this.c.getX(), (double)this.c.getY(), (double)this.c.getZ(), 1.100000023841858D);
- if (this.a.h(this.b) < 2.5D) {
- ++this.d;
- if (this.d > 16) {
- this.a.setSleeping(true);
- //this.a.v(false);
- } else {
- this.a.a(this.b, 45.0F, 45.0F);
- //this.a.v(true);
- }
- } else {
- this.a.u(false);
- }
- }
-
- }
-}
diff --git a/src/main/java/net/seanomik/tamablefoxes/versions/version_1_15_R1/EntityTamableFox.java b/src/main/java/net/seanomik/tamablefoxes/versions/version_1_15_R1/EntityTamableFox.java
index 070c1cf..2026e52 100644
--- a/src/main/java/net/seanomik/tamablefoxes/versions/version_1_15_R1/EntityTamableFox.java
+++ b/src/main/java/net/seanomik/tamablefoxes/versions/version_1_15_R1/EntityTamableFox.java
@@ -73,7 +73,7 @@ public class EntityTamableFox extends EntityFox {
this.goalSelector.a(0, getFoxInnerPathfinderGoal("g")); // FoxFloatGoal
this.goalSelector.a(1, getFoxInnerPathfinderGoal("b")); // FaceplantGoal
this.goalSelector.a(2, new FoxPathfinderGoalPanic(this, 2.2D));
- this.goalSelector.a(2, new FoxPathfinderGoalRelaxOnOwner(this));
+ this.goalSelector.a(2, new FoxPathfinderGoalSleepWithOwner(this));
this.goalSelector.a(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) -> {
diff --git a/src/main/java/net/seanomik/tamablefoxes/versions/version_1_15_R1/pathfinding/FoxPathfinderGoalRelaxOnOwner.java b/src/main/java/net/seanomik/tamablefoxes/versions/version_1_15_R1/pathfinding/FoxPathfinderGoalRelaxOnOwner.java
deleted file mode 100644
index 912666b..0000000
--- a/src/main/java/net/seanomik/tamablefoxes/versions/version_1_15_R1/pathfinding/FoxPathfinderGoalRelaxOnOwner.java
+++ /dev/null
@@ -1,130 +0,0 @@
-package net.seanomik.tamablefoxes.versions.version_1_15_R1.pathfinding;
-
-import net.minecraft.server.v1_15_R1.*;
-import net.seanomik.tamablefoxes.versions.version_1_15_R1.EntityTamableFox;
-
-import java.util.Iterator;
-import java.util.List;
-import java.util.Random;
-
-public class FoxPathfinderGoalRelaxOnOwner extends PathfinderGoal {
- private final EntityTamableFox a;
- private EntityHuman b;
- private BlockPosition c;
- private int d;
-
- public FoxPathfinderGoalRelaxOnOwner(EntityTamableFox entityTamableFox) {
- this.a = entityTamableFox;
- }
-
- public boolean a() {
- if (!this.a.isTamed()) {
- return false;
- } else if (this.a.isSitting()) {
- return false;
- } else {
- EntityLiving entityliving = this.a.getOwner();
- if (entityliving instanceof EntityHuman) {
- this.b = (EntityHuman)entityliving;
- if (!entityliving.isSleeping()) {
- return false;
- }
-
- if (this.a.h(this.b) > 100.0D) {
- return false;
- }
-
- BlockPosition blockposition = new BlockPosition(this.b);
- IBlockData iblockdata = this.a.world.getType(blockposition);
- if (iblockdata.getBlock().a(TagsBlock.BEDS)) {
- EnumDirection enumdirection = (EnumDirection)iblockdata.get(BlockBed.FACING);
- this.c = new BlockPosition(blockposition.getX() - enumdirection.getAdjacentX(), blockposition.getY(), blockposition.getZ() - enumdirection.getAdjacentZ());
- return !this.g();
- }
- }
-
- return false;
- }
- }
-
- private boolean g() {
- List list = this.a.world.a(EntityTamableFox.class, (new AxisAlignedBB(this.c)).g(2.0D));
- Iterator iterator = list.iterator();
-
- EntityTamableFox entityTamableFox;
- do {
- do {
- if (!iterator.hasNext()) {
-
- return false;
- }
-
- entityTamableFox = (EntityTamableFox) iterator.next();
- } while(entityTamableFox == this.a);
- } while(!entityTamableFox.isSleeping());
-
- return true;
- }
-
- public boolean b() {
- return this.a.isTamed() && !this.a.isSitting() && this.b != null && this.b.isSleeping() && this.c != null && !this.g();
- }
-
- public void c() {
- if (this.c != null) {
- this.a.setSitting(false);
- this.a.getNavigation().a((double)this.c.getX(), (double)this.c.getY(), (double)this.c.getZ(), 1.100000023841858D);
- }
-
- }
-
- public void d() {
- this.a.u(false);
- float f = this.a.world.f(1.0F);
- if (this.b.ef() >= 100 && (double)f > 0.77D && (double)f < 0.8D && (double)this.a.world.getRandom().nextFloat() < 0.7D) {
- this.h();
- }
-
- this.d = 0;
- //this.a.v(false);
- this.a.getNavigation().o();
- }
-
- private void h() {
- Random random = this.a.getRandom();
- BlockPosition.MutableBlockPosition blockposition_mutableblockposition = new BlockPosition.MutableBlockPosition();
- blockposition_mutableblockposition.a(this.a);
- this.a.a((double)(blockposition_mutableblockposition.getX() + random.nextInt(11) - 5), (double)(blockposition_mutableblockposition.getY() + random.nextInt(5) - 2), (double)(blockposition_mutableblockposition.getZ() + random.nextInt(11) - 5), false);
- blockposition_mutableblockposition.a(this.a);
- LootTable loottable = this.a.world.getMinecraftServer().getLootTableRegistry().getLootTable(LootTables.af);
- LootTableInfo.Builder loottableinfo_builder = (new LootTableInfo.Builder((WorldServer)this.a.world)).set(LootContextParameters.POSITION, blockposition_mutableblockposition).set(LootContextParameters.THIS_ENTITY, this.a).a(random);
- List list = loottable.populateLoot(loottableinfo_builder.build(LootContextParameterSets.GIFT));
- Iterator iterator = list.iterator();
-
- while(iterator.hasNext()) {
- ItemStack itemstack = (ItemStack)iterator.next();
- this.a.world.addEntity(new EntityItem(this.a.world, (double)((float)blockposition_mutableblockposition.getX() - MathHelper.sin(this.a.aI * 0.017453292F)), (double)blockposition_mutableblockposition.getY(), (double)((float)blockposition_mutableblockposition.getZ() + MathHelper.cos(this.a.aI * 0.017453292F)), itemstack));
- }
-
- }
-
- public void e() {
- if (this.b != null && this.c != null) {
- this.a.setSitting(false);
- this.a.getNavigation().a((double)this.c.getX(), (double)this.c.getY(), (double)this.c.getZ(), 1.100000023841858D);
- if (this.a.h(this.b) < 2.5D) {
- ++this.d;
- if (this.d > 16) {
- this.a.u(true);
- //this.a.v(false);
- } else {
- this.a.a(this.b, 45.0F, 45.0F);
- //this.a.v(true);
- }
- } else {
- this.a.u(false);
- }
- }
-
- }
-}
diff --git a/src/main/java/net/seanomik/tamablefoxes/versions/version_1_16_R1/EntityTamableFox.java b/src/main/java/net/seanomik/tamablefoxes/versions/version_1_16_R1/EntityTamableFox.java
index b9dd8aa..64107ca 100644
--- a/src/main/java/net/seanomik/tamablefoxes/versions/version_1_16_R1/EntityTamableFox.java
+++ b/src/main/java/net/seanomik/tamablefoxes/versions/version_1_16_R1/EntityTamableFox.java
@@ -81,7 +81,7 @@ public class EntityTamableFox extends EntityFox {
this.goalSelector.a(0, getFoxInnerPathfinderGoal("g")); // FoxFloatGoal
this.goalSelector.a(1, getFoxInnerPathfinderGoal("b")); // FaceplantGoal
this.goalSelector.a(2, new FoxPathfinderGoalPanic(this, 2.2D));
- this.goalSelector.a(2, new FoxPathfinderGoalRelaxOnOwner(this));
+ this.goalSelector.a(2, new FoxPathfinderGoalSleepWithOwner(this));
this.goalSelector.a(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) -> {
diff --git a/src/main/java/net/seanomik/tamablefoxes/versions/version_1_16_R1/pathfinding/FoxPathfinderGoalHurtByTarget.java b/src/main/java/net/seanomik/tamablefoxes/versions/version_1_16_R1/pathfinding/FoxPathfinderGoalHurtByTarget.java
index 0caa474..699c6c9 100644
--- a/src/main/java/net/seanomik/tamablefoxes/versions/version_1_16_R1/pathfinding/FoxPathfinderGoalHurtByTarget.java
+++ b/src/main/java/net/seanomik/tamablefoxes/versions/version_1_16_R1/pathfinding/FoxPathfinderGoalHurtByTarget.java
@@ -84,7 +84,7 @@ public class FoxPathfinderGoalHurtByTarget extends PathfinderGoalTarget {
entityinsentient = (EntityInsentient)iterator.next();
} while(this.e == entityinsentient);
} while(entityinsentient.getGoalTarget() != null);
- } while(this.e instanceof EntityTameableAnimal && ((EntityTameableAnimal)this.e).getOwner() != ((EntityTameableAnimal)entityinsentient).getOwner());
+ } while(this.e instanceof EntityTamableFox && ((EntityTamableFox)this.e).getOwner() != ((EntityTamableFox)entityinsentient).getOwner());
} while(entityinsentient.r(this.e.getLastDamager()));
if (this.i == null) {
diff --git a/src/main/java/net/seanomik/tamablefoxes/versions/version_1_16_R1/pathfinding/FoxPathfinderGoalRelaxOnOwner.java b/src/main/java/net/seanomik/tamablefoxes/versions/version_1_16_R1/pathfinding/FoxPathfinderGoalRelaxOnOwner.java
deleted file mode 100644
index 04d6a71..0000000
--- a/src/main/java/net/seanomik/tamablefoxes/versions/version_1_16_R1/pathfinding/FoxPathfinderGoalRelaxOnOwner.java
+++ /dev/null
@@ -1,129 +0,0 @@
-package net.seanomik.tamablefoxes.versions.version_1_16_R1.pathfinding;
-
-import net.minecraft.server.v1_16_R1.*;
-import net.seanomik.tamablefoxes.versions.version_1_16_R1.EntityTamableFox;
-
-import java.util.Iterator;
-import java.util.List;
-import java.util.Random;
-
-public class FoxPathfinderGoalRelaxOnOwner extends PathfinderGoal {
- private final EntityTamableFox a;
- private EntityHuman b;
- private BlockPosition c;
- private int d;
-
- public FoxPathfinderGoalRelaxOnOwner(EntityTamableFox entityTamableFox) {
- this.a = entityTamableFox;
- }
-
- public boolean a() {
- if (this.a.isTamed()) {
- EntityLiving entityliving = this.a.getOwner();
- if (entityliving instanceof EntityHuman) {
- this.b = (EntityHuman) entityliving;
- if (!entityliving.isSleeping()) {
- return false;
- }
-
- if (this.a.h(this.b) > 100.0D) {
- return false;
- }
-
- BlockPosition blockposition = this.b.getChunkCoordinates();
- IBlockData iblockdata = this.a.world.getType(blockposition);
- if (iblockdata.getBlock().a(TagsBlock.BEDS)) {
- this.c = (BlockPosition) iblockdata.d(BlockBed.FACING).map((enumdirection) -> {
- return blockposition.shift(enumdirection.opposite());
- }).orElseGet(() -> {
- return new BlockPosition(blockposition);
- });
- return !this.g();
- }
- }
-
- }
-
- return false;
- }
-
- private boolean g() {
- List list = this.a.world.a(EntityTamableFox.class, (new AxisAlignedBB(this.c)).g(2.0D));
- Iterator iterator = list.iterator();
-
- EntityTamableFox entityTamableFox;
- do {
- do {
- if (!iterator.hasNext()) {
- return false;
- }
-
- entityTamableFox = (EntityTamableFox) iterator.next();
- } while(entityTamableFox == this.a);
- } while(!entityTamableFox.isSleeping());
-
- return true;
- }
-
- public boolean b() {
- return this.a.isTamed() && this.b != null && this.b.isSleeping() && this.c != null && !this.g();
- }
-
- public void c() {
- if (this.c != null) {
- this.a.setSitting(false);
- this.a.getNavigation().a((double)this.c.getX(), (double)this.c.getY(), (double)this.c.getZ(), 1.100000023841858D);
- }
-
- }
-
- public void d() {
- this.a.setSleeping(false);
- float f = this.a.world.f(1.0F);
- if (this.b.eB() >= 100 && (double)f > 0.77D && (double)f < 0.8D && (double)this.a.world.getRandom().nextFloat() < 0.7D) {
- this.h();
- }
-
- this.d = 0;
- //this.a.y(false);
- this.a.getNavigation().o();
- }
-
- private void h() {
- Random random = this.a.getRandom();
- BlockPosition.MutableBlockPosition blockposition_mutableblockposition = new BlockPosition.MutableBlockPosition();
- blockposition_mutableblockposition.g(this.a.getChunkCoordinates());
- this.a.a((double)(blockposition_mutableblockposition.getX() + random.nextInt(11) - 5), (double)(blockposition_mutableblockposition.getY() + random.nextInt(5) - 2), (double)(blockposition_mutableblockposition.getZ() + random.nextInt(11) - 5), false);
- blockposition_mutableblockposition.g(this.a.getChunkCoordinates());
- LootTable loottable = this.a.world.getMinecraftServer().getLootTableRegistry().getLootTable(LootTables.ak);
- net.minecraft.server.v1_16_R1.LootTableInfo.Builder loottableinfo_builder = (new net.minecraft.server.v1_16_R1.LootTableInfo.Builder((WorldServer)this.a.world)).set(LootContextParameters.POSITION, blockposition_mutableblockposition).set(LootContextParameters.THIS_ENTITY, this.a).a(random);
- List list = loottable.populateLoot(loottableinfo_builder.build(LootContextParameterSets.GIFT));
- Iterator iterator = list.iterator();
-
- while(iterator.hasNext()) {
- ItemStack itemstack = (ItemStack)iterator.next();
- this.a.world.addEntity(new EntityItem(this.a.world, (double)blockposition_mutableblockposition.getX() - (double)MathHelper.sin(this.a.aH * 0.017453292F), (double)blockposition_mutableblockposition.getY(), (double)blockposition_mutableblockposition.getZ() + (double)MathHelper.cos(this.a.aH * 0.017453292F), itemstack));
- }
-
- }
-
- public void e() {
- if (this.b != null && this.c != null) {
- this.a.setSitting(false);
- this.a.getNavigation().a((double)this.c.getX(), (double)this.c.getY(), (double)this.c.getZ(), 1.100000023841858D);
- if (this.a.h(this.b) < 2.5D) {
- ++this.d;
- if (this.d > 16) {
- this.a.setSleeping(true);
- //this.a.y(false);
- } else {
- this.a.a(this.b, 45.0F, 45.0F);
- //this.a.y(true);
- }
- } else {
- this.a.setSleeping(false);
- }
- }
-
- }
-}
diff --git a/src/main/java/net/seanomik/tamablefoxes/versions/version_1_16_R1/pathfinding/FoxPathfinderGoalSleepWithOwner.java b/src/main/java/net/seanomik/tamablefoxes/versions/version_1_16_R1/pathfinding/FoxPathfinderGoalSleepWithOwner.java
index 7db4d93..6d81401 100644
--- a/src/main/java/net/seanomik/tamablefoxes/versions/version_1_16_R1/pathfinding/FoxPathfinderGoalSleepWithOwner.java
+++ b/src/main/java/net/seanomik/tamablefoxes/versions/version_1_16_R1/pathfinding/FoxPathfinderGoalSleepWithOwner.java
@@ -20,7 +20,7 @@ public class FoxPathfinderGoalSleepWithOwner extends PathfinderGoal {
public boolean a() {
if (!this.a.isTamed()) {
return false;
- } else if (this.a.isSitting()) { // this.a.isWillSit()
+ } else if (this.a.isSitting()) {
return false;
} else {
EntityLiving entityliving = this.a.getOwner();
diff --git a/src/main/java/net/seanomik/tamablefoxes/versions/version_1_16_R2/EntityTamableFox.java b/src/main/java/net/seanomik/tamablefoxes/versions/version_1_16_R2/EntityTamableFox.java
index e0305f0..03d7742 100644
--- a/src/main/java/net/seanomik/tamablefoxes/versions/version_1_16_R2/EntityTamableFox.java
+++ b/src/main/java/net/seanomik/tamablefoxes/versions/version_1_16_R2/EntityTamableFox.java
@@ -79,7 +79,7 @@ public class EntityTamableFox extends EntityFox {
this.goalSelector.a(0, getFoxInnerPathfinderGoal("g")); // FoxFloatGoal
this.goalSelector.a(1, getFoxInnerPathfinderGoal("b")); // FaceplantGoal
this.goalSelector.a(2, new FoxPathfinderGoalPanic(this, 2.2D));
- this.goalSelector.a(2, new FoxPathfinderGoalRelaxOnOwner(this));
+ this.goalSelector.a(2, new FoxPathfinderGoalSleepWithOwner(this));
this.goalSelector.a(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) -> {
diff --git a/src/main/java/net/seanomik/tamablefoxes/versions/version_1_16_R2/pathfinding/FoxPathfinderGoalHurtByTarget.java b/src/main/java/net/seanomik/tamablefoxes/versions/version_1_16_R2/pathfinding/FoxPathfinderGoalHurtByTarget.java
index cefd9a4..a8e98ba 100644
--- a/src/main/java/net/seanomik/tamablefoxes/versions/version_1_16_R2/pathfinding/FoxPathfinderGoalHurtByTarget.java
+++ b/src/main/java/net/seanomik/tamablefoxes/versions/version_1_16_R2/pathfinding/FoxPathfinderGoalHurtByTarget.java
@@ -84,7 +84,7 @@ public class FoxPathfinderGoalHurtByTarget extends PathfinderGoalTarget {
entityinsentient = (EntityInsentient)iterator.next();
} while(this.e == entityinsentient);
} while(entityinsentient.getGoalTarget() != null);
- } while(this.e instanceof EntityTameableAnimal && ((EntityTameableAnimal)this.e).getOwner() != ((EntityTameableAnimal)entityinsentient).getOwner());
+ } while(this.e instanceof EntityTamableFox && ((EntityTamableFox)this.e).getOwner() != ((EntityTamableFox)entityinsentient).getOwner());
} while(entityinsentient.r(this.e.getLastDamager()));
if (this.i == null) {
diff --git a/src/main/java/net/seanomik/tamablefoxes/versions/version_1_16_R2/pathfinding/FoxPathfinderGoalSleepWithOwner.java b/src/main/java/net/seanomik/tamablefoxes/versions/version_1_16_R2/pathfinding/FoxPathfinderGoalSleepWithOwner.java
index f3e2bb3..b7e7477 100644
--- a/src/main/java/net/seanomik/tamablefoxes/versions/version_1_16_R2/pathfinding/FoxPathfinderGoalSleepWithOwner.java
+++ b/src/main/java/net/seanomik/tamablefoxes/versions/version_1_16_R2/pathfinding/FoxPathfinderGoalSleepWithOwner.java
@@ -20,7 +20,7 @@ public class FoxPathfinderGoalSleepWithOwner extends PathfinderGoal {
public boolean a() {
if (!this.a.isTamed()) {
return false;
- } else if (this.a.isSitting()) { // this.a.isWillSit()
+ } else if (this.a.isSitting()) {
return false;
} else {
EntityLiving entityliving = this.a.getOwner();
diff --git a/src/main/java/net/seanomik/tamablefoxes/versions/version_1_16_R3/EntityTamableFox.java b/src/main/java/net/seanomik/tamablefoxes/versions/version_1_16_R3/EntityTamableFox.java
new file mode 100644
index 0000000..ca0f7c2
--- /dev/null
+++ b/src/main/java/net/seanomik/tamablefoxes/versions/version_1_16_R3/EntityTamableFox.java
@@ -0,0 +1,530 @@
+package net.seanomik.tamablefoxes.versions.version_1_16_R3;
+
+import net.minecraft.server.v1_16_R3.*;
+import net.seanomik.tamablefoxes.TamableFoxes;
+import net.seanomik.tamablefoxes.Utils;
+import net.seanomik.tamablefoxes.io.Config;
+import net.seanomik.tamablefoxes.io.LanguageConfig;
+import net.seanomik.tamablefoxes.io.sqlite.SQLiteHelper;
+import net.seanomik.tamablefoxes.versions.version_1_16_R3.pathfinding.*;
+import net.wesjd.anvilgui.AnvilGUI;
+import org.bukkit.Bukkit;
+import org.bukkit.ChatColor;
+import org.bukkit.craftbukkit.libs.jline.internal.Nullable;
+import org.bukkit.craftbukkit.v1_16_R3.event.CraftEventFactory;
+import org.bukkit.craftbukkit.v1_16_R3.inventory.CraftItemStack;
+import org.bukkit.entity.Player;
+import org.bukkit.event.entity.EntityRegainHealthEvent;
+
+import java.lang.reflect.Field;
+import java.util.*;
+import java.util.function.Predicate;
+
+public class EntityTamableFox extends EntityFox {
+
+ protected static final DataWatcherObject tamed;
+ protected static final DataWatcherObject> ownerUUID;
+
+ private static final DataWatcherObject bw; // DATA_FLAGS_ID
+ private static final Predicate bC; // AVOID_PLAYERS
+
+ static {
+ tamed = DataWatcher.a(EntityTamableFox.class, DataWatcherRegistry.a);
+ ownerUUID = DataWatcher.a(EntityTamableFox.class, DataWatcherRegistry.o);
+
+ bw = DataWatcher.a(EntityFox.class, DataWatcherRegistry.a);
+ bC = (entity) -> !entity.bw() && IEntitySelector.e.test(entity);
+ }
+
+ List untamedGoals;
+ private FoxPathfinderGoalSit goalSit;
+
+ public EntityTamableFox(EntityTypes extends EntityFox> entitytypes, World world) {
+ super(entitytypes, world);
+
+ this.getAttributeInstance(GenericAttributes.MOVEMENT_SPEED).setValue(0.33000001192092896D);
+ if (isTamed()) {
+ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(24.0D);
+ this.getAttributeInstance(GenericAttributes.ATTACK_DAMAGE).setValue(3.0D);
+ this.setHealth(this.getMaxHealth());
+ } else {
+ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(10.0D);
+ this.getAttributeInstance(GenericAttributes.ATTACK_DAMAGE).setValue(2.0D);
+ }
+ }
+
+ @Override
+ public void initPathfinder() {
+ try {
+ this.goalSit = new FoxPathfinderGoalSit(this);
+ this.goalSelector.a(1, goalSit);
+
+ // Wild animal attacking
+ Field landTargetGoal = this.getClass().getSuperclass().getDeclaredField("bw"); // landTargetGoal
+ landTargetGoal.setAccessible(true);
+ landTargetGoal.set(this, new PathfinderGoalNearestAttackableTarget(this, EntityAnimal.class, 10, false, false, (entityliving) -> {
+ return (!isTamed() || (Config.doesTamedAttackWildAnimals() && isTamed())) && (entityliving instanceof EntityChicken || entityliving instanceof EntityRabbit);
+ }));
+
+ Field turtleEggTargetGoal = this.getClass().getSuperclass().getDeclaredField("bx"); // turtleEggTargetGoal
+ turtleEggTargetGoal.setAccessible(true);
+ turtleEggTargetGoal.set(this, new PathfinderGoalNearestAttackableTarget(this, EntityTurtle.class, 10, false, false, EntityTurtle.bo));
+
+ Field fishTargetGoal = this.getClass().getSuperclass().getDeclaredField("by"); // fishTargetGoal
+ fishTargetGoal.setAccessible(true);
+ fishTargetGoal.set(this, new PathfinderGoalNearestAttackableTarget(this, EntityFish.class, 20, false, false, (entityliving) -> {
+ return (!isTamed() || (Config.doesTamedAttackWildAnimals() && isTamed())) && entityliving instanceof EntityFishSchool;
+ }));
+
+ this.goalSelector.a(0, getFoxInnerPathfinderGoal("g")); // FoxFloatGoal
+ this.goalSelector.a(1, getFoxInnerPathfinderGoal("b")); // FaceplantGoal
+ this.goalSelector.a(2, new FoxPathfinderGoalPanic(this, 2.2D));
+ this.goalSelector.a(2, new FoxPathfinderGoalSleepWithOwner(this));
+ this.goalSelector.a(3, getFoxInnerPathfinderGoal("e", Arrays.asList(1.0D), Arrays.asList(double.class))); // FoxBreedGoal
+
+ this.goalSelector.a(4, new PathfinderGoalAvoidTarget(this, EntityHuman.class, 16.0F, 1.6D, 1.4D, (entityliving) -> {
+ return !isTamed() && bC.test((EntityLiving) entityliving) && !this.isDefending();
+ }));
+ this.goalSelector.a(4, new PathfinderGoalAvoidTarget(this, EntityWolf.class, 8.0F, 1.6D, 1.4D, (entityliving) -> {
+ return !((EntityWolf)entityliving).isTamed() && !this.isDefending();
+ }));
+ this.goalSelector.a(4, new PathfinderGoalAvoidTarget(this, EntityPolarBear.class, 8.0F, 1.6D, 1.4D, (entityliving) -> {
+ return !this.isDefending();
+ }));
+
+ this.goalSelector.a(5, getFoxInnerPathfinderGoal("u")); // StalkPreyGoal
+ this.goalSelector.a(6, new o()); // FoxPounceGoal
+ this.goalSelector.a(7, getFoxInnerPathfinderGoal("l", Arrays.asList(1.2000000476837158D, true), Arrays.asList(double.class, boolean.class))); // FoxMeleeAttackGoal
+ this.goalSelector.a(8, getFoxInnerPathfinderGoal("h", Arrays.asList(this, 1.25D), Arrays.asList(EntityFox.class, double.class))); // FoxFollowParentGoal
+ this.goalSelector.a(8, new FoxPathfinderGoalSleepWithOwner(this));
+ this.goalSelector.a(9, new FoxPathfinderGoalFollowOwner(this, 1.3D, 10.0F, 2.0F, false));
+ this.goalSelector.a(10, new PathfinderGoalLeapAtTarget(this, 0.4F));
+ this.goalSelector.a(11, new PathfinderGoalRandomStrollLand(this, 1.0D));
+ this.goalSelector.a(11, getFoxInnerPathfinderGoal("p")); // FoxSearchForItemsGoal
+ this.goalSelector.a(12, getFoxInnerPathfinderGoal("j", Arrays.asList(this, EntityHuman.class, 24.0f),
+ Arrays.asList(EntityInsentient.class, Class.class, float.class))); // LookAtPlayer
+
+ this.targetSelector.a(1, new FoxPathfinderGoalOwnerHurtByTarget(this));
+ this.targetSelector.a(2, new FoxPathfinderGoalOwnerHurtTarget(this));
+ this.targetSelector.a(3, (new FoxPathfinderGoalHurtByTarget(this)).a(new Class[0]));
+
+ // Assign all the untamed goals that will later be removed.
+ untamedGoals = new ArrayList<>();
+
+ // SleepGoal
+ PathfinderGoal sleep = getFoxInnerPathfinderGoal("t");
+ this.goalSelector.a(7, sleep);
+ untamedGoals.add(sleep);
+
+ // PerchAndSearch (Random sitting?)
+ PathfinderGoal perchAndSearch = getFoxInnerPathfinderGoal("r");
+ this.goalSelector.a(13, perchAndSearch);
+ untamedGoals.add(perchAndSearch);
+
+ // FoxEatBerriesGoal (Pick berry bushes)
+ PathfinderGoal eatBerries = new f(1.2000000476837158D, 12, 2);
+ this.goalSelector.a(11, eatBerries);
+ untamedGoals.add(eatBerries); // Maybe this should be configurable too?
+
+ // SeekShelterGoal
+ PathfinderGoal seekShelter = getFoxInnerPathfinderGoal("s", Arrays.asList(1.25D), Arrays.asList(double.class));
+ this.goalSelector.a(6, seekShelter);
+ untamedGoals.add(seekShelter);
+
+ PathfinderGoal strollThroughVillage = getFoxInnerPathfinderGoal("q", Arrays.asList(32, 200), Arrays.asList(int.class, int.class));
+ this.goalSelector.a(9, strollThroughVillage); // StrollThroughVillage
+ untamedGoals.add(strollThroughVillage);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ // deobf: getFlag
+ private boolean t(int i) {
+ return ((Byte)this.datawatcher.get(bw) & i) != 0;
+ }
+
+ // deobf: 'isDefending' from 'fc'
+ public boolean isDefending() {
+ return this.t(128);
+ }
+
+ public static Object getPrivateField(String fieldName, Class clazz, Object object) {
+ Field field;
+ Object o = null;
+
+ try {
+ field = clazz.getDeclaredField(fieldName);
+ field.setAccessible(true);
+ o = field.get(object);
+ } catch (NoSuchFieldException | IllegalAccessException e) {
+ e.printStackTrace();
+ }
+
+ return o;
+ }
+
+ protected void initDatawatcher() {
+ super.initDatawatcher();
+ this.datawatcher.register(tamed, (byte) 0);
+ this.datawatcher.register(ownerUUID, Optional.empty());
+ }
+
+ @Override
+ public void saveData(NBTTagCompound compound) {
+ super.saveData(compound);
+ if (this.getOwnerUUID() == null) {
+ compound.setString("OwnerUUID", "");
+ } else {
+ compound.setString("OwnerUUID", this.getOwnerUUID().toString());
+ }
+
+ compound.setBoolean("Sitting", this.isSitting());
+ }
+
+ @Override
+ public void loadData(NBTTagCompound compound) {
+ super.loadData(compound);
+ String ownerUuid = "";
+
+ if (compound.hasKeyOfType("OwnerUUID", 8)) {
+ ownerUuid = compound.getString("OwnerUUID");
+ }/* else {
+ String var2 = compound.getString("Owner");
+ ownerUuid = NameReferencingFileConverter.a(this.getMinecraftServer(), var2);
+ }*/
+
+ if (!ownerUuid.isEmpty()) {
+ try {
+ this.setOwnerUUID(UUID.fromString(ownerUuid));
+ this.setTamed(true);
+ } catch (Throwable throwable) {
+ this.setTamed(false);
+ }
+ }
+
+ if (this.goalSit != null) {
+ this.goalSit.setSitting(compound.getBoolean("Sitting"));
+ }
+
+ this.setSitting(compound.getBoolean("Sitting"));
+ }
+
+ public boolean isTamed() {
+ return ((Byte) this.datawatcher.get(tamed) & 4) != 0;
+ }
+
+ public void setTamed(boolean tamed_) {
+ byte isTamed = this.datawatcher.get(tamed);
+ if (tamed_) {
+ this.datawatcher.set(tamed, (byte) (isTamed | 4));
+ } else {
+ this.datawatcher.set(tamed, (byte) (isTamed & -5));
+ }
+ this.reassessTameGoals();
+
+ if (tamed_) {
+ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(24.0D);
+ this.getAttributeInstance(GenericAttributes.ATTACK_DAMAGE).setValue(3.0D);
+ this.setHealth(this.getMaxHealth());
+ } else {
+ this.getAttributeInstance(GenericAttributes.MAX_HEALTH).setValue(10.0D);
+ this.getAttributeInstance(GenericAttributes.ATTACK_DAMAGE).setValue(2.0D);
+ }
+ }
+
+ // Remove untamed goals if its tamed.
+ private void reassessTameGoals() {
+ if (!isTamed()) return;
+
+ for (PathfinderGoal untamedGoal : untamedGoals) {
+ this.goalSelector.a(untamedGoal);
+ }
+ }
+
+ // deobf: mobInteract
+ public EnumInteractionResult b(EntityHuman entityhuman, EnumHand enumhand) {
+ ItemStack itemstack = entityhuman.b(enumhand);
+ Item item = itemstack.getItem();
+
+ if (itemstack.getItem() instanceof ItemMonsterEgg) {
+ return super.b(entityhuman, enumhand);
+ } else {
+ if (this.isTamed()) {
+
+ // Heal the fox if its health is below the max.
+ if (item.isFood() && item.getFoodInfo().c() && this.getHealth() < this.getMaxHealth()) {
+ // Only remove the item from the player if they're in survival mode.
+ if (!entityhuman.abilities.canInstantlyBuild) {
+ itemstack.subtract(1);
+ }
+
+ this.heal((float)item.getFoodInfo().getNutrition(), EntityRegainHealthEvent.RegainReason.EATING);
+ return EnumInteractionResult.CONSUME;
+ }
+
+ if (isOwnedBy(entityhuman)) {
+ // This super method checks if the fox can breed or not.
+ EnumInteractionResult flag = super.b(entityhuman, enumhand);
+
+ // If the player is not sneaking and the fox cannot breed, then make the fox sit.
+ // @TODO: Do I need to use this.eQ() instead of flag != EnumInteractionResult.SUCCESS?
+ if (!entityhuman.isSneaking() && (flag != EnumInteractionResult.SUCCESS || this.isBaby())) {
+ this.goalSit.setSitting(!this.isSitting());
+ return flag;
+ } else if (entityhuman.isSneaking()) { // Swap/Put/Take item from fox.
+ // Ignore buckets since they can be easily duplicated.
+ if (itemstack.getItem() == Items.BUCKET || itemstack.getItem() == Items.LAVA_BUCKET || itemstack.getItem() == Items.WATER_BUCKET) {
+ return EnumInteractionResult.PASS;
+ }
+
+ if (!this.getEquipment(EnumItemSlot.MAINHAND).isEmpty()) {
+ getBukkitEntity().getWorld().dropItem(getBukkitEntity().getLocation(), CraftItemStack.asBukkitCopy(this.getEquipment(EnumItemSlot.MAINHAND)));
+ this.setSlot(EnumItemSlot.MAINHAND, new ItemStack(Items.AIR));
+ }
+
+ // 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.
+ Bukkit.getScheduler().runTaskLaterAsynchronously(TamableFoxes.getPlugin(), ()-> {
+ // Put item in mouth
+ if (item != Items.AIR) {
+ ItemStack c = itemstack.cloneItemStack();
+ c.setCount(1);
+
+ // Only remove the item from the player if they're in survival mode.
+ if (!entityhuman.abilities.canInstantlyBuild) {
+ itemstack.subtract(1);
+ }
+
+ this.setSlot(EnumItemSlot.MAINHAND, c);
+ }
+ }, (long) 0.1);
+
+ return EnumInteractionResult.SUCCESS;
+ //return true;
+ }
+ }
+ } else if (item == Items.CHICKEN) {
+ // Check if the player has permissions to tame the fox
+ if (Config.canPlayerTameFox((Player) entityhuman.getBukkitEntity())) {
+ // Only remove the item from the player if they're in survival mode.
+ if (!entityhuman.abilities.canInstantlyBuild) {
+ itemstack.subtract(1);
+ }
+
+ SQLiteHelper sqLiteHelper = SQLiteHelper.getInstance();
+ int maxTameCount = Config.getMaxPlayerFoxTames();
+ if ( !((Player) entityhuman.getBukkitEntity()).hasPermission("tamablefoxes.tame.unlimited") && maxTameCount > 0 && sqLiteHelper.getPlayerFoxAmount(entityhuman.getUniqueID()) >= maxTameCount) {
+ ((Player) entityhuman.getBukkitEntity()).sendMessage(Utils.getPrefix() + ChatColor.RED + LanguageConfig.getFoxDoesntTrust());
+
+ return EnumInteractionResult.SUCCESS;
+ }
+
+ // 0.33% chance to tame the fox, also check if the called tame entity event is cancelled or not.
+ if (this.random.nextInt(3) == 0 && !CraftEventFactory.callEntityTameEvent(this, entityhuman).isCancelled()) {
+ this.tame(entityhuman);
+
+ // Remove all navigation when tamed.
+ this.navigation.o();
+ this.setGoalTarget(null);
+ this.goalSit.setSitting(true);
+
+ if (maxTameCount > 0) {
+ sqLiteHelper.addPlayerFoxAmount(entityhuman.getUniqueID(), 1);
+ }
+
+ getBukkitEntity().getWorld().spawnParticle(org.bukkit.Particle.HEART, getBukkitEntity().getLocation(), 6, 0.5D, 0.5D, 0.5D);
+
+ // Give player tamed message.
+ ((Player) entityhuman.getBukkitEntity()).sendMessage(Utils.getPrefix() + ChatColor.GREEN + LanguageConfig.getTamedMessage());
+
+ // Let the player choose the new fox's name if its enabled in config.
+ if (Config.askForNameAfterTaming()) {
+ Player player = (Player) entityhuman.getBukkitEntity();
+
+ player.sendMessage(Utils.getPrefix() + ChatColor.RED + LanguageConfig.getTamingAskingName());
+ new AnvilGUI.Builder()
+ .onComplete((plr, input) -> { // Called when the inventory output slot is clicked
+ if (!input.equals("")) {
+ org.bukkit.entity.Entity tamableFox = this.getBukkitEntity();
+
+ // This will auto format the name for config settings.
+ String foxName = LanguageConfig.getFoxNameFormat(input, player.getDisplayName());
+
+ tamableFox.setCustomName(foxName);
+ tamableFox.setCustomNameVisible(true);
+ plr.sendMessage(Utils.getPrefix() + ChatColor.GREEN + LanguageConfig.getTamingChosenPerfect(input));
+ }
+
+ return AnvilGUI.Response.close();
+ })
+ .text("Fox name") // Sets the text the GUI should start with
+ .plugin(TamableFoxes.getPlugin()) // Set the plugin instance
+ .open(player); // Opens the GUI for the player provided
+ }
+ } else {
+ getBukkitEntity().getWorld().spawnParticle(org.bukkit.Particle.SMOKE_NORMAL, getBukkitEntity().getLocation(), 10, 0.2D, 0.2D, 0.2D, 0.15D);
+ }
+ }
+
+ return EnumInteractionResult.SUCCESS;
+ }
+
+ return super.b(entityhuman, enumhand);
+ }
+ }
+
+ @Override
+ public EntityTamableFox createChild(WorldServer worldserver, EntityAgeable entityageable) {
+ EntityTamableFox entityfox = (EntityTamableFox) EntityTypes.FOX.a(worldserver);
+ entityfox.setFoxType(this.random.nextBoolean() ? this.getFoxType() : ((EntityFox)entityageable).getFoxType());
+
+ UUID uuid = this.getOwnerUUID();
+ if (uuid != null) {
+ entityfox.setOwnerUUID(uuid);
+ entityfox.setTamed(true);
+ }
+
+ return entityfox;
+ }
+
+ public boolean mate(EntityAnimal entityanimal) {
+ if (entityanimal == this) {
+ return false;
+ } else if (!(entityanimal instanceof EntityTamableFox)) {
+ return false;
+ } else {
+ EntityTamableFox entityFox = (EntityTamableFox) entityanimal;
+ return (!entityFox.isSitting() && (this.isInLove() && entityFox.isInLove()));
+ }
+ }
+
+ @Nullable
+ public UUID getOwnerUUID() {
+ return (UUID) ((Optional) this.datawatcher.get(ownerUUID)).orElse(null);
+ }
+
+ public void setOwnerUUID(@Nullable UUID ownerUuid) {
+ this.datawatcher.set(ownerUUID, Optional.ofNullable(ownerUuid));
+ }
+
+ public void tame(EntityHuman owner) {
+ this.setTamed(true);
+ this.setOwnerUUID(owner.getUniqueID());
+
+ // Give the player the taming advancement.
+ if (owner instanceof EntityPlayer) {
+ CriterionTriggers.x.a((EntityPlayer)owner, this);
+ }
+ }
+
+ @Nullable
+ public EntityLiving getOwner() {
+ try {
+ UUID ownerUuid = this.getOwnerUUID();
+ return ownerUuid == null ? null : this.world.b(ownerUuid);
+ } catch (IllegalArgumentException var2) {
+ return null;
+ }
+ }
+
+ // Only attack entity if its not attacking owner.
+ @Override
+ public boolean c(EntityLiving entity) {
+ return !this.isOwnedBy(entity) && super.c(entity);
+ }
+
+ public boolean isOwnedBy(EntityLiving entity) {
+ return entity == this.getOwner();
+ }
+
+ /*
+ deobf: wantsToAttack (Copied from EntityWolf)
+ This code being from EntityWolf also means that wolves will want to attack foxes
+ Our life would be so much easier if we could extend both EntityFox and EntityTameableAnimal
+ */
+ public boolean a(EntityLiving entityliving, EntityLiving entityliving1) {
+ if (!(entityliving instanceof EntityCreeper) && !(entityliving instanceof EntityGhast)) {
+ if (entityliving instanceof EntityTamableFox) {
+ EntityTamableFox entityFox = (EntityTamableFox) entityliving;
+ return !entityFox.isTamed() || entityFox.getOwner() != entityliving1;
+ } else {
+ return (!(entityliving instanceof EntityHuman)
+ || !(entityliving1 instanceof EntityHuman) ||
+ ((EntityHuman) entityliving1).a((EntityHuman) entityliving)) && ((!(entityliving instanceof EntityHorseAbstract)
+ || !((EntityHorseAbstract) entityliving).isTamed()) && (!(entityliving instanceof EntityTameableAnimal)
+ || !((EntityTameableAnimal) entityliving).isTamed()));
+ }
+ } else {
+ return false;
+ }
+ }
+
+ // Set the scoreboard team to the same as the owner if its tamed.
+ public ScoreboardTeamBase getScoreboardTeam() {
+ if (this.isTamed()) {
+ EntityLiving var0 = this.getOwner();
+ if (var0 != null) {
+ return var0.getScoreboardTeam();
+ }
+ }
+
+ return super.getScoreboardTeam();
+ }
+
+ // Override isAlliedTo (Entity::r(Entity))
+ public boolean r(Entity entity) {
+ if (this.isTamed()) {
+ EntityLiving entityOwner = this.getOwner();
+ if (entity == entityOwner) {
+ return true;
+ }
+
+ if (entityOwner != null) {
+ return entityOwner.r(entity);
+ }
+ }
+ return super.r(entity);
+ }
+
+ // When the fox dies, show a chat message.
+ public void die(DamageSource damageSource) {
+ if (!this.world.isClientSide && this.world.getGameRules().getBoolean(GameRules.SHOW_DEATH_MESSAGES) && this.getOwner() instanceof EntityPlayer) {
+ this.getOwner().sendMessage(this.getCombatTracker().getDeathMessage(), getOwnerUUID());
+
+ // Remove the amount of foxes the player has tamed if the limit is enabled.
+ if (Config.getMaxPlayerFoxTames() > 0) {
+ SQLiteHelper sqliteHelper = SQLiteHelper.getInstance();
+ sqliteHelper.removePlayerFoxAmount(this.getOwner().getUniqueID(), 1);
+ }
+ }
+
+ super.die(damageSource);
+ }
+
+
+ private PathfinderGoal getFoxInnerPathfinderGoal(String innerName, List