mirror of
https://github.com/PurpurMC/Purpur.git
synced 2026-02-21 10:27:44 +01:00
Upstream has released updates that appear to apply and compile correctly Paper Changes: bca97a8f7 replace spaces in world key (touches #5397) de94f6485 Refactor chat message composition (#5396) e27f334bb [CI-SKIP] Fix makemcdevsrc.sh for nms relocations (#5389) ae15e85da Updated Upstream (CraftBukkit) 26fe0ac5a Only set despawnTimer for Wandering Traders spawned by MobSpawnerTrader (#5391) b748eb7b8 Fix VanillaMobGoalTest#testBukkitMap (#5390) 18dbbb578 [Auto] Updated Upstream (CraftBukkit) fac9cc5d5 [CI-SKIP] Ignore .gitignore 087aa70e7 Deprecate ItemStack#setLore(List<String>) and ItemStack#getLore, add Component based alternatives 9889c651c apply fixup c310f0a61 Updated Upstream (Bukkit/CraftBukkit) f17560ab0 wtf is this t file -jmp 347f3a9b8 fix compile 700e9e6a5 rebase cf4dc464a Revert de5f4e469...c270abe96 6870db613 script & POM fix 743c6533c Replace ** with * (BSD/macOS) 376d7b097 Don't remove the .java fcb3fd42a Fix macOS/BSD support 8cfc05249 Link correctly ba1031ca7 Rename work dir c8d844ab7 Actually fix preloading this time e62aa5e3e Fix class preloading 1c03cf898 It's mojang math, not minecraft math 1034873df Apply fixups 39b125771 Use revision file 956150da7 Welcome to 1.16.5-R0.2 ccb217c01 Change cache keys 0d217001c more work f6d820f07 It compiles 0f78e9525 More work 1718f61bf Updated Upstream (CraftBukkit/Spigot) b28d46114 Update scripts for NMS repackaging Tuinity Changes: 9bdcb9b8e Delete work dir when running jar 6351d7ca7 Update Upstream (Paper) 932c199a6 Generate md-dev correctly bf3e73778 Make packet limiter work from IDE 1686f3861 Fix packet limiter config f40f7b425 Update README.md styling (#264) da1c3ace5 GH Actions Changes (#213) 5f325ecf1 Update Upstream (Paper) 0f83fe48d Update Upstream (Paper) Airplane Changes: f94d39947 Merge pull request #18 from notOM3GA/upstream/nms-repackage 0fc622631 Force build for Flare update 08439d6a9 Update Upstream (Tuinity)
372 lines
17 KiB
Diff
372 lines
17 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: William Blake Galbreath <blake.galbreath@gmail.com>
|
|
Date: Thu, 9 May 2019 18:26:06 -0500
|
|
Subject: [PATCH] Phantoms attracted to crystals and crystals shoot phantoms
|
|
|
|
|
|
diff --git a/src/main/java/net/minecraft/world/damagesource/DamageSource.java b/src/main/java/net/minecraft/world/damagesource/DamageSource.java
|
|
index 53ea8a6d90faf4f7f8fd0819be4499422bdd4cbe..6ba14f603b8ec69597c70677cc317f802d6afae9 100644
|
|
--- a/src/main/java/net/minecraft/world/damagesource/DamageSource.java
|
|
+++ b/src/main/java/net/minecraft/world/damagesource/DamageSource.java
|
|
@@ -99,6 +99,7 @@ public class DamageSource {
|
|
return (new EntityDamageSourceIndirect("thrown", entity, entity1)).c();
|
|
}
|
|
|
|
+ public static DamageSource indirectMagic(Entity entity, @Nullable Entity owner) { return c(entity, owner); } // Purpur - OBFHELPER
|
|
public static DamageSource c(Entity entity, @Nullable Entity entity1) {
|
|
return (new EntityDamageSourceIndirect("indirectMagic", entity, entity1)).setIgnoreArmor().setMagic();
|
|
}
|
|
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
|
|
index 7f897bebdc1fe2b7ce9528db9a7dd0fc0cf6c008..5ac6b7759cf43dbbad1bcf74d5d86efd69883cf5 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/Entity.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
|
|
@@ -2246,8 +2246,8 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne
|
|
return this.a(new ItemStack(imaterial), (float) i);
|
|
}
|
|
|
|
- @Nullable
|
|
- public EntityItem a(ItemStack itemstack) {
|
|
+ @Nullable public EntityItem dropItem(ItemStack itemstack) { return this.a(itemstack); } // Purpur - OBFHELPER
|
|
+ @Nullable public EntityItem a(ItemStack itemstack) {
|
|
return this.a(itemstack, 0.0F);
|
|
}
|
|
|
|
diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderCrystal.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderCrystal.java
|
|
index 9658d93615a51375204481cfe0a1fce6f105fd70..2c983e6a092464d1867fcbe875b2e1461ec8556b 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderCrystal.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderCrystal.java
|
|
@@ -14,6 +14,7 @@ import net.minecraft.server.level.WorldServer;
|
|
import net.minecraft.world.damagesource.DamageSource;
|
|
import net.minecraft.world.entity.Entity;
|
|
import net.minecraft.world.entity.EntityTypes;
|
|
+import net.minecraft.world.entity.monster.EntityPhantom;
|
|
import net.minecraft.world.level.Explosion;
|
|
import net.minecraft.world.level.IBlockAccess;
|
|
import net.minecraft.world.level.World;
|
|
@@ -30,6 +31,12 @@ public class EntityEnderCrystal extends Entity {
|
|
private static final DataWatcherObject<Optional<BlockPosition>> c = DataWatcher.a(EntityEnderCrystal.class, DataWatcherRegistry.m);
|
|
private static final DataWatcherObject<Boolean> 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<? extends EntityEnderCrystal> entitytypes, World world) {
|
|
super(entitytypes, world);
|
|
@@ -68,7 +75,50 @@ public class EntityEnderCrystal extends Entity {
|
|
}
|
|
}
|
|
|
|
+ // Purpur start
|
|
+ if (world.purpurConfig.phantomAttackedByCrystalRadius <= 0 || --idleCooldown > 0) {
|
|
+ return; // on cooldown
|
|
+ }
|
|
+
|
|
+ if (targetPhantom == null) {
|
|
+ for (EntityPhantom phantom : world.getEntitiesInAABB(EntityPhantom.class, getBoundingBox().grow(world.purpurConfig.phantomAttackedByCrystalRadius))) {
|
|
+ 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.indirectMagic(this, this), world.purpurConfig.phantomAttackedByCrystalDamage);
|
|
+ }
|
|
+ } 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 saveData(NBTTagCompound nbttagcompound) {
|
|
diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityPhantom.java b/src/main/java/net/minecraft/world/entity/monster/EntityPhantom.java
|
|
index 42cf3fa42b73739182d26fbb524ee5b304c799b2..daf738e8f0987aa6ab200189d7a26d166918b8fc 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/monster/EntityPhantom.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/monster/EntityPhantom.java
|
|
@@ -12,6 +12,7 @@ import net.minecraft.nbt.NBTTagCompound;
|
|
import net.minecraft.network.syncher.DataWatcher;
|
|
import net.minecraft.network.syncher.DataWatcherObject;
|
|
import net.minecraft.network.syncher.DataWatcherRegistry;
|
|
+import net.minecraft.server.level.WorldServer;
|
|
import net.minecraft.sounds.SoundCategory;
|
|
import net.minecraft.sounds.SoundEffect;
|
|
import net.minecraft.sounds.SoundEffects;
|
|
@@ -36,18 +37,23 @@ import net.minecraft.world.entity.ai.control.EntityAIBodyControl;
|
|
import net.minecraft.world.entity.ai.goal.PathfinderGoal;
|
|
import net.minecraft.world.entity.ai.targeting.PathfinderTargetCondition;
|
|
import net.minecraft.world.entity.animal.EntityCat;
|
|
+import net.minecraft.world.entity.boss.enderdragon.EntityEnderCrystal;
|
|
import net.minecraft.world.entity.player.EntityHuman;
|
|
+import net.minecraft.world.item.ItemStack;
|
|
+import net.minecraft.world.item.Items;
|
|
import net.minecraft.world.level.World;
|
|
import net.minecraft.world.level.WorldAccess;
|
|
import net.minecraft.world.level.levelgen.HeightMap;
|
|
+import net.minecraft.world.level.storage.loot.LootTableInfo;
|
|
import net.minecraft.world.phys.Vec3D;
|
|
|
|
public class EntityPhantom extends EntityFlying implements IMonster {
|
|
|
|
private static final DataWatcherObject<Integer> b = DataWatcher.a(EntityPhantom.class, DataWatcherRegistry.b);
|
|
- private Vec3D c;
|
|
- private BlockPosition d;
|
|
- private EntityPhantom.AttackPhase bo;
|
|
+ private Vec3D c; public void setHomeOffset(Vec3D offset) { this.c = offset; } public Vec3D getHomeOffset() { return this.c; } // Purpur - OBFHELPER
|
|
+ private BlockPosition d; public void setHome(BlockPosition home) { this.d = home; } public BlockPosition getHome() { return this.d; } // Purpur - OBFHELPER
|
|
+ private EntityPhantom.AttackPhase bo; public AttackPhase getAttackPhase() { return this.bo; } // Purpur - OBFHELPER
|
|
+ private Vec3D crystalPosition; // Purpur
|
|
|
|
public EntityPhantom(EntityTypes<? extends EntityPhantom> entitytypes, World world) {
|
|
super(entitytypes, world);
|
|
@@ -66,11 +72,37 @@ public class EntityPhantom extends EntityFlying implements IMonster {
|
|
|
|
@Override
|
|
protected void initPathfinder() {
|
|
- this.goalSelector.a(1, new EntityPhantom.c());
|
|
- this.goalSelector.a(2, new EntityPhantom.i());
|
|
- this.goalSelector.a(3, new EntityPhantom.e());
|
|
- this.targetSelector.a(1, new EntityPhantom.b());
|
|
+ // Purpur start
|
|
+ if (world.purpurConfig.phantomOrbitCrystalRadius > 0) {
|
|
+ this.goalSelector.a(1, new FindCrystalGoal(this));
|
|
+ this.goalSelector.a(2, new OrbitCrystalGoal(this));
|
|
+ }
|
|
+ this.goalSelector.a(3, new EntityPhantom.c()); // PickAttackGoal
|
|
+ this.goalSelector.a(4, new EntityPhantom.i()); // SweepAttackGoal
|
|
+ this.goalSelector.a(5, new EntityPhantom.e()); // OrbitPointGoal
|
|
+ this.targetSelector.a(1, new EntityPhantom.b()); // AttackPlayer Goal
|
|
+ // Purpur end
|
|
+ }
|
|
+
|
|
+ // 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 = dropItem(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
|
|
protected void initDatawatcher() {
|
|
@@ -235,6 +267,136 @@ public class EntityPhantom extends EntityFlying implements IMonster {
|
|
public void setSpawningEntity(java.util.UUID entity) { this.spawningEntity = entity; }
|
|
// Paper end
|
|
|
|
+ // Purpur start
|
|
+ class FindCrystalGoal extends PathfinderGoal {
|
|
+ private final EntityPhantom phantom;
|
|
+ private EntityEnderCrystal crystal;
|
|
+ private java.util.Comparator<EntityEnderCrystal> comparator;
|
|
+
|
|
+ FindCrystalGoal(EntityPhantom phantom) {
|
|
+ this.phantom = phantom;
|
|
+ comparator = java.util.Comparator.comparingDouble(phantom::h);
|
|
+ this.a(EnumSet.of(PathfinderGoal.Type.LOOK));
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean a() { // shouldExecute
|
|
+ double range = maxTargetRange();
|
|
+ List<EntityEnderCrystal> crystals = world.getEntitiesInAABB(EntityEnderCrystal.class, phantom.getBoundingBox().grow(range));
|
|
+ if (crystals.isEmpty()) {
|
|
+ return false;
|
|
+ }
|
|
+ crystals.sort(comparator);
|
|
+ crystal = crystals.get(0);
|
|
+ if (phantom.getDistanceSquared(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.getDistanceSquared(crystal) <= (range * range) * 2;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void c() { // startExecuting
|
|
+ phantom.crystalPosition = new Vec3D(crystal.locX(), crystal.locY() + (phantom.getRandom().nextInt(10) + 10), crystal.locZ());
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void d() { // resetTask
|
|
+ crystal = null;
|
|
+ phantom.crystalPosition = null;
|
|
+ super.d();
|
|
+ }
|
|
+
|
|
+ private double maxTargetRange() {
|
|
+ return phantom.world.purpurConfig.phantomOrbitCrystalRadius;
|
|
+ }
|
|
+
|
|
+ class DistanceComparator implements java.util.Comparator<Entity> {
|
|
+ private final Entity entity;
|
|
+
|
|
+ public DistanceComparator(Entity entity) {
|
|
+ this.entity = entity;
|
|
+ }
|
|
+
|
|
+ public int compare(Entity entity1, Entity entity2) {
|
|
+ return Double.compare(entity.getDistanceSquared(entity1), entity.getDistanceSquared(entity2));
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ class OrbitCrystalGoal extends PathfinderGoal {
|
|
+ private final EntityPhantom phantom;
|
|
+ private float offset;
|
|
+ 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.offset = phantom.random.nextFloat() * 2.0F * 3.1415927F;
|
|
+ updateOffset();
|
|
+ }
|
|
+ if (phantom.getHomeOffset().c(phantom.locX(), phantom.locY(), phantom.locZ()) < 4.0D) {
|
|
+ updateOffset();
|
|
+ }
|
|
+ if (phantom.getHomeOffset().y < phantom.locY() && !phantom.world.isEmpty((new BlockPosition(phantom)).down(1))) {
|
|
+ this.verticalChange = Math.max(1.0F, this.verticalChange);
|
|
+ updateOffset();
|
|
+ }
|
|
+ if (phantom.getHomeOffset().y > phantom.locY() && !phantom.world.isEmpty((new BlockPosition(phantom)).up(1))) {
|
|
+ this.verticalChange = Math.min(-1.0F, this.verticalChange);
|
|
+ updateOffset();
|
|
+ }
|
|
+ }
|
|
+
|
|
+ private void updateOffset() {
|
|
+ this.offset += this.direction * 15.0F * 0.017453292F;
|
|
+ phantom.setHomeOffset(phantom.crystalPosition.add(
|
|
+ this.radius * MathHelper.cos(this.offset),
|
|
+ -4.0F + this.verticalChange,
|
|
+ this.radius * MathHelper.sin(this.offset)));
|
|
+ }
|
|
+ }
|
|
+ // Purpur end
|
|
+
|
|
class b extends PathfinderGoal {
|
|
|
|
private final PathfinderTargetCondition b;
|
|
@@ -247,6 +409,7 @@ public class EntityPhantom extends EntityFlying implements IMonster {
|
|
|
|
@Override
|
|
public boolean a() {
|
|
+ if (isCirclingCrystal()) return false; // Purpur - pathfinder does not have a flag
|
|
if (this.c > 0) {
|
|
--this.c;
|
|
return false;
|
|
@@ -275,6 +438,7 @@ public class EntityPhantom extends EntityFlying implements IMonster {
|
|
|
|
@Override
|
|
public boolean b() {
|
|
+ if (isCirclingCrystal()) return false; // Purpur - pathfinder does not have a flag
|
|
EntityLiving entityliving = EntityPhantom.this.getGoalTarget();
|
|
|
|
return entityliving != null ? EntityPhantom.this.a(entityliving, PathfinderTargetCondition.a) : false;
|
|
@@ -289,6 +453,7 @@ public class EntityPhantom extends EntityFlying implements IMonster {
|
|
|
|
@Override
|
|
public boolean a() {
|
|
+ if (isCirclingCrystal()) return false; // Purpur - pathfinder does not have a flag
|
|
EntityLiving entityliving = EntityPhantom.this.getGoalTarget();
|
|
|
|
return entityliving != null ? EntityPhantom.this.a(EntityPhantom.this.getGoalTarget(), PathfinderTargetCondition.a) : false;
|
|
diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
|
|
index 1ebc8d04020aec7e36dfed5196dde9e9fe6ada0f..d5e1ca888c6fe0910f54e30b3b59af4dfde86cb3 100644
|
|
--- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
|
|
+++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
|
|
@@ -349,6 +349,15 @@ public class PurpurWorldConfig {
|
|
ironGolemCanSwim = getBoolean("mobs.iron_golem.can-swim", ironGolemCanSwim);
|
|
}
|
|
|
|
+ public double phantomAttackedByCrystalRadius = 0.0D;
|
|
+ public float phantomAttackedByCrystalDamage = 1.0F;
|
|
+ public double phantomOrbitCrystalRadius = 0.0D;
|
|
+ private void phantomSettings() {
|
|
+ phantomAttackedByCrystalRadius = getDouble("mobs.phantom.attacked-by-crystal-range", phantomAttackedByCrystalRadius);
|
|
+ phantomAttackedByCrystalDamage = (float) getDouble("mobs.phantom.attacked-by-crystal-damage", phantomAttackedByCrystalDamage);
|
|
+ phantomOrbitCrystalRadius = getDouble("mobs.phantom.orbit-crystal-radius", phantomOrbitCrystalRadius);
|
|
+ }
|
|
+
|
|
public boolean pigGiveSaddleBack = false;
|
|
private void pigSettings() {
|
|
pigGiveSaddleBack = getBoolean("mobs.pig.give-saddle-back", pigGiveSaddleBack);
|