-
-
Notifications
You must be signed in to change notification settings - Fork 345
/
0010-Phantoms-attracted-to-crystals-and-crystals-shoot-ph.patch
397 lines (371 loc) · 17.4 KB
/
0010-Phantoms-attracted-to-crystals-and-crystals-shoot-ph.patch
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
From bda77b04fc4d1e17807745254ff5304bb39d304f 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
---
.../net/minecraft/server/DamageSource.java | 1 +
.../java/net/minecraft/server/Entity.java | 8 +-
.../minecraft/server/EntityEnderCrystal.java | 49 +++++
.../net/minecraft/server/EntityPhantom.java | 181 +++++++++++++++++-
.../net/minecraft/server/IEntityAccess.java | 1 +
.../java/net/pl3x/purpur/PurpurConfig.java | 9 +
6 files changed, 235 insertions(+), 14 deletions(-)
diff --git a/src/main/java/net/minecraft/server/DamageSource.java b/src/main/java/net/minecraft/server/DamageSource.java
index 730a15f332..31454349a2 100644
--- a/src/main/java/net/minecraft/server/DamageSource.java
+++ b/src/main/java/net/minecraft/server/DamageSource.java
@@ -77,6 +77,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/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java
index 40ab9daade..dd787b7b65 100644
--- a/src/main/java/net/minecraft/server/Entity.java
+++ b/src/main/java/net/minecraft/server/Entity.java
@@ -1400,6 +1400,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke
return d3 * d3 + d4 * d4 + d5 * d5;
}
+ public double getDistanceSq(Entity entity) { return this.h(entity); } // Purpur - OBFHELPER
public double h(Entity entity) {
return this.c(entity.getPositionVector());
}
@@ -1919,14 +1920,13 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke
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);
}
@Nullable public final EntityItem dropItem(ItemStack itemstack, float offset) { return this.a(itemstack, offset); } // Paper - OBFHELPER
- @Nullable
- public EntityItem a(ItemStack itemstack, float f) {
+ @Nullable public EntityItem a(ItemStack itemstack, float f) {
if (itemstack.isEmpty()) {
return null;
} else if (this.world.isClientSide) {
diff --git a/src/main/java/net/minecraft/server/EntityEnderCrystal.java b/src/main/java/net/minecraft/server/EntityEnderCrystal.java
index 801552fc61..9c7f7fee85 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<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);
@@ -54,7 +60,50 @@ public class EntityEnderCrystal extends Entity {
}
}
+ // Purpur start
+ if (net.pl3x.purpur.PurpurConfig.crystalsAttackPhantomsRadius <= 0 || --idleCooldown > 0) {
+ return; // on cooldown
+ }
+
+ if (targetPhantom == null) {
+ for (EntityPhantom phantom : world.getEntitiesByClass(EntityPhantom.class, getBoundingBox().grow(net.pl3x.purpur.PurpurConfig.crystalsAttackPhantomsRadius))) {
+ 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), net.pl3x.purpur.PurpurConfig.crystalsAttackPhantomDamage);
+ }
+ } 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 e5d032d02b..7bc7b33665 100644
--- a/src/main/java/net/minecraft/server/EntityPhantom.java
+++ b/src/main/java/net/minecraft/server/EntityPhantom.java
@@ -8,9 +8,10 @@ import javax.annotation.Nullable;
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 bz;
+ 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 bz; public AttackPhase getAttackPhase() { return this.bz; } // Purpur - OBFHELPER
+ private BlockPosition crystalPosition; // Purpur
public EntityPhantom(EntityTypes<? extends EntityPhantom> entitytypes, World world) {
super(entitytypes, world);
@@ -29,10 +30,16 @@ 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 (net.pl3x.purpur.PurpurConfig.phantomsOrbitCrystalsRadius > 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()); // AttackPlayerGoal
+ // Purpur end
}
@Override
@@ -114,6 +121,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 = 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
public GroupDataEntity prepare(GeneratorAccess generatoraccess, DifficultyDamageScaler difficultydamagescaler, EnumMobSpawn enummobspawn, @Nullable GroupDataEntity groupdataentity, @Nullable NBTTagCompound nbttagcompound) {
this.d = (new BlockPosition(this)).up(5);
@@ -202,6 +229,135 @@ public class EntityPhantom extends EntityFlying implements IMonster {
}
// 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);
+ }
+
+ @Override
+ public boolean a() { // shouldExecute
+ double range = maxTargetRange();
+ List<EntityEnderCrystal> crystals = world.getEntitiesByClass(EntityEnderCrystal.class, phantom.getBoundingBox().grow(range));
+ if (crystals.isEmpty()) {
+ return false;
+ }
+ crystals.sort(comparator);
+ crystal = crystals.get(0);
+ if (phantom.getDistanceSq(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.getDistanceSq(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() {
+ return net.pl3x.purpur.PurpurConfig.phantomsOrbitCrystalsRadius;
+ }
+
+ 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.getDistanceSq(entity1), entity.getDistanceSq(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(new Vec3D(phantom.crystalPosition).add(
+ (double) (this.radius * MathHelper.cos(this.offset)),
+ (double) (-4.0F + this.verticalChange),
+ (double) (this.radius * MathHelper.sin(this.offset))));
+ }
+ }
+ // Purpur end
+
class b extends PathfinderGoal {
private final PathfinderTargetCondition b;
@@ -259,7 +415,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 +461,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.getAttackPhase() == 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 +540,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.getAttackPhase() == EntityPhantom.AttackPhase.CIRCLE; // Purpur
}
@Override
diff --git a/src/main/java/net/minecraft/server/IEntityAccess.java b/src/main/java/net/minecraft/server/IEntityAccess.java
index dca18afdbb..9aaa75e959 100644
--- a/src/main/java/net/minecraft/server/IEntityAccess.java
+++ b/src/main/java/net/minecraft/server/IEntityAccess.java
@@ -34,6 +34,7 @@ public interface IEntityAccess {
});
}
+ default <T extends Entity> List<T> getEntitiesByClass(Class<? extends T> oclass, AxisAlignedBB axisalignedbb) { return a(oclass, axisalignedbb); } // Purpur - OBFHELPER
default <T extends Entity> List<T> a(Class<? extends T> oclass, AxisAlignedBB axisalignedbb) {
return this.a(oclass, axisalignedbb, IEntitySelector.f);
}
diff --git a/src/main/java/net/pl3x/purpur/PurpurConfig.java b/src/main/java/net/pl3x/purpur/PurpurConfig.java
index 37bab6180c..0bfcef2d38 100644
--- a/src/main/java/net/pl3x/purpur/PurpurConfig.java
+++ b/src/main/java/net/pl3x/purpur/PurpurConfig.java
@@ -136,6 +136,15 @@ public class PurpurConfig {
feedMushroomsToCows = getInt("settings.mobs.cow.feed-mushrooms-for-mooshroom", feedMushroomsToCows);
}
+ public static double crystalsAttackPhantomsRadius = 0.0D;
+ public static float crystalsAttackPhantomDamage = 1.0F;
+ public static double phantomsOrbitCrystalsRadius = 0.0D;
+ private static void phantomSettings() {
+ crystalsAttackPhantomsRadius = getDouble("settings.mobs.phantom.crystals-attack-range", crystalsAttackPhantomsRadius);
+ crystalsAttackPhantomDamage = (float) getDouble("settings.mobs.phantom.crystals-attack-damage", crystalsAttackPhantomDamage);
+ phantomsOrbitCrystalsRadius = getDouble("settings.mobs.phantom.orbit-crystal-radius", phantomsOrbitCrystalsRadius);
+ }
+
public static boolean snowmanDropsPumpkin = false;
public static boolean snowmanPumpkinPutBack = false;
private static void snowmansSettings() {
--
2.20.1