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
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com>
Date: Tue, 22 Jun 2021 23:41:11 -0400
Subject: [PATCH] More Projectile API
== AT ==
public net.minecraft.world.entity.projectile.FishingHook timeUntilLured
public net.minecraft.world.entity.projectile.FishingHook fishAngle
public net.minecraft.world.entity.projectile.ShulkerBullet targetDeltaX
public net.minecraft.world.entity.projectile.ShulkerBullet targetDeltaY
public net.minecraft.world.entity.projectile.ShulkerBullet targetDeltaZ
public net.minecraft.world.entity.projectile.ShulkerBullet currentMoveDirection
public net.minecraft.world.entity.projectile.ShulkerBullet flightSteps
public net.minecraft.world.entity.projectile.AbstractArrow soundEvent
public net.minecraft.world.entity.projectile.ThrownTrident dealtDamage
public net.minecraft.world.entity.projectile.Arrow NO_EFFECT_COLOR
public net.minecraft.world.entity.projectile.Projectile hasBeenShot
public net.minecraft.world.entity.projectile.Projectile leftOwner
public net.minecraft.world.entity.projectile.Projectile preOnHit(Lnet/minecraft/world/phys/HitResult;)V
public net.minecraft.world.entity.projectile.Projectile canHitEntity(Lnet/minecraft/world/entity/Entity;)Z
public net.minecraft.world.entity.projectile.FireworkRocketEntity getDefaultItem()Lnet/minecraft/world/item/ItemStack;
Co-authored-by: Nassim Jahnke <nassim@njahnke.dev>
Co-authored-by: SoSeDiK <mrsosedik@gmail.com>
diff --git a/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java b/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java
index 7d557c7ec6fb1763395f4920a170bd4e4ba6747f..e603307871b623ce437f4b1b68ab306fbdd9919d 100644
--- a/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java
+++ b/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java
@@ -413,13 +413,18 @@ public class FishingHook extends Projectile {
}
} else {
// CraftBukkit start - logic to modify fishing wait time
- this.timeUntilLured = Mth.nextInt(this.random, this.minWaitTime, this.maxWaitTime);
- this.timeUntilLured -= (this.applyLure) ? (this.lureSpeed * 20 * 5 >= this.maxWaitTime ? this.timeUntilLured - 1 : this.lureSpeed * 20 * 5) : 0; // Paper - Fix Lure infinite loop
+ resetTimeUntilLured(); // Paper - more projectile api - extract time until lured reset logic
// CraftBukkit end
}
}
}
+ // Paper start - more projectile api - extract time until lured reset logic
+ public void resetTimeUntilLured() {
+ this.timeUntilLured = Mth.nextInt(this.random, this.minWaitTime, this.maxWaitTime);
+ this.timeUntilLured -= (this.applyLure) ? (this.lureSpeed * 20 * 5 >= this.maxWaitTime ? this.timeUntilLured - 1 : this.lureSpeed * 20 * 5) : 0; // Paper - Fix Lure infinite loop
+ }
+ // Paper end - more projectile api - extract time until lured reset logic
public boolean calculateOpenWater(BlockPos pos) {
FishingHook.OpenWaterType entityfishinghook_waterposition = FishingHook.OpenWaterType.INVALID;
diff --git a/src/main/java/net/minecraft/world/entity/projectile/Projectile.java b/src/main/java/net/minecraft/world/entity/projectile/Projectile.java
index 40348e45b02be9a0b397a883940a476fb6738ef4..ccb7aa341e3087255bce1f6fb953d33584147fd3 100644
--- a/src/main/java/net/minecraft/world/entity/projectile/Projectile.java
+++ b/src/main/java/net/minecraft/world/entity/projectile/Projectile.java
@@ -180,7 +180,7 @@ public abstract class Projectile extends Entity implements TraceableEntity {
}
// CraftBukkit start - call projectile hit event
- protected ProjectileDeflection preHitTargetOrDeflectSelf(HitResult movingobjectposition) {
+ public ProjectileDeflection preHitTargetOrDeflectSelf(HitResult movingobjectposition) { // Paper - protected -> public
org.bukkit.event.entity.ProjectileHitEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callProjectileHitEvent(this, movingobjectposition);
this.hitCancelled = event != null && event.isCancelled();
if (movingobjectposition.getType() == HitResult.Type.BLOCK || !this.hitCancelled) {
diff --git a/src/main/java/net/minecraft/world/entity/projectile/ThrownPotion.java b/src/main/java/net/minecraft/world/entity/projectile/ThrownPotion.java
index bf627d66310f201172d3cd3ea12f1d321cd3cd62..5adaeb59f7733809f1cf6b52031292c9611a3a86 100644
--- a/src/main/java/net/minecraft/world/entity/projectile/ThrownPotion.java
+++ b/src/main/java/net/minecraft/world/entity/projectile/ThrownPotion.java
@@ -100,6 +100,11 @@ public class ThrownPotion extends ThrowableItemProjectile implements ItemSupplie
@Override
protected void onHit(HitResult hitResult) {
super.onHit(hitResult);
+ // Paper start - More projectile API
+ this.splash(hitResult);
+ }
+ public void splash(@Nullable HitResult hitResult) {
+ // Paper end - More projectile API
if (!this.level().isClientSide) {
ItemStack itemstack = this.getItem();
PotionContents potioncontents = (PotionContents) itemstack.getOrDefault(DataComponents.POTION_CONTENTS, PotionContents.EMPTY);
@@ -111,7 +116,7 @@ public class ThrownPotion extends ThrowableItemProjectile implements ItemSupplie
if (this.isLingering()) {
showParticles = this.makeAreaOfEffectCloud(potioncontents, hitResult); // CraftBukkit - Pass MovingObjectPosition // Paper
} else {
- showParticles = this.applySplash(potioncontents.getAllEffects(), hitResult.getType() == HitResult.Type.ENTITY ? ((EntityHitResult) hitResult).getEntity() : null, hitResult); // CraftBukkit - Pass MovingObjectPosition // Paper
+ showParticles = this.applySplash(potioncontents.getAllEffects(), hitResult != null && hitResult.getType() == HitResult.Type.ENTITY ? ((EntityHitResult) hitResult).getEntity() : null, hitResult); // CraftBukkit - Pass MovingObjectPosition // Paper - More projectile API
}
}
@@ -173,7 +178,7 @@ public class ThrownPotion extends ThrowableItemProjectile implements ItemSupplie
}
- private boolean applySplash(Iterable<MobEffectInstance> iterable, @Nullable Entity entity, HitResult position) { // CraftBukkit - Pass MovingObjectPosition // Paper - Fix potions splash events
+ private boolean applySplash(Iterable<MobEffectInstance> iterable, @Nullable Entity entity, @Nullable HitResult position) { // CraftBukkit - Pass MovingObjectPosition // Paper - Fix potions splash events & More projectile API
AABB axisalignedbb = this.getBoundingBox().inflate(4.0D, 2.0D, 4.0D);
List<net.minecraft.world.entity.LivingEntity> list = this.level().getEntitiesOfClass(net.minecraft.world.entity.LivingEntity.class, axisalignedbb);
Map<LivingEntity, Double> affected = new HashMap<LivingEntity, Double>(); // CraftBukkit
@@ -251,7 +256,7 @@ public class ThrownPotion extends ThrowableItemProjectile implements ItemSupplie
}
- private boolean makeAreaOfEffectCloud(PotionContents potioncontents, HitResult position) { // CraftBukkit - Pass MovingObjectPosition
+ private boolean makeAreaOfEffectCloud(PotionContents potioncontents, @Nullable HitResult position) { // CraftBukkit - Pass MovingObjectPosition // Paper - More projectile API
AreaEffectCloud entityareaeffectcloud = new AreaEffectCloud(this.level(), this.getX(), this.getY(), this.getZ());
Entity entity = this.getOwner();
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/AbstractProjectile.java b/src/main/java/org/bukkit/craftbukkit/entity/AbstractProjectile.java
index 91c2d0b40d3fca86938cd454e1415a4eea3df7c7..de4fb2654c7895cfd83ad694455ee56cb708c2f2 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/AbstractProjectile.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/AbstractProjectile.java
@@ -17,4 +17,65 @@ public abstract class AbstractProjectile extends CraftEntity implements Projecti
@Override
public void setBounce(boolean doesBounce) {}
+ // Paper start - More projectile API
+ @Override
+ public boolean hasLeftShooter() {
+ return this.getHandle().leftOwner;
+ }
+
+ @Override
+ public void setHasLeftShooter(boolean leftShooter) {
+ this.getHandle().leftOwner = leftShooter;
+ }
+
+ @Override
+ public boolean hasBeenShot() {
+ return this.getHandle().hasBeenShot;
+ }
+
+ @Override
+ public void setHasBeenShot(boolean beenShot) {
+ this.getHandle().hasBeenShot = beenShot;
+ }
+
+ @Override
+ public boolean canHitEntity(org.bukkit.entity.Entity entity) {
+ return this.getHandle().canHitEntity(((CraftEntity) entity).getHandle());
+ }
+
+ @Override
+ public void hitEntity(org.bukkit.entity.Entity entity) {
+ this.getHandle().preHitTargetOrDeflectSelf(new net.minecraft.world.phys.EntityHitResult(((CraftEntity) entity).getHandle()));
+ }
+
+ @Override
+ public void hitEntity(org.bukkit.entity.Entity entity, org.bukkit.util.Vector vector) {
+ this.getHandle().preHitTargetOrDeflectSelf(new net.minecraft.world.phys.EntityHitResult(((CraftEntity) entity).getHandle(), new net.minecraft.world.phys.Vec3(vector.getX(), vector.getY(), vector.getZ())));
+ }
+
+ @Override
+ public net.minecraft.world.entity.projectile.Projectile getHandle() {
+ return (net.minecraft.world.entity.projectile.Projectile) entity;
+ }
+
+ @Override
+ public final org.bukkit.projectiles.ProjectileSource getShooter() {
+ return this.getHandle().projectileSource;
+ }
+
+ @Override
+ public final void setShooter(org.bukkit.projectiles.ProjectileSource shooter) {
+ if (shooter instanceof CraftEntity craftEntity) {
+ this.getHandle().setOwner(craftEntity.getHandle());
+ } else {
+ this.getHandle().setOwner(null);
+ }
+ this.getHandle().projectileSource = shooter;
+ }
+
+ @Override
+ public java.util.UUID getOwnerUniqueId() {
+ return this.getHandle().ownerUUID;
+ }
+ // Paper end - More projectile API
}
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractArrow.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractArrow.java
index 98f46fadd60ea688fefa8d83dbd6fe9b61b6a96f..0cc1cdf91deb07ebb437ef5e61d149b2c109877f 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractArrow.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractArrow.java
@@ -60,20 +60,7 @@ public class CraftAbstractArrow extends AbstractProjectile implements AbstractAr
this.getHandle().setCritArrow(critical);
}
- @Override
- public ProjectileSource getShooter() {
- return this.getHandle().projectileSource;
- }
-
- @Override
- public void setShooter(ProjectileSource shooter) {
- if (shooter instanceof Entity) {
- this.getHandle().setOwner(((CraftEntity) shooter).getHandle());
- } else {
- this.getHandle().setOwner(null);
- }
- this.getHandle().projectileSource = shooter;
- }
+ // Paper - moved to AbstractProjectile
@Override
public boolean isInBlock() {
@@ -140,4 +127,31 @@ public class CraftAbstractArrow extends AbstractProjectile implements AbstractAr
public String toString() {
return "CraftArrow";
}
+
+ // Paper start
+ @Override
+ public org.bukkit.craftbukkit.inventory.CraftItemStack getItemStack() {
+ return org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(this.getHandle().getPickupItem());
+ }
+
+ @Override
+ public void setLifetimeTicks(int ticks) {
+ this.getHandle().life = ticks;
+ }
+
+ @Override
+ public int getLifetimeTicks() {
+ return this.getHandle().life;
+ }
+
+ @Override
+ public org.bukkit.Sound getHitSound() {
+ return org.bukkit.craftbukkit.CraftSound.minecraftToBukkit(this.getHandle().soundEvent);
+ }
+
+ @Override
+ public void setHitSound(org.bukkit.Sound sound) {
+ this.getHandle().setSoundEvent(org.bukkit.craftbukkit.CraftSound.bukkitToMinecraft(sound));
+ }
+ // Paper end
}
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftAreaEffectCloud.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftAreaEffectCloud.java
index 81f5e1d866128af8fb2acc13aca715580fdf9886..88f2a9f310f30a08893f3fa68af13a54cf72fa7f 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftAreaEffectCloud.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftAreaEffectCloud.java
@@ -125,7 +125,7 @@ public class CraftAreaEffectCloud extends CraftEntity implements AreaEffectCloud
@Override
public Color getColor() {
- return Color.fromRGB(this.getHandle().potionContents.getColor());
+ return Color.fromRGB(this.getHandle().potionContents.getColor() & 0x00FFFFFF); // Paper - skip alpha channel
}
@Override
@@ -143,7 +143,7 @@ public class CraftAreaEffectCloud extends CraftEntity implements AreaEffectCloud
this.removeCustomEffect(effect.getType());
}
this.getHandle().addEffect(CraftPotionUtil.fromBukkit(effect));
- this.getHandle().updateColor();
+ // this.getHandle().updateColor(); // Paper - already done above
return true;
}
@@ -151,7 +151,7 @@ public class CraftAreaEffectCloud extends CraftEntity implements AreaEffectCloud
public void clearCustomEffects() {
PotionContents old = this.getHandle().potionContents;
this.getHandle().setPotionContents(new PotionContents(old.potion(), old.customColor(), List.of()));
- this.getHandle().updateColor();
+ // this.getHandle().updateColor(); // Paper - already done above
}
@Override
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftArrow.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftArrow.java
index 5232fbef0d014edd32a5d18d4a1500ab215313f5..071be344c3265a0cd52b31ffbb02ff7a70bdf231 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftArrow.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftArrow.java
@@ -43,7 +43,7 @@ public class CraftArrow extends CraftAbstractArrow implements Arrow {
this.removeCustomEffect(effect.getType());
}
this.getHandle().addEffect(CraftPotionUtil.fromBukkit(effect));
- this.getHandle().updateColor();
+ // this.getHandle().updateColor(); // Paper - already done above
return true;
}
@@ -51,7 +51,7 @@ public class CraftArrow extends CraftAbstractArrow implements Arrow {
public void clearCustomEffects() {
PotionContents old = this.getHandle().getPotionContents();
this.getHandle().setPotionContents(new PotionContents(old.potion(), old.customColor(), List.of()));
- this.getHandle().updateColor();
+ // this.getHandle().updateColor(); // Paper - already done above
}
@Override
@@ -117,16 +117,17 @@ public class CraftArrow extends CraftAbstractArrow implements Arrow {
@Override
public void setColor(Color color) {
- int colorRGB = (color == null) ? -1 : color.asRGB();
+ int colorRGB = (color == null) ? net.minecraft.world.entity.projectile.Arrow.NO_EFFECT_COLOR : color.asARGB(); // Paper
PotionContents old = this.getHandle().getPotionContents();
this.getHandle().setPotionContents(new PotionContents(old.potion(), Optional.of(colorRGB), old.customEffects()));
}
@Override
public Color getColor() {
- if (this.getHandle().getColor() <= -1) {
+ int color = this.getHandle().getColor(); // Paper
+ if (color == net.minecraft.world.entity.projectile.Arrow.NO_EFFECT_COLOR) { // Paper
return null;
}
- return Color.fromRGB(this.getHandle().getColor());
+ return Color.fromARGB(color); // Paper
}
}
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntityTypes.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntityTypes.java
index 7ba6302ecb72fa6e523054e7e3223d79eedf6589..907904da7f89e8e5e5cfab80977f04af3fdf17c7 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntityTypes.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntityTypes.java
@@ -388,7 +388,7 @@ public final class CraftEntityTypes {
BlockPos pos = BlockPos.containing(spawnData.x(), spawnData.y(), spawnData.z());
return new FallingBlockEntity(spawnData.minecraftWorld(), spawnData.x(), spawnData.y(), spawnData.z(), spawnData.world().getBlockState(pos)); // Paper - create falling block entities correctly
}));
- register(new EntityTypeData<>(EntityType.FIREWORK_ROCKET, Firework.class, CraftFirework::new, spawnData -> new FireworkRocketEntity(spawnData.minecraftWorld(), spawnData.x(), spawnData.y(), spawnData.z(), net.minecraft.world.item.ItemStack.EMPTY)));
+ register(new EntityTypeData<>(EntityType.FIREWORK_ROCKET, Firework.class, CraftFirework::new, spawnData -> new FireworkRocketEntity(spawnData.minecraftWorld(), spawnData.x(), spawnData.y(), spawnData.z(), FireworkRocketEntity.getDefaultItem()))); // Paper - pass correct default to rocket for data storage
register(new EntityTypeData<>(EntityType.EVOKER_FANGS, EvokerFangs.class, CraftEvokerFangs::new, spawnData -> new net.minecraft.world.entity.projectile.EvokerFangs(spawnData.minecraftWorld(), spawnData.x(), spawnData.y(), spawnData.z(), (float) Math.toRadians(spawnData.yaw()), 0, null)));
register(new EntityTypeData<>(EntityType.COMMAND_BLOCK_MINECART, CommandMinecart.class, CraftMinecartCommand::new, spawnData -> new MinecartCommandBlock(spawnData.minecraftWorld(), spawnData.x(), spawnData.y(), spawnData.z())));
register(new EntityTypeData<>(EntityType.MINECART, RideableMinecart.class, CraftMinecartRideable::new, spawnData -> new Minecart(spawnData.minecraftWorld(), spawnData.x(), spawnData.y(), spawnData.z())));
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftFireball.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftFireball.java
index b0a02c9ca4349ab56ceceae8b78559e20a9b0af5..297b7e592caa2a05e1fb18a3ad22a91ae7621f5d 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftFireball.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftFireball.java
@@ -33,20 +33,7 @@ public class CraftFireball extends AbstractProjectile implements Fireball {
this.getHandle().bukkitYield = yield;
}
- @Override
- public ProjectileSource getShooter() {
- return this.getHandle().projectileSource;
- }
-
- @Override
- public void setShooter(ProjectileSource shooter) {
- if (shooter instanceof CraftLivingEntity) {
- this.getHandle().setOwner(((CraftLivingEntity) shooter).getHandle());
- } else {
- this.getHandle().setOwner(null);
- }
- this.getHandle().projectileSource = shooter;
- }
+ // Paper - moved to AbstractProjectile
@Override
public Vector getDirection() {
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftFirework.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftFirework.java
index c9e15a9d82dee935293b2e7e233f5b9b2d822448..3c31ff72f3e77ee0d9231fec5f15267c56799a7c 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftFirework.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftFirework.java
@@ -15,24 +15,26 @@ import org.bukkit.inventory.meta.FireworkMeta;
public class CraftFirework extends CraftProjectile implements Firework {
private final Random random = new Random();
- private final CraftItemStack item;
+ //private CraftItemStack item; // Paper - Remove usage, not accurate representation of current item.
public CraftFirework(CraftServer server, FireworkRocketEntity entity) {
super(server, entity);
- ItemStack item = this.getHandle().getEntityData().get(FireworkRocketEntity.DATA_ID_FIREWORKS_ITEM);
-
- if (item.isEmpty()) {
- item = new ItemStack(Items.FIREWORK_ROCKET);
- this.getHandle().getEntityData().set(FireworkRocketEntity.DATA_ID_FIREWORKS_ITEM, item);
- }
-
- this.item = CraftItemStack.asCraftMirror(item);
-
- // Ensure the item is a firework...
- if (this.item.getType() != Material.FIREWORK_ROCKET) {
- this.item.setType(Material.FIREWORK_ROCKET);
- }
+ // Paper start - Expose firework item directly
+// ItemStack item = this.getHandle().getEntityData().get(FireworkRocketEntity.DATA_ID_FIREWORKS_ITEM);
+//
+// if (item.isEmpty()) {
+// item = new ItemStack(Items.FIREWORK_ROCKET);
+// this.getHandle().getEntityData().set(FireworkRocketEntity.DATA_ID_FIREWORKS_ITEM, item);
+// }
+//
+// this.item = CraftItemStack.asCraftMirror(item);
+//
+// // Ensure the item is a firework...
+// if (this.item.getType() != Material.FIREWORK_ROCKET) {
+// this.item.setType(Material.FIREWORK_ROCKET);
+// }
+ // Paper end - Expose firework item directly
}
@Override
@@ -47,12 +49,12 @@ public class CraftFirework extends CraftProjectile implements Firework {
@Override
public FireworkMeta getFireworkMeta() {
- return (FireworkMeta) this.item.getItemMeta();
+ return (FireworkMeta) CraftItemStack.getItemMeta(this.getHandle().getEntityData().get(FireworkRocketEntity.DATA_ID_FIREWORKS_ITEM), Material.FIREWORK_ROCKET); // Paper - Expose firework item directly
}
@Override
public void setFireworkMeta(FireworkMeta meta) {
- this.item.setItemMeta(meta);
+ applyFireworkEffect(meta); // Paper - Expose firework item directly
// Copied from EntityFireworks constructor, update firework lifetime/power
this.getHandle().lifetime = 10 * (1 + meta.getPower()) + this.random.nextInt(6) + this.random.nextInt(7);
@@ -136,4 +138,46 @@ public class CraftFirework extends CraftProjectile implements Firework {
return getHandle().spawningEntity;
}
// Paper end
+ // Paper start - Expose firework item directly + manually setting flight
+ @Override
+ public org.bukkit.inventory.ItemStack getItem() {
+ return CraftItemStack.asBukkitCopy(this.getHandle().getItem());
+ }
+
+ @Override
+ public void setItem(org.bukkit.inventory.ItemStack itemStack) {
+ FireworkMeta meta = getFireworkMeta();
+ ItemStack nmsItem = itemStack == null ? FireworkRocketEntity.getDefaultItem() : CraftItemStack.asNMSCopy(itemStack);
+ this.getHandle().getEntityData().set(FireworkRocketEntity.DATA_ID_FIREWORKS_ITEM, nmsItem);
+
+ applyFireworkEffect(meta);
+ }
+
+ @Override
+ public int getTicksFlown() {
+ return this.getHandle().life;
+ }
+
+ @Override
+ public void setTicksFlown(int ticks) {
+ this.getHandle().life = ticks;
+ }
+
+ @Override
+ public int getTicksToDetonate() {
+ return this.getHandle().lifetime;
+ }
+
+ @Override
+ public void setTicksToDetonate(int ticks) {
+ this.getHandle().lifetime = ticks;
+ }
+
+ void applyFireworkEffect(FireworkMeta meta) {
+ ItemStack item = this.getHandle().getItem();
+ CraftItemStack.applyMetaToItem(item, meta);
+
+ this.getHandle().getEntityData().set(FireworkRocketEntity.DATA_ID_FIREWORKS_ITEM, item);
+ }
+ // Paper end - Expose firework item directly + manually setting flight
}
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftFishHook.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftFishHook.java
index 6e2f91423371ead9890095cf4b1e2299c4dcba28..9d8f4b7176e60180565e3134a14ecf19060f2621 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftFishHook.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftFishHook.java
@@ -196,4 +196,42 @@ public class CraftFishHook extends CraftProjectile implements FishHook {
public HookState getState() {
return HookState.values()[this.getHandle().currentState.ordinal()];
}
+ // Paper start - More FishHook API
+ @Override
+ public int getWaitTime() {
+ return this.getHandle().timeUntilLured;
+ }
+
+ @Override
+ public void setWaitTime(int ticks) {
+ this.getHandle().timeUntilLured = ticks;
+ }
+
+ @Override
+ public int getTimeUntilBite() {
+ return this.getHandle().timeUntilHooked;
+ }
+
+ @Override
+ public void setTimeUntilBite(final int ticks) {
+ com.google.common.base.Preconditions.checkArgument(ticks >= 1, "Cannot set time until bite to less than 1 (%s<1)", ticks);
+ final FishingHook hook = this.getHandle();
+
+ // Reset the fish angle hook only when this call "enters" the fish into the lure stage.
+ final boolean alreadyInLuringPhase = hook.timeUntilHooked > 0 && hook.timeUntilLured <= 0;
+ if (!alreadyInLuringPhase) {
+ hook.fishAngle = net.minecraft.util.Mth.nextFloat(hook.random, hook.minLureAngle, hook.maxLureAngle);
+ hook.timeUntilLured = 0;
+ }
+
+ hook.timeUntilHooked = ticks;
+ }
+
+ @Override
+ public void resetFishingState() {
+ final FishingHook hook = this.getHandle();
+ hook.resetTimeUntilLured();
+ hook.timeUntilHooked = 0; // Reset time until hooked, will be repopulated once lured time is ticked down.
+ }
+ // Paper end
}
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
index 00cac0c83897221fd4a83dcee884db751321af2e..88cd49128a19efee6bf20dcfdcfda4b9bd5e4808 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
@@ -647,7 +647,7 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity {
} else if (Firework.class.isAssignableFrom(projectile)) {
Location location = this.getEyeLocation();
- launch = new FireworkRocketEntity(world, net.minecraft.world.item.ItemStack.EMPTY, this.getHandle());
+ launch = new FireworkRocketEntity(world, FireworkRocketEntity.getDefaultItem(), this.getHandle()); // Paper - pass correct default to rocket for data storage
launch.moveTo(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch());
}
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLlamaSpit.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLlamaSpit.java
index 70cbc6c668c60e9d608ca7013b72f9b916c05c2d..47633f05b4fab1dcabc2117e7645fe6d6949622a 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLlamaSpit.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLlamaSpit.java
@@ -20,13 +20,5 @@ public class CraftLlamaSpit extends AbstractProjectile implements LlamaSpit {
return "CraftLlamaSpit";
}
- @Override
- public ProjectileSource getShooter() {
- return (this.getHandle().getOwner() != null) ? (ProjectileSource) this.getHandle().getOwner().getBukkitEntity() : null;
- }
-
- @Override
- public void setShooter(ProjectileSource source) {
- this.getHandle().setOwner((source != null) ? ((CraftLivingEntity) source).getHandle() : null);
- }
+ // Paper - moved to AbstractProjectile
}
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftProjectile.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftProjectile.java
index 696fdfa723aa896a67946f862d7c6890f7f7ab17..4f1fa7dec78970bdfc184d3c1f1632dc9d75a574 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftProjectile.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftProjectile.java
@@ -10,20 +10,7 @@ public abstract class CraftProjectile extends AbstractProjectile implements Proj
super(server, entity);
}
- @Override
- public ProjectileSource getShooter() {
- return this.getHandle().projectileSource;
- }
-
- @Override
- public void setShooter(ProjectileSource shooter) {
- if (shooter instanceof CraftLivingEntity) {
- this.getHandle().setOwner((LivingEntity) ((CraftLivingEntity) shooter).entity);
- } else {
- this.getHandle().setOwner(null);
- }
- this.getHandle().projectileSource = shooter;
- }
+ // Paper - moved to AbstractProjectile
@Override
public net.minecraft.world.entity.projectile.Projectile getHandle() {
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftShulkerBullet.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftShulkerBullet.java
index d685d09cae5f862c0004f148298c800736d2139e..636c4481e3afdf20197e502cf221f5d34d18f101 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftShulkerBullet.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftShulkerBullet.java
@@ -12,20 +12,7 @@ public class CraftShulkerBullet extends AbstractProjectile implements ShulkerBul
super(server, entity);
}
- @Override
- public ProjectileSource getShooter() {
- return this.getHandle().projectileSource;
- }
-
- @Override
- public void setShooter(ProjectileSource shooter) {
- if (shooter instanceof Entity) {
- this.getHandle().setOwner(((CraftEntity) shooter).getHandle());
- } else {
- this.getHandle().setOwner(null);
- }
- this.getHandle().projectileSource = shooter;
- }
+ // Paper - moved to AbstractProjectile
@Override
public org.bukkit.entity.Entity getTarget() {
@@ -39,6 +26,40 @@ public class CraftShulkerBullet extends AbstractProjectile implements ShulkerBul
this.getHandle().setTarget(target == null ? null : ((CraftEntity) target).getHandle());
}
+ @Override
+ public org.bukkit.util.Vector getTargetDelta() {
+ net.minecraft.world.entity.projectile.ShulkerBullet bullet = this.getHandle();
+ return new org.bukkit.util.Vector(bullet.targetDeltaX, bullet.targetDeltaY, bullet.targetDeltaZ);
+ }
+
+ @Override
+ public void setTargetDelta(org.bukkit.util.Vector vector) {
+ net.minecraft.world.entity.projectile.ShulkerBullet bullet = this.getHandle();
+ bullet.targetDeltaX = vector.getX();
+ bullet.targetDeltaY = vector.getY();
+ bullet.targetDeltaZ = vector.getZ();
+ }
+
+ @Override
+ public org.bukkit.block.BlockFace getCurrentMovementDirection() {
+ return org.bukkit.craftbukkit.block.CraftBlock.notchToBlockFace(this.getHandle().currentMoveDirection);
+ }
+
+ @Override
+ public void setCurrentMovementDirection(org.bukkit.block.BlockFace movementDirection) {
+ this.getHandle().currentMoveDirection = org.bukkit.craftbukkit.block.CraftBlock.blockFaceToNotch(movementDirection);
+ }
+
+ @Override
+ public int getFlightSteps() {
+ return this.getHandle().flightSteps;
+ }
+
+ @Override
+ public void setFlightSteps(int steps) {
+ this.getHandle().flightSteps = steps;
+ }
+
@Override
public String toString() {
return "CraftShulkerBullet";
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftThrownPotion.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftThrownPotion.java
index d67a80161b3e7c1fe02a6ed9d341c00dc7c2847a..408a0a0433b97d7f97d758fd1dfa7975dbf8eccd 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftThrownPotion.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftThrownPotion.java
@@ -36,11 +36,31 @@ public class CraftThrownPotion extends CraftThrowableProjectile implements Throw
@Override
public void setItem(ItemStack item) {
Preconditions.checkArgument(item != null, "ItemStack cannot be null");
- Preconditions.checkArgument(item.getType() == Material.LINGERING_POTION || item.getType() == Material.SPLASH_POTION, "ItemStack material must be Material.LINGERING_POTION or Material.SPLASH_POTION but was Material.%s", item.getType());
+ // Preconditions.checkArgument(item.getType() == Material.LINGERING_POTION || item.getType() == Material.SPLASH_POTION, "ItemStack material must be Material.LINGERING_POTION or Material.SPLASH_POTION but was Material.%s", item.getType()); // Paper - Projectile API
+ org.bukkit.inventory.meta.PotionMeta meta = (item.getType() == Material.LINGERING_POTION || item.getType() == Material.SPLASH_POTION) ? null : this.getPotionMeta(); // Paper - Projectile API
this.getHandle().setItem(CraftItemStack.asNMSCopy(item));
+ if (meta != null) this.setPotionMeta(meta); // Paper - Projectile API
}
+ // Paper start - Projectile API
+ @Override
+ public org.bukkit.inventory.meta.PotionMeta getPotionMeta() {
+ return (org.bukkit.inventory.meta.PotionMeta) CraftItemStack.getItemMeta(this.getHandle().getItem(), Material.SPLASH_POTION);
+ }
+
+ @Override
+ public void setPotionMeta(org.bukkit.inventory.meta.PotionMeta meta) {
+ net.minecraft.world.item.ItemStack item = this.getHandle().getItem();
+ CraftItemStack.applyMetaToItem(item, meta);
+ this.getHandle().setItem(item); // Reset item
+ }
+
+ @Override
+ public void splash() {
+ this.getHandle().splash(null);
+ }
+ // Paper end
@Override
public net.minecraft.world.entity.projectile.ThrownPotion getHandle() {
return (net.minecraft.world.entity.projectile.ThrownPotion) this.entity;
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftTrident.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftTrident.java
index e374b9f40eddca13b30855d25a2030f8df98138f..4fc893378fb0568ddcffc7593d66df6bfe23f659 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftTrident.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftTrident.java
@@ -53,5 +53,15 @@ public class CraftTrident extends CraftAbstractArrow implements Trident {
com.google.common.base.Preconditions.checkArgument(loyaltyLevel >= 0 && loyaltyLevel <= 127, "The loyalty level has to be between 0 and 127");
this.getHandle().setLoyalty((byte) loyaltyLevel);
}
+
+ @Override
+ public boolean hasDealtDamage() {
+ return this.getHandle().dealtDamage;
+ }
+
+ @Override
+ public void setHasDealtDamage(boolean hasDealtDamage) {
+ this.getHandle().dealtDamage = hasDealtDamage;
+ }
// Paper end
}
diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
index efc3808dde268f8325304f4bce8fb3bf399adafd..9588c191ccb5665be2ff90ae2ded5bbff12faacb 100644
--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
@@ -832,19 +832,19 @@ public class CraftEventFactory {
/**
* PotionSplashEvent
*/
- public static PotionSplashEvent callPotionSplashEvent(net.minecraft.world.entity.projectile.ThrownPotion potion, HitResult position, Map<LivingEntity, Double> affectedEntities) {
+ public static PotionSplashEvent callPotionSplashEvent(net.minecraft.world.entity.projectile.ThrownPotion potion, @Nullable HitResult position, Map<LivingEntity, Double> affectedEntities) { // Paper - nullable hitResult
ThrownPotion thrownPotion = (ThrownPotion) potion.getBukkitEntity();
Block hitBlock = null;
BlockFace hitFace = null;
- if (position.getType() == HitResult.Type.BLOCK) {
+ if (position != null && position.getType() == HitResult.Type.BLOCK) { // Paper - nullable hitResult
BlockHitResult positionBlock = (BlockHitResult) position;
hitBlock = CraftBlock.at(potion.level(), positionBlock.getBlockPos());
hitFace = CraftBlock.notchToBlockFace(positionBlock.getDirection());
}
org.bukkit.entity.Entity hitEntity = null;
- if (position.getType() == HitResult.Type.ENTITY) {
+ if (position != null && position.getType() == HitResult.Type.ENTITY) { // Paper - nullable hitResult
hitEntity = ((EntityHitResult) position).getEntity().getBukkitEntity();
}
@@ -853,20 +853,20 @@ public class CraftEventFactory {
return event;
}
- public static LingeringPotionSplashEvent callLingeringPotionSplashEvent(net.minecraft.world.entity.projectile.ThrownPotion potion, HitResult position, net.minecraft.world.entity.AreaEffectCloud cloud) {
+ public static LingeringPotionSplashEvent callLingeringPotionSplashEvent(net.minecraft.world.entity.projectile.ThrownPotion potion, @Nullable HitResult position, net.minecraft.world.entity.AreaEffectCloud cloud) { // Paper - nullable hitResult
ThrownPotion thrownPotion = (ThrownPotion) potion.getBukkitEntity();
AreaEffectCloud effectCloud = (AreaEffectCloud) cloud.getBukkitEntity();
Block hitBlock = null;
BlockFace hitFace = null;
- if (position.getType() == HitResult.Type.BLOCK) {
+ if (position != null && position.getType() == HitResult.Type.BLOCK) { // Paper
BlockHitResult positionBlock = (BlockHitResult) position;
hitBlock = CraftBlock.at(potion.level(), positionBlock.getBlockPos());
hitFace = CraftBlock.notchToBlockFace(positionBlock.getDirection());
}
org.bukkit.entity.Entity hitEntity = null;
- if (position.getType() == HitResult.Type.ENTITY) {
+ if (position != null && position.getType() == HitResult.Type.ENTITY) { // Paper
hitEntity = ((EntityHitResult) position).getEntity().getBukkitEntity();
}
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java
index 92faa15f79f0541048e29254dcf3560616d3c0e7..2a7996f5cfb1eacf098e73f35bafc4327b041c51 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java
@@ -295,12 +295,22 @@ public final class CraftItemStack extends ItemStack {
public ItemMeta getItemMeta() {
return CraftItemStack.getItemMeta(this.handle);
}
+ // Paper start
+ public static void applyMetaToItem(net.minecraft.world.item.ItemStack itemStack, ItemMeta itemMeta) {
+ final CraftMetaItem.Applicator tag = new CraftMetaItem.Applicator();
+ ((CraftMetaItem) itemMeta).applyToItem(tag);
+ itemStack.applyComponents(tag.build());
+ }
public static ItemMeta getItemMeta(net.minecraft.world.item.ItemStack item) {
+ return getItemMeta(item, CraftItemStack.getType(item));
+ }
+ public static ItemMeta getItemMeta(net.minecraft.world.item.ItemStack item, Material material) {
+ // Paper end
if (!CraftItemStack.hasItemMeta(item)) {
- return CraftItemFactory.instance().getItemMeta(CraftItemStack.getType(item));
+ return CraftItemFactory.instance().getItemMeta(material); // Paper
}
- switch (CraftItemStack.getType(item)) {
+ switch (material) { // Paper
case WRITTEN_BOOK:
return new CraftMetaBookSigned(item.getComponentsPatch());
case WRITABLE_BOOK:
|