From 6e9e72df5c63a3d957775e83bb1989d079da97a1 Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Thu, 9 May 2019 18:35:51 -0500 Subject: [PATCH] Add config files. Separate phantom/crystal logic from ridables. Reorder patches --- patches/server/0002-Purpur-config-files.patch | 274 ++++++++++++ ...ows-to-mooshroom-when-fed-mushrooms.patch} | 2 +- ...patch => 0004-PlayerFeedAnimalEvent.patch} | 2 +- ...se-Animals-isBreedingItem-ItemStack.patch} | 2 +- ...ow-rotation-when-shearing-mooshroom.patch} | 2 +- ...umpkin-on-off-by-player-interaction.patch} | 2 +- ...ement-LivingEntity-safeFallDistance.patch} | 4 +- ...s.patch => 0009-Silk-touch-spawners.patch} | 2 +- ...ed-to-crystals-and-crystals-shoot-ph.patch | 311 +++++++++++++ ...es.patch => 0011-Integrate-ridables.patch} | 422 +++--------------- 10 files changed, 654 insertions(+), 369 deletions(-) create mode 100644 patches/server/0002-Purpur-config-files.patch rename patches/server/{0002-cows-to-mooshroom-when-fed-mushrooms.patch => 0003-cows-to-mooshroom-when-fed-mushrooms.patch} (98%) rename patches/server/{0003-PlayerFeedAnimalEvent.patch => 0004-PlayerFeedAnimalEvent.patch} (95%) rename patches/server/{0004-Expose-Animals-isBreedingItem-ItemStack.patch => 0005-Expose-Animals-isBreedingItem-ItemStack.patch} (94%) rename patches/server/{0005-Fix-cow-rotation-when-shearing-mooshroom.patch => 0006-Fix-cow-rotation-when-shearing-mooshroom.patch} (95%) rename patches/server/{0006-Snowman-set-pumpkin-on-off-by-player-interaction.patch => 0007-Snowman-set-pumpkin-on-off-by-player-interaction.patch} (97%) rename patches/server/{0007-Implement-LivingEntity-safeFallDistance.patch => 0008-Implement-LivingEntity-safeFallDistance.patch} (97%) rename patches/server/{0008-Silk-touch-spawners.patch => 0009-Silk-touch-spawners.patch} (98%) create mode 100644 patches/server/0010-Phantoms-attracted-to-crystals-and-crystals-shoot-ph.patch rename patches/server/{0009-Integrate-ridables.patch => 0011-Integrate-ridables.patch} (83%) diff --git a/patches/server/0002-Purpur-config-files.patch b/patches/server/0002-Purpur-config-files.patch new file mode 100644 index 000000000..730db74a9 --- /dev/null +++ b/patches/server/0002-Purpur-config-files.patch @@ -0,0 +1,274 @@ +From 59f6f2e5c04bcb8dd2dcfabde239f9683f623288 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Thu, 9 May 2019 18:09:43 -0500 +Subject: [PATCH] Purpur config files + +--- + .../net/minecraft/server/DedicatedServer.java | 8 ++ + src/main/java/net/minecraft/server/World.java | 3 + + .../java/net/pl3x/purpur/PurpurConfig.java | 101 ++++++++++++++++++ + .../net/pl3x/purpur/PurpurWorldConfig.java | 63 +++++++++++ + .../org/bukkit/craftbukkit/CraftServer.java | 2 + + .../java/org/bukkit/craftbukkit/Main.java | 8 ++ + 6 files changed, 185 insertions(+) + create mode 100644 src/main/java/net/pl3x/purpur/PurpurConfig.java + create mode 100644 src/main/java/net/pl3x/purpur/PurpurWorldConfig.java + +diff --git a/src/main/java/net/minecraft/server/DedicatedServer.java b/src/main/java/net/minecraft/server/DedicatedServer.java +index 3d452fe0e..22e81ee10 100644 +--- a/src/main/java/net/minecraft/server/DedicatedServer.java ++++ b/src/main/java/net/minecraft/server/DedicatedServer.java +@@ -172,6 +172,14 @@ public class DedicatedServer extends MinecraftServer implements IMinecraftServer + return false; + } + com.destroystokyo.paper.PaperConfig.registerCommands(); ++ // Purpur start ++ try { ++ net.pl3x.purpur.PurpurConfig.init((File) options.valueOf("purpur-settings")); ++ } catch (Exception e) { ++ DedicatedServer.LOGGER.error("Unable to load server configuration", e); ++ return false; ++ } ++ // Purpur end + com.destroystokyo.paper.VersionHistoryManager.INSTANCE.getClass(); // load version history now + // Paper end + +diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java +index cae59ed37..fdd316779 100644 +--- a/src/main/java/net/minecraft/server/World.java ++++ b/src/main/java/net/minecraft/server/World.java +@@ -94,6 +94,8 @@ public abstract class World implements IIBlockAccess, GeneratorAccess, AutoClose + + public final com.destroystokyo.paper.PaperWorldConfig paperConfig; // Paper + ++ public final net.pl3x.purpur.PurpurWorldConfig purpurConfig; // Purpur ++ + public final co.aikar.timings.WorldTimingsHandler timings; // Paper + public static BlockPosition lastPhysicsProblem; // Spigot + private org.spigotmc.TickLimiter entityLimiter; +@@ -116,6 +118,7 @@ public abstract class World implements IIBlockAccess, GeneratorAccess, AutoClose + protected World(WorldData worlddata, DimensionManager dimensionmanager, BiFunction bifunction, GameProfilerFiller gameprofilerfiller, boolean flag, org.bukkit.generator.ChunkGenerator gen, org.bukkit.World.Environment env) { + this.spigotConfig = new org.spigotmc.SpigotWorldConfig( worlddata.getName() ); // Spigot + this.paperConfig = new com.destroystokyo.paper.PaperWorldConfig(worlddata.getName(), this.spigotConfig); // Paper ++ this.purpurConfig = new net.pl3x.purpur.PurpurWorldConfig(worlddata.getName(), this.paperConfig, this.spigotConfig); // Purpur + this.generator = gen; + this.world = new CraftWorld((WorldServer) this, gen, env); + this.ticksPerAnimalSpawns = this.getServer().getTicksPerAnimalSpawns(); // CraftBukkit +diff --git a/src/main/java/net/pl3x/purpur/PurpurConfig.java b/src/main/java/net/pl3x/purpur/PurpurConfig.java +new file mode 100644 +index 000000000..28f80e1a5 +--- /dev/null ++++ b/src/main/java/net/pl3x/purpur/PurpurConfig.java +@@ -0,0 +1,101 @@ ++package net.pl3x.purpur; ++ ++import com.google.common.base.Throwables; ++import org.bukkit.Bukkit; ++import org.bukkit.configuration.InvalidConfigurationException; ++import org.bukkit.configuration.file.YamlConfiguration; ++ ++import java.io.File; ++import java.io.IOException; ++import java.lang.reflect.InvocationTargetException; ++import java.lang.reflect.Method; ++import java.lang.reflect.Modifier; ++import java.util.List; ++import java.util.logging.Level; ++ ++public class PurpurConfig { ++ private static final int CONFIG_VERSION = 1; ++ private static final String HEADER = "This is the main configuration file for Purpur."; ++ private static File CONFIG_FILE; ++ static YamlConfiguration config; ++ static int version; ++ ++ public static void init(File configFile) { ++ CONFIG_FILE = configFile; ++ config = new YamlConfiguration(); ++ try { ++ config.load(CONFIG_FILE); ++ } catch (IOException ex) { ++ } catch (InvalidConfigurationException ex) { ++ Bukkit.getLogger().log(Level.SEVERE, "Could not load purpur.yml, please correct your syntax errors", ex); ++ throw Throwables.propagate(ex); ++ } ++ config.options().header(HEADER); ++ config.options().copyDefaults(true); ++ ++ version = getInt("config-version", CONFIG_VERSION); ++ set("config-version", version); ++ ++ readConfig(PurpurConfig.class, null); ++ } ++ ++ protected static void log(String s) { ++ log(Level.INFO, s); ++ } ++ ++ protected static void log(Level level, String s) { ++ Bukkit.getLogger().log(level, s); ++ } ++ ++ static void readConfig(Class clazz, Object instance) { ++ for (Method method : clazz.getDeclaredMethods()) { ++ if (Modifier.isPrivate(method.getModifiers())) { ++ if (method.getParameterTypes().length == 0 && method.getReturnType() == Void.TYPE) { ++ try { ++ method.setAccessible(true); ++ method.invoke(instance); ++ } catch (InvocationTargetException ex) { ++ throw Throwables.propagate(ex.getCause()); ++ } catch (Exception ex) { ++ Bukkit.getLogger().log(Level.SEVERE, "Error invoking " + method, ex); ++ } ++ } ++ } ++ } ++ ++ try { ++ config.save(CONFIG_FILE); ++ } catch (IOException ex) { ++ Bukkit.getLogger().log(Level.SEVERE, "Could not save " + CONFIG_FILE, ex); ++ } ++ } ++ ++ private static void set(String path, Object val) { ++ config.set(path, val); ++ } ++ ++ private static boolean getBoolean(String path, boolean def) { ++ config.addDefault(path, def); ++ return config.getBoolean(path, config.getBoolean(path)); ++ } ++ ++ private static double getDouble(String path, double def) { ++ config.addDefault(path, def); ++ return config.getDouble(path, config.getDouble(path)); ++ } ++ ++ private static int getInt(String path, int def) { ++ config.addDefault(path, def); ++ return config.getInt(path, config.getInt(path)); ++ } ++ ++ private static List getList(String path, T def) { ++ config.addDefault(path, def); ++ return config.getList(path, config.getList(path)); ++ } ++ ++ private static String getString(String path, String def) { ++ config.addDefault(path, def); ++ return config.getString(path, config.getString(path)); ++ } ++} +diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +new file mode 100644 +index 000000000..30f11fe26 +--- /dev/null ++++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +@@ -0,0 +1,63 @@ ++package net.pl3x.purpur; ++ ++import com.destroystokyo.paper.PaperWorldConfig; ++import org.bukkit.configuration.file.YamlConfiguration; ++import org.spigotmc.SpigotWorldConfig; ++ ++import java.util.List; ++ ++import static net.pl3x.purpur.PurpurConfig.log; ++ ++public class PurpurWorldConfig { ++ ++ private final String worldName; ++ private final PaperWorldConfig paperConfig; ++ private final SpigotWorldConfig spigotConfig; ++ private final YamlConfiguration config; ++ private boolean verbose; ++ ++ public PurpurWorldConfig(String worldName, PaperWorldConfig paperConfig, SpigotWorldConfig spigotConfig) { ++ this.worldName = worldName; ++ this.paperConfig = paperConfig; ++ this.spigotConfig = spigotConfig; ++ this.config = PurpurConfig.config; ++ init(); ++ } ++ ++ public void init() { ++ log("-------- World Settings For [" + worldName + "] --------"); ++ PurpurConfig.readConfig(PurpurWorldConfig.class, this); ++ } ++ ++ private void set(String path, Object val) { ++ config.set("world-settings.default." + path, val); ++ if (config.get("world-settings." + worldName + "." + path) != null) { ++ config.set("world-settings." + worldName + "." + path, val); ++ } ++ } ++ ++ private boolean getBoolean(String path, boolean def) { ++ config.addDefault("world-settings.default." + path, def); ++ return config.getBoolean("world-settings." + worldName + "." + path, config.getBoolean("world-settings.default." + path)); ++ } ++ ++ private double getDouble(String path, double def) { ++ config.addDefault("world-settings.default." + path, def); ++ return config.getDouble("world-settings." + worldName + "." + path, config.getDouble("world-settings.default." + path)); ++ } ++ ++ private int getInt(String path, int def) { ++ config.addDefault("world-settings.default." + path, def); ++ return config.getInt("world-settings." + worldName + "." + path, config.getInt("world-settings.default." + path)); ++ } ++ ++ private List getList(String path, T def) { ++ config.addDefault("world-settings.default." + path, def); ++ return config.getList("world-settings." + worldName + "." + path, config.getList("world-settings.default." + path)); ++ } ++ ++ private String getString(String path, String def) { ++ config.addDefault("world-settings.default." + path, def); ++ return config.getString("world-settings." + worldName + "." + path, config.getString("world-settings.default." + path)); ++ } ++} +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index 347e3f918..69ecd9cc1 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -788,6 +788,7 @@ public final class CraftServer implements Server { + + org.spigotmc.SpigotConfig.init((File) console.options.valueOf("spigot-settings")); // Spigot + com.destroystokyo.paper.PaperConfig.init((File) console.options.valueOf("paper-settings")); // Paper ++ net.pl3x.purpur.PurpurConfig.init((File) console.options.valueOf("purpur-settings")); // Purpur + for (WorldServer world : console.getWorlds()) { + world.worldData.setDifficulty(config.difficulty); + world.setSpawnFlags(config.spawnMonsters, config.spawnAnimals); +@@ -804,6 +805,7 @@ public final class CraftServer implements Server { + } + world.spigotConfig.init(); // Spigot + world.paperConfig.init(); // Paper ++ world.purpurConfig.init(); // Purpur + } + + Plugin[] pluginClone = pluginManager.getPlugins().clone(); // Paper +diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java +index 405ea5c46..2d60e7588 100644 +--- a/src/main/java/org/bukkit/craftbukkit/Main.java ++++ b/src/main/java/org/bukkit/craftbukkit/Main.java +@@ -137,6 +137,14 @@ public class Main { + .describedAs("Yml file"); + // Paper end + ++ // Purpur Start ++ acceptsAll(asList("purpur", "purpur-settings"), "File for purpur settings") ++ .withRequiredArg() ++ .ofType(File.class) ++ .defaultsTo(new File("purpur.yml")) ++ .describedAs("Yml file"); ++ // Purpur end ++ + // Paper start + acceptsAll(asList("server-name"), "Name of the server") + .withRequiredArg() +-- +2.20.1 + diff --git a/patches/server/0002-cows-to-mooshroom-when-fed-mushrooms.patch b/patches/server/0003-cows-to-mooshroom-when-fed-mushrooms.patch similarity index 98% rename from patches/server/0002-cows-to-mooshroom-when-fed-mushrooms.patch rename to patches/server/0003-cows-to-mooshroom-when-fed-mushrooms.patch index 35e7f5845..02a2deadf 100644 --- a/patches/server/0002-cows-to-mooshroom-when-fed-mushrooms.patch +++ b/patches/server/0003-cows-to-mooshroom-when-fed-mushrooms.patch @@ -1,4 +1,4 @@ -From 526b45ebd934832e19fd6b9091cb399f34e2c793 Mon Sep 17 00:00:00 2001 +From a831a65545098083d533f3053354aef9e0d98a62 Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Sat, 4 May 2019 01:10:30 -0500 Subject: [PATCH] cows to mooshroom when fed mushrooms diff --git a/patches/server/0003-PlayerFeedAnimalEvent.patch b/patches/server/0004-PlayerFeedAnimalEvent.patch similarity index 95% rename from patches/server/0003-PlayerFeedAnimalEvent.patch rename to patches/server/0004-PlayerFeedAnimalEvent.patch index e6630aa01..625c92f27 100644 --- a/patches/server/0003-PlayerFeedAnimalEvent.patch +++ b/patches/server/0004-PlayerFeedAnimalEvent.patch @@ -1,4 +1,4 @@ -From 50e421da6a6620d15e29fb476577b0ff445b0c65 Mon Sep 17 00:00:00 2001 +From 85502589238590465c50bdff0c2283ce3b021fa4 Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Fri, 3 May 2019 23:39:38 -0500 Subject: [PATCH] PlayerFeedAnimalEvent diff --git a/patches/server/0004-Expose-Animals-isBreedingItem-ItemStack.patch b/patches/server/0005-Expose-Animals-isBreedingItem-ItemStack.patch similarity index 94% rename from patches/server/0004-Expose-Animals-isBreedingItem-ItemStack.patch rename to patches/server/0005-Expose-Animals-isBreedingItem-ItemStack.patch index 0f6e2bb05..d4cb1fe96 100644 --- a/patches/server/0004-Expose-Animals-isBreedingItem-ItemStack.patch +++ b/patches/server/0005-Expose-Animals-isBreedingItem-ItemStack.patch @@ -1,4 +1,4 @@ -From 57f8d250f1af0e3b93e1168e2a5c5711c4f97d71 Mon Sep 17 00:00:00 2001 +From 58e9ab95ec62c6d5e2dcc37849b323a1254734cd Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Fri, 3 May 2019 23:45:45 -0500 Subject: [PATCH] Expose Animals#isBreedingItem(ItemStack) diff --git a/patches/server/0005-Fix-cow-rotation-when-shearing-mooshroom.patch b/patches/server/0006-Fix-cow-rotation-when-shearing-mooshroom.patch similarity index 95% rename from patches/server/0005-Fix-cow-rotation-when-shearing-mooshroom.patch rename to patches/server/0006-Fix-cow-rotation-when-shearing-mooshroom.patch index a413e10ae..171958f75 100644 --- a/patches/server/0005-Fix-cow-rotation-when-shearing-mooshroom.patch +++ b/patches/server/0006-Fix-cow-rotation-when-shearing-mooshroom.patch @@ -1,4 +1,4 @@ -From e08952bd0dd95decb187f18b812d85e27d476e38 Mon Sep 17 00:00:00 2001 +From 6e9f28ddbb366425610b4608758b4f256aa9dc4f Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Fri, 3 May 2019 23:53:16 -0500 Subject: [PATCH] Fix cow rotation when shearing mooshroom diff --git a/patches/server/0006-Snowman-set-pumpkin-on-off-by-player-interaction.patch b/patches/server/0007-Snowman-set-pumpkin-on-off-by-player-interaction.patch similarity index 97% rename from patches/server/0006-Snowman-set-pumpkin-on-off-by-player-interaction.patch rename to patches/server/0007-Snowman-set-pumpkin-on-off-by-player-interaction.patch index 7c2bd7ba1..18837aad8 100644 --- a/patches/server/0006-Snowman-set-pumpkin-on-off-by-player-interaction.patch +++ b/patches/server/0007-Snowman-set-pumpkin-on-off-by-player-interaction.patch @@ -1,4 +1,4 @@ -From 545452f08d19964e93df05345cbd7e405c583077 Mon Sep 17 00:00:00 2001 +From fccb0a779a6fcf0809341268d16dbaa072999566 Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Fri, 3 May 2019 23:58:44 -0500 Subject: [PATCH] Snowman set pumpkin on/off by player interaction diff --git a/patches/server/0007-Implement-LivingEntity-safeFallDistance.patch b/patches/server/0008-Implement-LivingEntity-safeFallDistance.patch similarity index 97% rename from patches/server/0007-Implement-LivingEntity-safeFallDistance.patch rename to patches/server/0008-Implement-LivingEntity-safeFallDistance.patch index c950d60ea..fa789af6d 100644 --- a/patches/server/0007-Implement-LivingEntity-safeFallDistance.patch +++ b/patches/server/0008-Implement-LivingEntity-safeFallDistance.patch @@ -1,4 +1,4 @@ -From 9fb9afd68241fd01be4dfdf00f0211294b8471d6 Mon Sep 17 00:00:00 2001 +From fd56e202b0bda0125e3491b9a71c62ac5ee1fcf9 Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Sun, 5 May 2019 12:58:45 -0500 Subject: [PATCH] Implement LivingEntity safeFallDistance @@ -39,7 +39,7 @@ index 8ce2fca80..686bca4f2 100644 if (i > 0) { this.damageEntity(DamageSource.FALL, (float) i); diff --git a/src/main/java/net/minecraft/server/EntityLiving.java b/src/main/java/net/minecraft/server/EntityLiving.java -index dacaa16e0..488ecbaa9 100644 +index 20e8ae96d..b27a9efcc 100644 --- a/src/main/java/net/minecraft/server/EntityLiving.java +++ b/src/main/java/net/minecraft/server/EntityLiving.java @@ -122,6 +122,7 @@ public abstract class EntityLiving extends Entity { diff --git a/patches/server/0008-Silk-touch-spawners.patch b/patches/server/0009-Silk-touch-spawners.patch similarity index 98% rename from patches/server/0008-Silk-touch-spawners.patch rename to patches/server/0009-Silk-touch-spawners.patch index d19e1c608..f418afaca 100644 --- a/patches/server/0008-Silk-touch-spawners.patch +++ b/patches/server/0009-Silk-touch-spawners.patch @@ -1,4 +1,4 @@ -From 2f26b5ae47d6b6528c3955c8244da07a298deded Mon Sep 17 00:00:00 2001 +From 9d9becd499b2fcea1601e0c18f9f090c359a297a Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Thu, 9 May 2019 14:27:37 -0500 Subject: [PATCH] Silk touch spawners diff --git a/patches/server/0010-Phantoms-attracted-to-crystals-and-crystals-shoot-ph.patch b/patches/server/0010-Phantoms-attracted-to-crystals-and-crystals-shoot-ph.patch new file mode 100644 index 000000000..649a7c493 --- /dev/null +++ b/patches/server/0010-Phantoms-attracted-to-crystals-and-crystals-shoot-ph.patch @@ -0,0 +1,311 @@ +From fb39b44c654ae8bfaae679e4031d088616b50e38 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Thu, 9 May 2019 18:26:06 -0500 +Subject: [PATCH] Phantoms attracted to crystals and crystals shoot phantoms + +--- + .../minecraft/server/EntityEnderCrystal.java | 49 ++++++ + .../net/minecraft/server/EntityPhantom.java | 165 +++++++++++++++++- + 2 files changed, 211 insertions(+), 3 deletions(-) + +diff --git a/src/main/java/net/minecraft/server/EntityEnderCrystal.java b/src/main/java/net/minecraft/server/EntityEnderCrystal.java +index 9491cb9de..871c65b88 100644 +--- a/src/main/java/net/minecraft/server/EntityEnderCrystal.java ++++ b/src/main/java/net/minecraft/server/EntityEnderCrystal.java +@@ -13,6 +13,12 @@ public class EntityEnderCrystal extends Entity { + private static final DataWatcherObject> c = DataWatcher.a(EntityEnderCrystal.class, DataWatcherRegistry.m); + private static final DataWatcherObject d = DataWatcher.a(EntityEnderCrystal.class, DataWatcherRegistry.i); + public int b; ++ // Purpur start ++ private EntityPhantom targetPhantom; ++ private int phantomBeamTicks = 0; ++ private int phantomDamageCooldown = 0; ++ private int idleCooldown = 0; ++ // Purpur end + + public EntityEnderCrystal(EntityTypes entitytypes, World world) { + super(entitytypes, world); +@@ -54,7 +60,50 @@ public class EntityEnderCrystal extends Entity { + } + } + ++ // Purpur start ++ if (--idleCooldown > 0) { ++ return; // on cooldown ++ } ++ ++ if (targetPhantom == null) { ++ for (EntityPhantom phantom : world.a(EntityPhantom.class, getBoundingBox().grow(16, 16, 16))) { ++ if (phantom.hasLineOfSight(this)) { ++ attackPhantom(phantom); ++ break; ++ } ++ } ++ } else { ++ setBeamTarget(new BlockPosition(targetPhantom).add(0, -2, 0)); ++ if (--phantomBeamTicks > 0 && targetPhantom.isAlive()) { ++ phantomDamageCooldown--; ++ if (targetPhantom.hasLineOfSight(this)) { ++ if (phantomDamageCooldown <= 0) { ++ phantomDamageCooldown = 20; ++ targetPhantom.damageEntity(DamageSource.c(this, this), 1.0F); ++ } ++ } else { ++ forgetPhantom(); // no longer in sight ++ } ++ } else { ++ forgetPhantom(); // attacked long enough ++ } ++ } ++ } ++ ++ private void attackPhantom(EntityPhantom phantom) { ++ phantomDamageCooldown = 0; ++ phantomBeamTicks = 60; ++ targetPhantom = phantom; ++ } ++ ++ private void forgetPhantom() { ++ targetPhantom = null; ++ setBeamTarget(null); ++ phantomBeamTicks = 0; ++ phantomDamageCooldown = 0; ++ idleCooldown = 60; + } ++ // Purpur end + + @Override + protected void b(NBTTagCompound nbttagcompound) { +diff --git a/src/main/java/net/minecraft/server/EntityPhantom.java b/src/main/java/net/minecraft/server/EntityPhantom.java +index e5d032d02..6aa116f4b 100644 +--- a/src/main/java/net/minecraft/server/EntityPhantom.java ++++ b/src/main/java/net/minecraft/server/EntityPhantom.java +@@ -1,5 +1,6 @@ + package net.minecraft.server; + ++import java.util.Comparator; + import java.util.EnumSet; + import java.util.Iterator; + import java.util.List; +@@ -11,6 +12,7 @@ public class EntityPhantom extends EntityFlying implements IMonster { + private Vec3D c; + private BlockPosition d; + private EntityPhantom.AttackPhase bz; ++ private BlockPosition crystalPosition; // Purpur + + public EntityPhantom(EntityTypes entitytypes, World world) { + super(entitytypes, world); +@@ -29,8 +31,10 @@ public class EntityPhantom extends EntityFlying implements IMonster { + + @Override + protected void initPathfinder() { ++ this.goalSelector.a(0, new FindCrystalGoal(this)); // Purpur + this.goalSelector.a(1, new EntityPhantom.c()); + this.goalSelector.a(2, new EntityPhantom.i()); ++ this.goalSelector.a(3, new OrbitCrystalGoal(this)); // Purpur + this.goalSelector.a(3, new EntityPhantom.e()); + this.targetSelector.a(1, new EntityPhantom.b()); + } +@@ -114,6 +118,26 @@ public class EntityPhantom extends EntityFlying implements IMonster { + super.mobTick(); + } + ++ // Purpur start ++ @Override ++ protected LootTableInfo.Builder a(boolean wasRecentlyHit, DamageSource damagesource) { // dropLoot ++ boolean dropped = false; ++ if (killer == null && damagesource.getEntity() instanceof EntityEnderCrystal) { ++ if (random.nextInt(5) < 1) { // 1 out of 5 chance (20%) ++ dropped = a(new ItemStack(Items.PHANTOM_MEMBRANE)) != null; ++ } ++ } ++ if (!dropped) { ++ return super.a(wasRecentlyHit, damagesource); // dropLoot ++ } ++ return new LootTableInfo.Builder((WorldServer) world); ++ } ++ ++ public boolean isCirclingCrystal() { ++ return crystalPosition != null; ++ } ++ // Purpur end ++ + @Override + public GroupDataEntity prepare(GeneratorAccess generatoraccess, DifficultyDamageScaler difficultydamagescaler, EnumMobSpawn enummobspawn, @Nullable GroupDataEntity groupdataentity, @Nullable NBTTagCompound nbttagcompound) { + this.d = (new BlockPosition(this)).up(5); +@@ -202,6 +226,136 @@ public class EntityPhantom extends EntityFlying implements IMonster { + } + // Paper end + ++ // Purpur start ++ class FindCrystalGoal extends PathfinderGoal { ++ private final EntityPhantom phantom; ++ private EntityEnderCrystal crystal; ++ private Comparator comparator; ++ ++ FindCrystalGoal(EntityPhantom phantom) { ++ this.phantom = phantom; ++ comparator = Comparator.comparingDouble(phantom::h); ++ } ++ ++ @Override ++ public boolean a() { // shouldExecute ++ double range = maxTargetRange(); ++ List crystals = world.a(EntityEnderCrystal.class, phantom.getBoundingBox().grow(range, range, range)); ++ if (crystals.isEmpty()) { ++ return false; ++ } ++ crystals.sort(comparator); ++ crystal = crystals.get(0); ++ if (phantom.h(crystal) > range * range) { ++ crystal = null; ++ return false; ++ } ++ return true; ++ } ++ ++ @Override ++ public boolean b() { // shouldContinueExecuting ++ if (crystal == null || !crystal.isAlive()) { ++ return false; ++ } ++ double range = maxTargetRange(); ++ return phantom.h(crystal) <= (range * range) * 2; ++ } ++ ++ @Override ++ public void c() { // startExecuting ++ phantom.crystalPosition = new BlockPosition(crystal).add(0, phantom.getRandom().nextInt(10) + 10, 0); ++ } ++ ++ @Override ++ public void d() { // resetTask ++ crystal = null; ++ phantom.crystalPosition = null; ++ super.d(); ++ } ++ ++ private double maxTargetRange() { ++ AttributeInstance range = phantom.getAttributeInstance(GenericAttributes.FOLLOW_RANGE); ++ return range == null ? 16.0D : range.getValue(); ++ } ++ ++ class DistanceComparator implements Comparator { ++ private final Entity entity; ++ ++ public DistanceComparator(Entity entity) { ++ this.entity = entity; ++ } ++ ++ public int compare(Entity entity1, Entity entity2) { ++ return Double.compare(entity.h(entity1), entity.h(entity2)); ++ } ++ } ++ } ++ ++ class OrbitCrystalGoal extends PathfinderGoal { ++ private final EntityPhantom phantom; ++ private float c; ++ private float radius; ++ private float verticalChange; ++ private float direction; ++ ++ OrbitCrystalGoal(EntityPhantom phantom) { ++ this.phantom = phantom; ++ this.a(EnumSet.of(PathfinderGoal.Type.MOVE)); ++ } ++ ++ @Override ++ public boolean a() { // shouldExecute ++ return phantom.isCirclingCrystal(); ++ } ++ ++ @Override ++ public void c() { // startExecuting ++ this.radius = 5.0F + phantom.random.nextFloat() * 10.0F; ++ this.verticalChange = -4.0F + phantom.random.nextFloat() * 9.0F; ++ this.direction = phantom.random.nextBoolean() ? 1.0F : -1.0F; ++ updateOffset(); ++ } ++ ++ @Override ++ public void e() { // tick ++ if (phantom.random.nextInt(350) == 0) { ++ this.verticalChange = -4.0F + phantom.random.nextFloat() * 9.0F; ++ } ++ if (phantom.random.nextInt(250) == 0) { ++ ++this.radius; ++ if (this.radius > 15.0F) { ++ this.radius = 5.0F; ++ this.direction = -this.direction; ++ } ++ } ++ if (phantom.random.nextInt(450) == 0) { ++ this.c = phantom.random.nextFloat() * 2.0F * 3.1415927F; ++ updateOffset(); ++ } ++ if (phantom.c.c(phantom.locX, phantom.locY, phantom.locZ) < 4.0D) { ++ updateOffset(); ++ } ++ if (phantom.c.y < phantom.locY && !phantom.world.isEmpty((new BlockPosition(phantom)).down(1))) { ++ this.verticalChange = Math.max(1.0F, this.verticalChange); ++ updateOffset(); ++ } ++ if (phantom.c.y > phantom.locY && !phantom.world.isEmpty((new BlockPosition(phantom)).up(1))) { ++ this.verticalChange = Math.min(-1.0F, this.verticalChange); ++ updateOffset(); ++ } ++ } ++ ++ private void updateOffset() { ++ this.c += this.direction * 15.0F * 0.017453292F; ++ phantom.c = new Vec3D(phantom.crystalPosition).add( ++ (double) (this.radius * MathHelper.cos(this.c)), ++ (double) (-4.0F + this.verticalChange), ++ (double) (this.radius * MathHelper.sin(this.c))); ++ } ++ } ++ // Purpur end ++ + class b extends PathfinderGoal { + + private final PathfinderTargetCondition b; +@@ -259,7 +413,7 @@ public class EntityPhantom extends EntityFlying implements IMonster { + public boolean a() { + EntityLiving entityliving = EntityPhantom.this.getGoalTarget(); + +- return entityliving != null ? EntityPhantom.this.a(EntityPhantom.this.getGoalTarget(), PathfinderTargetCondition.a) : false; ++ return !isCirclingCrystal() && entityliving != null && EntityPhantom.this.a(EntityPhantom.this.getGoalTarget(), PathfinderTargetCondition.a); // Purpur + } + + @Override +@@ -305,11 +459,16 @@ public class EntityPhantom extends EntityFlying implements IMonster { + + @Override + public boolean a() { +- return EntityPhantom.this.getGoalTarget() != null && EntityPhantom.this.bz == EntityPhantom.AttackPhase.SWOOP; ++ return !isCirclingCrystal() && EntityPhantom.this.getGoalTarget() != null && EntityPhantom.this.bz == EntityPhantom.AttackPhase.SWOOP; // Purpur + } + + @Override + public boolean b() { ++ // Purpur start ++ if (isCirclingCrystal()) { ++ return false; ++ } ++ // Purpur end + EntityLiving entityliving = EntityPhantom.this.getGoalTarget(); + + if (entityliving == null) { +@@ -379,7 +538,7 @@ public class EntityPhantom extends EntityFlying implements IMonster { + + @Override + public boolean a() { +- return EntityPhantom.this.getGoalTarget() == null || EntityPhantom.this.bz == EntityPhantom.AttackPhase.CIRCLE; ++ return !isCirclingCrystal() && EntityPhantom.this.getGoalTarget() == null || EntityPhantom.this.bz == EntityPhantom.AttackPhase.CIRCLE; // Purpur + } + + @Override +-- +2.20.1 + diff --git a/patches/server/0009-Integrate-ridables.patch b/patches/server/0011-Integrate-ridables.patch similarity index 83% rename from patches/server/0009-Integrate-ridables.patch rename to patches/server/0011-Integrate-ridables.patch index e3d418cdf..d41e715d4 100644 --- a/patches/server/0009-Integrate-ridables.patch +++ b/patches/server/0011-Integrate-ridables.patch @@ -1,59 +1,58 @@ -From 2f733e203b811f198f28e10bf8c98c3bb23ed07c Mon Sep 17 00:00:00 2001 +From 856e639ac4dda7f7e6c472725457f97b7f88ac0f Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Tue, 30 Apr 2019 19:17:21 -0500 Subject: [PATCH] Integrate ridables --- - .../java/net/minecraft/server/BiomeBase.java | 1 + - .../java/net/minecraft/server/Biomes.java | 23 ++ - .../server/ControllerLookDolphin.java | 4 +- - .../java/net/minecraft/server/Entity.java | 15 +- - .../net/minecraft/server/EntityChicken.java | 17 +- - .../java/net/minecraft/server/EntityCow.java | 16 +- - .../net/minecraft/server/EntityCreeper.java | 14 ++ - .../net/minecraft/server/EntityDolphin.java | 27 ++- - .../net/minecraft/server/EntityDrowned.java | 9 +- - .../minecraft/server/EntityEnderCrystal.java | 49 ++++ - .../net/minecraft/server/EntityEnderman.java | 15 ++ - .../net/minecraft/server/EntityEndermite.java | 17 +- - .../java/net/minecraft/server/EntityFish.java | 33 ++- - .../minecraft/server/EntityGiantZombie.java | 35 ++- - .../net/minecraft/server/EntityGuardian.java | 37 ++- - .../net/minecraft/server/EntityHorse.java | 10 +- - .../minecraft/server/EntityHorseAbstract.java | 4 +- - .../server/EntityHorseChestedAbstract.java | 18 +- - .../minecraft/server/EntityHorseDonkey.java | 3 + - .../net/minecraft/server/EntityHorseMule.java | 3 + - .../minecraft/server/EntityHorseSkeleton.java | 15 +- - .../minecraft/server/EntityHorseZombie.java | 12 +- - .../net/minecraft/server/EntityHuman.java | 14 +- - .../minecraft/server/EntityInsentient.java | 39 ++++ - .../net/minecraft/server/EntityIronGolem.java | 15 ++ - .../net/minecraft/server/EntityLiving.java | 28 ++- - .../net/minecraft/server/EntityLlama.java | 37 ++- - .../minecraft/server/EntityMushroomCow.java | 14 ++ - .../net/minecraft/server/EntityOcelot.java | 14 ++ - .../net/minecraft/server/EntityPhantom.java | 216 +++++++++++++++++- - .../java/net/minecraft/server/EntityPig.java | 25 ++ - .../net/minecraft/server/EntityPolarBear.java | 15 ++ - .../net/minecraft/server/EntityRabbit.java | 2 +- - .../net/minecraft/server/EntitySheep.java | 14 ++ - .../minecraft/server/EntitySilverfish.java | 15 ++ - .../server/EntitySkeletonAbstract.java | 15 ++ - .../net/minecraft/server/EntitySlime.java | 2 +- - .../net/minecraft/server/EntitySnowman.java | 15 ++ - .../net/minecraft/server/EntitySpider.java | 15 ++ - .../net/minecraft/server/EntitySquid.java | 57 +++++ - .../server/EntityTameableAnimal.java | 6 + - .../net/minecraft/server/EntityTypes.java | 6 + - .../java/net/minecraft/server/EntityWolf.java | 14 ++ - .../net/minecraft/server/EntityZombie.java | 15 ++ - .../purpur/controller/ControllerLookWASD.java | 46 ++++ - .../purpur/controller/ControllerMoveWASD.java | 77 +++++++ - .../controller/ControllerMoveWASDFlying.java | 58 +++++ - .../controller/ControllerMoveWASDWater.java | 42 ++++ - .../craftbukkit/entity/CraftLivingEntity.java | 10 + - 49 files changed, 1136 insertions(+), 67 deletions(-) + .../java/net/minecraft/server/BiomeBase.java | 1 + + .../java/net/minecraft/server/Biomes.java | 23 ++++++ + .../server/ControllerLookDolphin.java | 4 +- + .../java/net/minecraft/server/Entity.java | 15 +++- + .../net/minecraft/server/EntityChicken.java | 17 +++- + .../java/net/minecraft/server/EntityCow.java | 16 +++- + .../net/minecraft/server/EntityCreeper.java | 14 ++++ + .../net/minecraft/server/EntityDolphin.java | 27 ++++++- + .../net/minecraft/server/EntityDrowned.java | 9 ++- + .../net/minecraft/server/EntityEnderman.java | 15 ++++ + .../net/minecraft/server/EntityEndermite.java | 17 +++- + .../java/net/minecraft/server/EntityFish.java | 33 ++++++-- + .../minecraft/server/EntityGiantZombie.java | 35 ++++++++- + .../net/minecraft/server/EntityGuardian.java | 37 +++++++-- + .../net/minecraft/server/EntityHorse.java | 10 ++- + .../minecraft/server/EntityHorseAbstract.java | 4 +- + .../server/EntityHorseChestedAbstract.java | 18 +++-- + .../minecraft/server/EntityHorseDonkey.java | 3 + + .../net/minecraft/server/EntityHorseMule.java | 3 + + .../minecraft/server/EntityHorseSkeleton.java | 15 ++-- + .../minecraft/server/EntityHorseZombie.java | 12 +-- + .../net/minecraft/server/EntityHuman.java | 14 +++- + .../minecraft/server/EntityInsentient.java | 39 ++++++++++ + .../net/minecraft/server/EntityIronGolem.java | 15 ++++ + .../net/minecraft/server/EntityLiving.java | 28 +++++-- + .../net/minecraft/server/EntityLlama.java | 37 ++++++++- + .../minecraft/server/EntityMushroomCow.java | 14 ++++ + .../net/minecraft/server/EntityOcelot.java | 14 ++++ + .../net/minecraft/server/EntityPhantom.java | 39 ++++++++-- + .../java/net/minecraft/server/EntityPig.java | 25 ++++++ + .../net/minecraft/server/EntityPolarBear.java | 15 ++++ + .../net/minecraft/server/EntityRabbit.java | 2 +- + .../net/minecraft/server/EntitySheep.java | 14 ++++ + .../minecraft/server/EntitySilverfish.java | 15 ++++ + .../server/EntitySkeletonAbstract.java | 15 ++++ + .../net/minecraft/server/EntitySlime.java | 2 +- + .../net/minecraft/server/EntitySnowman.java | 15 ++++ + .../net/minecraft/server/EntitySpider.java | 15 ++++ + .../net/minecraft/server/EntitySquid.java | 57 ++++++++++++++ + .../server/EntityTameableAnimal.java | 6 ++ + .../net/minecraft/server/EntityTypes.java | 6 ++ + .../java/net/minecraft/server/EntityWolf.java | 14 ++++ + .../net/minecraft/server/EntityZombie.java | 15 ++++ + .../purpur/controller/ControllerLookWASD.java | 46 +++++++++++ + .../purpur/controller/ControllerMoveWASD.java | 77 +++++++++++++++++++ + .../controller/ControllerMoveWASDFlying.java | 58 ++++++++++++++ + .../controller/ControllerMoveWASDWater.java | 42 ++++++++++ + .../craftbukkit/entity/CraftLivingEntity.java | 10 +++ + 48 files changed, 916 insertions(+), 61 deletions(-) create mode 100644 src/main/java/net/pl3x/purpur/controller/ControllerLookWASD.java create mode 100644 src/main/java/net/pl3x/purpur/controller/ControllerMoveWASD.java create mode 100644 src/main/java/net/pl3x/purpur/controller/ControllerMoveWASDFlying.java @@ -402,74 +401,6 @@ index 449fbee60..52571bada 100644 } } -diff --git a/src/main/java/net/minecraft/server/EntityEnderCrystal.java b/src/main/java/net/minecraft/server/EntityEnderCrystal.java -index 9491cb9de..871c65b88 100644 ---- a/src/main/java/net/minecraft/server/EntityEnderCrystal.java -+++ b/src/main/java/net/minecraft/server/EntityEnderCrystal.java -@@ -13,6 +13,12 @@ public class EntityEnderCrystal extends Entity { - private static final DataWatcherObject> c = DataWatcher.a(EntityEnderCrystal.class, DataWatcherRegistry.m); - private static final DataWatcherObject d = DataWatcher.a(EntityEnderCrystal.class, DataWatcherRegistry.i); - public int b; -+ // Purpur start -+ private EntityPhantom targetPhantom; -+ private int phantomBeamTicks = 0; -+ private int phantomDamageCooldown = 0; -+ private int idleCooldown = 0; -+ // Purpur end - - public EntityEnderCrystal(EntityTypes entitytypes, World world) { - super(entitytypes, world); -@@ -54,7 +60,50 @@ public class EntityEnderCrystal extends Entity { - } - } - -+ // Purpur start -+ if (--idleCooldown > 0) { -+ return; // on cooldown -+ } -+ -+ if (targetPhantom == null) { -+ for (EntityPhantom phantom : world.a(EntityPhantom.class, getBoundingBox().grow(16, 16, 16))) { -+ if (phantom.hasLineOfSight(this)) { -+ attackPhantom(phantom); -+ break; -+ } -+ } -+ } else { -+ setBeamTarget(new BlockPosition(targetPhantom).add(0, -2, 0)); -+ if (--phantomBeamTicks > 0 && targetPhantom.isAlive()) { -+ phantomDamageCooldown--; -+ if (targetPhantom.hasLineOfSight(this)) { -+ if (phantomDamageCooldown <= 0) { -+ phantomDamageCooldown = 20; -+ targetPhantom.damageEntity(DamageSource.c(this, this), 1.0F); -+ } -+ } else { -+ forgetPhantom(); // no longer in sight -+ } -+ } else { -+ forgetPhantom(); // attacked long enough -+ } -+ } -+ } -+ -+ private void attackPhantom(EntityPhantom phantom) { -+ phantomDamageCooldown = 0; -+ phantomBeamTicks = 60; -+ targetPhantom = phantom; -+ } -+ -+ private void forgetPhantom() { -+ targetPhantom = null; -+ setBeamTarget(null); -+ phantomBeamTicks = 0; -+ phantomDamageCooldown = 0; -+ idleCooldown = 60; - } -+ // Purpur end - - @Override - protected void b(NBTTagCompound nbttagcompound) { diff --git a/src/main/java/net/minecraft/server/EntityEnderman.java b/src/main/java/net/minecraft/server/EntityEnderman.java index f08f139e9..434ffc0f4 100644 --- a/src/main/java/net/minecraft/server/EntityEnderman.java @@ -1263,31 +1194,10 @@ index 1713bead2..21fa1579b 100644 if ((this.bD == null || this.bD.h()) && !this.isTrusting() && this.i(itemstack) && entityhuman.h((Entity) this) < 9.0D) { diff --git a/src/main/java/net/minecraft/server/EntityPhantom.java b/src/main/java/net/minecraft/server/EntityPhantom.java -index e5d032d02..7201b3a39 100644 +index 6aa116f4b..d475cc97e 100644 --- a/src/main/java/net/minecraft/server/EntityPhantom.java +++ b/src/main/java/net/minecraft/server/EntityPhantom.java -@@ -1,5 +1,6 @@ - package net.minecraft.server; - -+import java.util.Comparator; - import java.util.EnumSet; - import java.util.Iterator; - import java.util.List; -@@ -8,9 +9,10 @@ import javax.annotation.Nullable; - public class EntityPhantom extends EntityFlying implements IMonster { - - private static final DataWatcherObject b = DataWatcher.a(EntityPhantom.class, DataWatcherRegistry.b); -- private Vec3D c; -- private BlockPosition d; -- private EntityPhantom.AttackPhase bz; -+ private Vec3D c; public Vec3D getOrbitOffset() { return this.c; } public void setOrbitOffset(Vec3D offset) { this.c = offset; } // Purpur - OBFHELPER -+ private BlockPosition d; public BlockPosition getOrbitPosition() { return this.d; } public void setOrbitPosition(BlockPosition position) { this.d = position; } // Purpur - OBFHELPER -+ private EntityPhantom.AttackPhase bz; public AttackPhase getPhase() { return this.bz; } public void setPhase(AttackPhase phase) { this.bz = phase; } // Purpur - OBFHELPER -+ private BlockPosition totemPosition; public BlockPosition getTotemPosition() { return this.totemPosition; } public void setTotemPosition(BlockPosition position) { this.totemPosition = position; } // Purpur - - public EntityPhantom(EntityTypes entitytypes, World world) { - super(entitytypes, world); -@@ -20,6 +22,7 @@ public class EntityPhantom extends EntityFlying implements IMonster { +@@ -22,6 +22,7 @@ public class EntityPhantom extends EntityFlying implements IMonster { this.f = 5; this.moveController = new EntityPhantom.g(this); this.lookController = new EntityPhantom.f(this); @@ -1295,18 +1205,7 @@ index e5d032d02..7201b3a39 100644 } @Override -@@ -29,8 +32,10 @@ public class EntityPhantom extends EntityFlying implements IMonster { - - @Override - protected void initPathfinder() { -+ this.goalSelector.a(0, new FindTotemGoal(this)); // Purpur - this.goalSelector.a(1, new EntityPhantom.c()); - this.goalSelector.a(2, new EntityPhantom.i()); -+ this.goalSelector.a(3, new OrbitTotemGoal(this)); // Purpur - this.goalSelector.a(3, new EntityPhantom.e()); - this.targetSelector.a(1, new EntityPhantom.b()); - } -@@ -102,7 +107,7 @@ public class EntityPhantom extends EntityFlying implements IMonster { +@@ -106,7 +107,7 @@ public class EntityPhantom extends EntityFlying implements IMonster { @Override public void movementTick() { @@ -1315,38 +1214,10 @@ index e5d032d02..7201b3a39 100644 this.setOnFire(8); } -@@ -114,6 +119,26 @@ public class EntityPhantom extends EntityFlying implements IMonster { - super.mobTick(); - } - -+ // Purpur start -+ @Override -+ protected LootTableInfo.Builder a(boolean wasRecentlyHit, DamageSource damagesource) { // dropLoot -+ boolean dropped = false; -+ if (killer == null && damagesource.getEntity() instanceof EntityEnderCrystal) { -+ if (random.nextInt(5) < 1) { // 1 out of 5 chance (20%) -+ dropped = a(new ItemStack(Items.PHANTOM_MEMBRANE)) != null; -+ } -+ } -+ if (!dropped) { -+ return super.a(wasRecentlyHit, damagesource); // dropLoot -+ } -+ return new LootTableInfo.Builder((WorldServer) world); -+ } -+ -+ public boolean isCirclingTotem() { -+ return totemPosition != null; -+ } -+ // Purpur end -+ - @Override - public GroupDataEntity prepare(GeneratorAccess generatoraccess, DifficultyDamageScaler difficultydamagescaler, EnumMobSpawn enummobspawn, @Nullable GroupDataEntity groupdataentity, @Nullable NBTTagCompound nbttagcompound) { - this.d = (new BlockPosition(this)).up(5); -@@ -202,6 +227,150 @@ public class EntityPhantom extends EntityFlying implements IMonster { - } +@@ -227,6 +228,14 @@ public class EntityPhantom extends EntityFlying implements IMonster { // Paper end -+ // Purpur start - processInteract + // Purpur start + @Override + public boolean a(EntityHuman entityhuman, EnumHand enumhand) { + if (super.a(entityhuman, enumhand)) { @@ -1355,181 +1226,10 @@ index e5d032d02..7201b3a39 100644 + return tryRide(entityhuman, enumhand); + } + -+ class FindTotemGoal extends PathfinderGoal { -+ private final EntityPhantom phantom; -+ private EntityEnderCrystal totem; -+ private Comparator comparator; -+ -+ FindTotemGoal(EntityPhantom phantom) { -+ this.phantom = phantom; -+ comparator = Comparator.comparingDouble(phantom::h); -+ } -+ -+ @Override -+ public boolean a() { // shouldExecute -+ if (phantom.getRider() != null) { -+ return false; -+ } -+ double range = maxTargetRange(); -+ List crystals = world.a(EntityEnderCrystal.class, phantom.getBoundingBox().grow(range, range, range)); -+ if (crystals.isEmpty()) { -+ return false; -+ } -+ crystals.sort(comparator); -+ totem = crystals.get(0); -+ if (phantom.h(totem) > range * range) { -+ totem = null; -+ return false; -+ } -+ return true; -+ } -+ -+ @Override -+ public boolean b() { // shouldContinueExecuting -+ if (phantom.getRider() != null) { -+ return false; -+ } -+ if (totem == null || !totem.isAlive()) { -+ return false; -+ } -+ double range = maxTargetRange(); -+ return phantom.h(totem) <= (range * range) * 2; -+ } -+ -+ @Override -+ public void c() { // startExecuting -+ phantom.setTotemPosition(new BlockPosition(totem).add(0, phantom.getRandom().nextInt(10) + 10, 0)); -+ } -+ -+ @Override -+ public void d() { // resetTask -+ totem = null; -+ phantom.setTotemPosition(null); -+ super.d(); -+ } -+ -+ private double maxTargetRange() { -+ AttributeInstance range = phantom.getAttributeInstance(GenericAttributes.FOLLOW_RANGE); -+ return range == null ? 16.0D : range.getValue(); -+ } -+ -+ class DistanceComparator implements Comparator { -+ private final Entity entity; -+ -+ public DistanceComparator(Entity entity) { -+ this.entity = entity; -+ } -+ -+ public int compare(Entity entity1, Entity entity2) { -+ return Double.compare(entity.h(entity1), entity.h(entity2)); -+ } -+ } -+ } -+ -+ class OrbitTotemGoal extends PathfinderGoal { -+ private final EntityPhantom phantom; -+ private float c; -+ private float radius; -+ private float verticalChange; -+ private float direction; -+ -+ OrbitTotemGoal(EntityPhantom phantom) { -+ this.phantom = phantom; -+ this.a(EnumSet.of(PathfinderGoal.Type.MOVE)); -+ } -+ -+ @Override -+ public boolean a() { // shouldExecute -+ return phantom.getRider() == null && phantom.isCirclingTotem(); -+ } -+ -+ @Override -+ public void c() { // startExecuting -+ this.radius = 5.0F + phantom.random.nextFloat() * 10.0F; -+ this.verticalChange = -4.0F + phantom.random.nextFloat() * 9.0F; -+ this.direction = phantom.random.nextBoolean() ? 1.0F : -1.0F; -+ updateOffset(); -+ } -+ -+ @Override -+ public void e() { // tick -+ if (phantom.random.nextInt(350) == 0) { -+ this.verticalChange = -4.0F + phantom.random.nextFloat() * 9.0F; -+ } -+ if (phantom.random.nextInt(250) == 0) { -+ ++this.radius; -+ if (this.radius > 15.0F) { -+ this.radius = 5.0F; -+ this.direction = -this.direction; -+ } -+ } -+ if (phantom.random.nextInt(450) == 0) { -+ this.c = phantom.random.nextFloat() * 2.0F * 3.1415927F; -+ updateOffset(); -+ } -+ if (phantom.c.c(phantom.locX, phantom.locY, phantom.locZ) < 4.0D) { -+ updateOffset(); -+ } -+ if (phantom.c.y < phantom.locY && !phantom.world.isEmpty((new BlockPosition(phantom)).down(1))) { -+ this.verticalChange = Math.max(1.0F, this.verticalChange); -+ updateOffset(); -+ } -+ if (phantom.c.y > phantom.locY && !phantom.world.isEmpty((new BlockPosition(phantom)).up(1))) { -+ this.verticalChange = Math.min(-1.0F, this.verticalChange); -+ updateOffset(); -+ } -+ } -+ -+ private void updateOffset() { -+ this.c += this.direction * 15.0F * 0.017453292F; -+ phantom.setOrbitOffset(new Vec3D(phantom.totemPosition).add( -+ (double) (this.radius * MathHelper.cos(this.c)), -+ (double) (-4.0F + this.verticalChange), -+ (double) (this.radius * MathHelper.sin(this.c)))); -+ } -+ } -+ // Purpur end -+ - class b extends PathfinderGoal { - - private final PathfinderTargetCondition b; -@@ -259,7 +428,7 @@ public class EntityPhantom extends EntityFlying implements IMonster { - public boolean a() { - EntityLiving entityliving = EntityPhantom.this.getGoalTarget(); - -- return entityliving != null ? EntityPhantom.this.a(EntityPhantom.this.getGoalTarget(), PathfinderTargetCondition.a) : false; -+ return !isCirclingTotem() && entityliving != null && EntityPhantom.this.a(EntityPhantom.this.getGoalTarget(), PathfinderTargetCondition.a); // Purpur - } - - @Override -@@ -305,11 +474,16 @@ public class EntityPhantom extends EntityFlying implements IMonster { - - @Override - public boolean a() { -- return EntityPhantom.this.getGoalTarget() != null && EntityPhantom.this.bz == EntityPhantom.AttackPhase.SWOOP; -+ return !isCirclingTotem() && EntityPhantom.this.getGoalTarget() != null && EntityPhantom.this.bz == EntityPhantom.AttackPhase.SWOOP; // Purpur - } - - @Override - public boolean b() { -+ // Purpur start -+ if (isCirclingTotem()) { -+ return false; -+ } -+ // Purpur end - EntityLiving entityliving = EntityPhantom.this.getGoalTarget(); - - if (entityliving == null) { -@@ -379,7 +553,7 @@ public class EntityPhantom extends EntityFlying implements IMonster { - - @Override - public boolean a() { -- return EntityPhantom.this.getGoalTarget() == null || EntityPhantom.this.bz == EntityPhantom.AttackPhase.CIRCLE; -+ return !isCirclingTotem() && EntityPhantom.this.getGoalTarget() == null || EntityPhantom.this.bz == EntityPhantom.AttackPhase.CIRCLE; // Purpur - } - - @Override -@@ -446,14 +620,23 @@ public class EntityPhantom extends EntityFlying implements IMonster { + class FindCrystalGoal extends PathfinderGoal { + private final EntityPhantom phantom; + private EntityEnderCrystal crystal; +@@ -605,14 +614,23 @@ public class EntityPhantom extends EntityFlying implements IMonster { } } @@ -1555,7 +1255,7 @@ index e5d032d02..7201b3a39 100644 } class d extends EntityAIBodyControl { -@@ -469,7 +652,7 @@ public class EntityPhantom extends EntityFlying implements IMonster { +@@ -628,7 +646,7 @@ public class EntityPhantom extends EntityFlying implements IMonster { } } @@ -1564,7 +1264,7 @@ index e5d032d02..7201b3a39 100644 private float j = 0.1F; -@@ -477,8 +660,19 @@ public class EntityPhantom extends EntityFlying implements IMonster { +@@ -636,8 +654,19 @@ public class EntityPhantom extends EntityFlying implements IMonster { super(entityinsentient); }