From 4daa21123c599eec7e43f56abfa888024470d99b Mon Sep 17 00:00:00 2001 From: Parker Hawke Date: Mon, 12 Sep 2022 19:04:24 +1000 Subject: [PATCH] SPIGOT-3842: Add Player#fireworkBoost() and expand Firework API --- .../entity/projectile/EntityFireworks.patch | 13 +++- .../craftbukkit/entity/CraftFirework.java | 60 ++++++++++++++++++- .../craftbukkit/entity/CraftHumanEntity.java | 13 ++++ 3 files changed, 84 insertions(+), 2 deletions(-) diff --git a/nms-patches/net/minecraft/world/entity/projectile/EntityFireworks.patch b/nms-patches/net/minecraft/world/entity/projectile/EntityFireworks.patch index cdd7d162a..44bfe5ecc 100644 --- a/nms-patches/net/minecraft/world/entity/projectile/EntityFireworks.patch +++ b/nms-patches/net/minecraft/world/entity/projectile/EntityFireworks.patch @@ -1,6 +1,6 @@ --- a/net/minecraft/world/entity/projectile/EntityFireworks.java +++ b/net/minecraft/world/entity/projectile/EntityFireworks.java -@@ -29,6 +29,8 @@ +@@ -29,15 +29,17 @@ import net.minecraft.world.phys.MovingObjectPositionEntity; import net.minecraft.world.phys.Vec3D; @@ -9,6 +9,17 @@ public class EntityFireworks extends IProjectile implements ItemSupplier { public static final DataWatcherObject DATA_ID_FIREWORKS_ITEM = DataWatcher.defineId(EntityFireworks.class, DataWatcherRegistry.ITEM_STACK); + private static final DataWatcherObject DATA_ATTACHED_TO_TARGET = DataWatcher.defineId(EntityFireworks.class, DataWatcherRegistry.OPTIONAL_UNSIGNED_INT); + public static final DataWatcherObject DATA_SHOT_AT_ANGLE = DataWatcher.defineId(EntityFireworks.class, DataWatcherRegistry.BOOLEAN); +- private int life; ++ public int life; // PAIL private -> public + public int lifetime; + @Nullable +- private EntityLiving attachedToEntity; ++ public EntityLiving attachedToEntity; // PAIL private -> public + + public EntityFireworks(EntityTypes entitytypes, World world) { + super(entitytypes, world); @@ -144,7 +146,7 @@ MovingObjectPosition movingobjectposition = ProjectileHelper.getHitResult(this, this::canHitEntity); diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftFirework.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftFirework.java index c91468dec..27ddb27ec 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftFirework.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftFirework.java @@ -1,6 +1,8 @@ package org.bukkit.craftbukkit.entity; +import com.google.common.base.Preconditions; import java.util.Random; +import net.minecraft.world.entity.EntityLiving; import net.minecraft.world.entity.projectile.EntityFireworks; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; @@ -9,6 +11,7 @@ import org.bukkit.craftbukkit.CraftServer; import org.bukkit.craftbukkit.inventory.CraftItemStack; import org.bukkit.entity.EntityType; import org.bukkit.entity.Firework; +import org.bukkit.entity.LivingEntity; import org.bukkit.inventory.meta.FireworkMeta; public class CraftFirework extends CraftProjectile implements Firework { @@ -64,9 +67,64 @@ public class CraftFirework extends CraftProjectile implements Firework { getHandle().getEntityData().markDirty(EntityFireworks.DATA_ID_FIREWORKS_ITEM); } + @Override + public boolean setAttachedTo(LivingEntity entity) { + if (isDetonated()) { + return false; + } + + getHandle().attachedToEntity = (entity != null) ? ((CraftLivingEntity) entity).getHandle() : null; + return true; + } + + @Override + public LivingEntity getAttachedTo() { + EntityLiving entity = getHandle().attachedToEntity; + return (entity != null) ? (LivingEntity) entity.getBukkitEntity() : null; + } + + @Override + public boolean setLife(int ticks) { + Preconditions.checkArgument(ticks >= 0, "ticks must be greater than or equal to 0"); + + if (isDetonated()) { + return false; + } + + getHandle().life = ticks; + return true; + } + + @Override + public int getLife() { + return getHandle().life; + } + + @Override + public boolean setMaxLife(int ticks) { + Preconditions.checkArgument(ticks > 0, "ticks must be greater than 0"); + + if (isDetonated()) { + return false; + } + + getHandle().lifetime = ticks; + return true; + } + + @Override + public int getMaxLife() { + return getHandle().lifetime; + } + @Override public void detonate() { - getHandle().lifetime = 0; + this.setLife(getMaxLife() + 1); + } + + @Override + public boolean isDetonated() { + return getHandle().life > getHandle().lifetime; } @Override diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java index ac19f5030..00d9d3843 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java @@ -18,6 +18,7 @@ import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EntityTypes; import net.minecraft.world.entity.EnumMainHand; import net.minecraft.world.entity.player.EntityHuman; +import net.minecraft.world.entity.projectile.EntityFireworks; import net.minecraft.world.inventory.Container; import net.minecraft.world.inventory.Containers; import net.minecraft.world.item.ItemCooldown; @@ -49,8 +50,10 @@ import org.bukkit.craftbukkit.inventory.CraftMerchantCustom; import org.bukkit.craftbukkit.util.CraftChatMessage; import org.bukkit.craftbukkit.util.CraftMagicNumbers; import org.bukkit.craftbukkit.util.CraftNamespacedKey; +import org.bukkit.entity.Firework; import org.bukkit.entity.HumanEntity; import org.bukkit.entity.Villager; +import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason; import org.bukkit.inventory.EntityEquipment; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.InventoryView; @@ -661,4 +664,14 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { getHandle().setLastDeathLocation(Optional.of(CraftMemoryMapper.toNms(location))); } } + + @Override + public Firework fireworkBoost(ItemStack fireworkItemStack) { + Preconditions.checkArgument(fireworkItemStack != null, "fireworkItemStack must not be null"); + Preconditions.checkArgument(fireworkItemStack.getType() == Material.FIREWORK_ROCKET, "fireworkItemStack must be of type %s", Material.FIREWORK_ROCKET); + + EntityFireworks fireworks = new EntityFireworks(getHandle().level, CraftItemStack.asNMSCopy(fireworkItemStack), getHandle()); + boolean success = getHandle().level.addFreshEntity(fireworks, SpawnReason.CUSTOM); + return success ? (Firework) fireworks.getBukkitEntity() : null; + } }