Skip to content

Commit

Permalink
Hurt command: allow source:location - also meta fixes for Area
Browse files Browse the repository at this point in the history
also remove deprecated source_once
  • Loading branch information
mcmonkey4eva committed Nov 25, 2022
1 parent 8602207 commit 2d373e5
Show file tree
Hide file tree
Showing 8 changed files with 70 additions and 86 deletions.
Expand Up @@ -14,6 +14,7 @@
import org.bukkit.block.CreatureSpawner;
import org.bukkit.block.data.BlockData;
import org.bukkit.entity.*;
import org.bukkit.event.entity.EntityDamageByBlockEvent;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
import org.bukkit.event.entity.EntityDamageEvent;
import org.bukkit.inventory.meta.MapMeta;
Expand Down Expand Up @@ -388,13 +389,22 @@ public void setGhastAttacking(Entity entity, boolean attacking) { // TODO: once

public abstract void setEndermanAngry(Entity entity, boolean angry);

public static EntityDamageEvent fireFakeDamageEvent(Entity target, Entity source, EntityDamageEvent.DamageCause cause, float amount) {
EntityDamageEvent ede = source == null ? new EntityDamageEvent(target, cause, amount) : new EntityDamageByEntityEvent(source, target, cause, amount);
public static EntityDamageEvent fireFakeDamageEvent(Entity target, EntityTag source, Location sourceLoc, EntityDamageEvent.DamageCause cause, float amount) {
EntityDamageEvent ede;
if (source != null) {
ede = new EntityDamageByEntityEvent(source.getBukkitEntity(), target, cause, amount);
}
else if (sourceLoc != null) {
ede = new EntityDamageByBlockEvent(sourceLoc.getBlock(), target, cause, amount);
}
else {
ede = new EntityDamageEvent(target, cause, amount);
}
Bukkit.getPluginManager().callEvent(ede);
return ede;
}

public abstract void damage(LivingEntity target, float amount, Entity source, EntityDamageEvent.DamageCause cause);
public abstract void damage(LivingEntity target, float amount, EntityTag source, Location sourceLoc, EntityDamageEvent.DamageCause cause);

public void setLastHurtBy(LivingEntity mob, LivingEntity damager) {
throw new UnsupportedOperationException();
Expand Down
Expand Up @@ -123,9 +123,9 @@ static <T extends AreaContainmentObject> void register(Class<T> type, ObjectTag
// @description
// Gets a list of all players currently within the area.
// @example
// # Narrates a list of players' names that are within the area separated by a comma and a space.
// # Narrates a list of players' names that are within the area.
// # For example: "List of players in 'my_cuboid': steve, alex, john, jane"
// - narrate "List of players in 'my_cuboid': <cuboid[my_cuboid].players.parse[name].separated_by[, ]>"
// - narrate "List of players in 'my_cuboid': <cuboid[my_cuboid].players.formatted>"
// -->
processor.registerTag(ListTag.class, "players", (attribute, area) -> {
ListTag result = new ListTag();
Expand All @@ -143,9 +143,9 @@ static <T extends AreaContainmentObject> void register(Class<T> type, ObjectTag
// @description
// Gets a list of all NPCs currently within the area.
// @example
// # Narrates a list of NPCs' names that are within the area separated by a comma and a space.
// # Narrates a list of NPCs' names that are within the area.
// # For example: "List of NPCs in 'my_cuboid': steve, alex, john, jane"
// - narrate "List of NPCs in 'my_cuboid': <cuboid[my_cuboid].npcs.parse[name].separated_by[, ]>"
// - narrate "List of NPCs in 'my_cuboid': <cuboid[my_cuboid].npcs.formatted>"
// -->
if (Depends.citizens != null) {
processor.registerTag(ListTag.class, "npcs", (attribute, area) -> {
Expand Down
@@ -1,33 +1,35 @@
package com.denizenscript.denizen.scripts.commands.entity;

import com.denizenscript.denizen.nms.NMSHandler;
import com.denizenscript.denizen.objects.LocationTag;
import com.denizenscript.denizen.utilities.Utilities;
import com.denizenscript.denizencore.exceptions.InvalidArgumentsRuntimeException;
import com.denizenscript.denizencore.objects.ObjectTag;
import com.denizenscript.denizencore.scripts.commands.generator.*;
import com.denizenscript.denizencore.utilities.debugging.Debug;
import com.denizenscript.denizen.objects.EntityTag;
import com.denizenscript.denizencore.exceptions.InvalidArgumentsException;
import com.denizenscript.denizencore.objects.Argument;
import com.denizenscript.denizencore.objects.core.ElementTag;
import com.denizenscript.denizencore.objects.core.ListTag;
import com.denizenscript.denizencore.scripts.ScriptEntry;
import com.denizenscript.denizencore.scripts.commands.AbstractCommand;
import com.denizenscript.denizen.utilities.BukkitImplDeprecations;
import org.bukkit.event.entity.EntityDamageEvent;

import java.util.ArrayList;
import java.util.List;

public class HurtCommand extends AbstractCommand {

public HurtCommand() {
setName("hurt");
setSyntax("hurt (<#.#>) ({player}/<entity>|...) (cause:<cause>) (source:<entity>)");
setRequiredArguments(0, 5);
setSyntax("hurt (<#.#>) ({player}/<entity>|...) (cause:<cause>) (source:<entity>/<location>)");
setRequiredArguments(0, 4);
isProcedural = false;
addRemappedPrefixes("source", "s");
autoCompile();
}

// <--[command]
// @Name Hurt
// @Syntax hurt (<#.#>) ({player}/<entity>|...) (cause:<cause>) (source:<entity>)
// @Syntax hurt (<#.#>) ({player}/<entity>|...) (cause:<cause>) (source:<entity>/<location>)
// @Required 0
// @Maximum 4
// @Short Hurts the player or a list of entities.
Expand All @@ -43,6 +45,7 @@ public HurtCommand() {
// Does a specified amount of damage usually, but, if no damage is specified, does precisely 1HP worth of damage (half a heart).
//
// Optionally, specify (source:<entity>) to make the system treat that entity as the attacker.
// If using a block-type cause such as "contact", you *must* specify (source:<location>) to set that block location as the attacker. The block can be any block, even just "<player.location>" (as long as the player in inside a world).
//
// You may also specify a damage cause to fire a proper damage event with the given cause, only doing the damage if the event wasn't cancelled.
// Calculates the 'final damage' rather than using the raw damage input number. See <@link language damage cause> for damage causes.
Expand Down Expand Up @@ -70,72 +73,45 @@ public HurtCommand() {
// - hurt <npc.health> <npc> cause:CUSTOM source:<player>
// -->

@Override
public void parseArgs(ScriptEntry scriptEntry) throws InvalidArgumentsException {
for (Argument arg : scriptEntry) {
if (!scriptEntry.hasObject("amount")
&& (arg.matchesFloat()
|| arg.matchesInteger())) {
scriptEntry.addObject("amount", arg.asElement());
}
else if (!scriptEntry.hasObject("source")
&& arg.matchesPrefix("source", "s")
&& arg.matchesArgumentType(EntityTag.class)) {
scriptEntry.addObject("source", arg.asType(EntityTag.class));
}
else if (!scriptEntry.hasObject("entities")
&& arg.matchesArgumentList(EntityTag.class)) {
scriptEntry.addObject("entities", arg.asType(ListTag.class).filter(EntityTag.class, scriptEntry));
}
else if (!scriptEntry.hasObject("cause")
&& arg.matchesEnum(EntityDamageEvent.DamageCause.class)) {
scriptEntry.addObject("cause", arg.asElement());
}
else if (!scriptEntry.hasObject("source_once")
&& arg.matches("source_once")) {
BukkitImplDeprecations.hurtSourceOne.warn(scriptEntry);
scriptEntry.addObject("source_once", new ElementTag(true));
public static void autoExecute(ScriptEntry scriptEntry,
@ArgName("source") @ArgPrefixed @ArgDefaultNull ObjectTag source,
@ArgName("cause") @ArgPrefixed @ArgDefaultNull EntityDamageEvent.DamageCause cause,
@ArgName("amount") @ArgLinear @ArgDefaultText("1") ObjectTag amountObj,
@ArgName("entities") @ArgLinear @ArgDefaultNull ObjectTag entitiesObj) {
if (!amountObj.asElement().isDouble()) { // Compensate for legacy out-of-order args
ObjectTag swapEntities = entitiesObj;
entitiesObj = amountObj;
if (swapEntities != null && swapEntities.asElement().isDouble()) {
amountObj = swapEntities;
}
else {
arg.reportUnhandled();
amountObj = new ElementTag(1.0d);
}
}
if (!scriptEntry.hasObject("amount")) {
scriptEntry.addObject("amount", new ElementTag(1.0d));
List<EntityTag> entities = entitiesObj == null ? null : entitiesObj.asType(ListTag.class, scriptEntry.context).filter(EntityTag.class, scriptEntry.context);
if (entities == null) {
entities = Utilities.entryDefaultEntityList(scriptEntry, true);
if (entities == null) {
throw new InvalidArgumentsRuntimeException("No valid target entities found.");
}
}
if (!scriptEntry.hasObject("entities")) {
List<EntityTag> entities = new ArrayList<>();
if (Utilities.getEntryPlayer(scriptEntry) != null) {
entities.add(Utilities.getEntryPlayer(scriptEntry).getDenizenEntity());
EntityTag sourceEntity = null;
LocationTag sourceLocation = null;
if (source != null) {
if (source.shouldBeType(LocationTag.class)) {
sourceLocation = source.asType(LocationTag.class, scriptEntry.context);
}
else if (Utilities.getEntryNPC(scriptEntry) != null) {
entities.add(Utilities.getEntryNPC(scriptEntry).getDenizenEntity());
if (source.shouldBeType(EntityTag.class)) {
sourceEntity = source.asType(EntityTag.class, scriptEntry.context);
}
else {
throw new InvalidArgumentsException("No valid target entities found.");
}
scriptEntry.addObject("entities", entities);
}

}

@Override
public void execute(ScriptEntry scriptEntry) {
List<EntityTag> entities = (List<EntityTag>) scriptEntry.getObject("entities");
EntityTag source = scriptEntry.getObjectTag("source");
ElementTag amountElement = scriptEntry.getElement("amount");
ElementTag cause = scriptEntry.getElement("cause");
if (scriptEntry.dbCallShouldDebug()) {
Debug.report(scriptEntry, getName(), amountElement, db("entities", entities), cause, source);
}
double amount = amountElement.asDouble();
double amount = amountObj.asElement().asDouble();
for (EntityTag entity : entities) {
if (entity.getLivingEntity() == null) {
Debug.echoDebug(scriptEntry, entity + " is not a living entity!");
continue;
}
EntityDamageEvent.DamageCause causeEnum = cause == null ? null : EntityDamageEvent.DamageCause.valueOf(cause.asString().toUpperCase());
NMSHandler.entityHelper.damage(entity.getLivingEntity(), (float) amount, source == null ? null : source.getBukkitEntity(), causeEnum);
NMSHandler.entityHelper.damage(entity.getLivingEntity(), (float) amount, sourceEntity, sourceLocation, cause);
}
}
}
Expand Up @@ -141,9 +141,6 @@ public class BukkitImplDeprecations {
// Added 2020/04/16.
public static Warning entityStandingOn = new SlowWarning("entityStandingOn", pointlessSubtagPrefix + "entity.location.standing_on is now just entity.standing_on.");

// Added 2021/05/02.
public static Warning hurtSourceOne = new SlowWarning("hurtSourceOne", "The 'hurt' command's 'source_once' argument is deprecated due to being now irrelevant thanks to the new NMS backing for the hurt command.");

// Added 2021/05/05.
public static Warning materialLit = new SlowWarning("materialLit", "The MaterialTag property 'lit' is deprecated in favor of 'switched'.");
public static Warning materialCampfire = new SlowWarning("materialCampfire", "The MaterialTag property 'campfire' are deprecated in favor of 'type'.");
Expand Down
Expand Up @@ -5,6 +5,7 @@
import com.denizenscript.denizen.nms.interfaces.EntityHelper;
import com.denizenscript.denizen.nms.util.jnbt.CompoundTag;
import com.denizenscript.denizen.nms.v1_16.impl.jnbt.CompoundTagImpl;
import com.denizenscript.denizen.objects.EntityTag;
import com.denizenscript.denizen.utilities.Utilities;
import com.denizenscript.denizencore.utilities.ReflectionHelper;
import com.denizenscript.denizencore.utilities.debugging.Debug;
Expand All @@ -21,7 +22,6 @@
import org.bukkit.entity.Entity;
import org.bukkit.entity.*;
import org.bukkit.event.entity.EntityDamageEvent;
import org.bukkit.event.entity.EntityTargetEvent;
import org.bukkit.scheduler.BukkitRunnable;
import org.bukkit.scheduler.BukkitTask;
import org.bukkit.util.BoundingBox;
Expand Down Expand Up @@ -490,13 +490,14 @@ public void setEndermanAngry(Entity entity, boolean angry) {
}

@Override
public void damage(LivingEntity target, float amount, Entity source, EntityDamageEvent.DamageCause cause) {
public void damage(LivingEntity target, float amount, EntityTag source, Location sourceLoc, EntityDamageEvent.DamageCause cause) {
if (target == null) {
return;
}
EntityLiving nmsTarget = ((CraftLivingEntity) target).getHandle();
net.minecraft.server.v1_16_R3.Entity nmsSource = source == null ? null : ((CraftEntity) source).getHandle();
net.minecraft.server.v1_16_R3.Entity nmsSource = source == null ? null : ((CraftEntity) source.getBukkitEntity()).getHandle();
CraftEventFactory.entityDamage = nmsSource;
CraftEventFactory.blockDamage = sourceLoc == null ? null : sourceLoc.getBlock();
try {
DamageSource src = DamageSource.GENERIC;
if (nmsSource != null) {
Expand Down Expand Up @@ -594,7 +595,7 @@ else if (nmsSource instanceof EntityLiving) {
break;
//case SUICIDE:
default:
EntityDamageEvent ede = fireFakeDamageEvent(target, source, cause, amount);
EntityDamageEvent ede = fireFakeDamageEvent(target, source, sourceLoc, cause, amount);
if (ede.isCancelled()) {
return;
}
Expand Down
Expand Up @@ -53,7 +53,6 @@
import org.bukkit.craftbukkit.v1_17_R1.inventory.CraftItemStack;
import org.bukkit.entity.*;
import org.bukkit.event.entity.EntityDamageEvent;
import org.bukkit.event.entity.EntityTargetEvent;
import org.bukkit.scheduler.BukkitRunnable;
import org.bukkit.scheduler.BukkitTask;
import org.bukkit.util.BoundingBox;
Expand Down Expand Up @@ -595,18 +594,19 @@ else if (nmsSource instanceof net.minecraft.world.entity.LivingEntity) {
}

@Override
public void damage(LivingEntity target, float amount, Entity source, EntityDamageEvent.DamageCause cause) {
public void damage(LivingEntity target, float amount, EntityTag source, Location sourceLoc, EntityDamageEvent.DamageCause cause) {
if (target == null) {
return;
}
net.minecraft.world.entity.LivingEntity nmsTarget = ((CraftLivingEntity) target).getHandle();
net.minecraft.world.entity.Entity nmsSource = source == null ? null : ((CraftEntity) source).getHandle();
net.minecraft.world.entity.Entity nmsSource = source == null ? null : ((CraftEntity) source.getBukkitEntity()).getHandle();
CraftEventFactory.entityDamage = nmsSource;
CraftEventFactory.blockDamage = sourceLoc == null ? null : sourceLoc.getBlock();
try {
DamageSource src = getSourceFor(nmsSource, cause);
if (src instanceof FakeDamageSrc) {
src = ((FakeDamageSrc) src).real;
EntityDamageEvent ede = fireFakeDamageEvent(target, source, cause, amount);
EntityDamageEvent ede = fireFakeDamageEvent(target, source, sourceLoc, cause, amount);
if (ede.isCancelled()) {
return;
}
Expand Down
Expand Up @@ -60,7 +60,6 @@
import org.bukkit.craftbukkit.v1_18_R2.inventory.CraftItemStack;
import org.bukkit.entity.*;
import org.bukkit.event.entity.EntityDamageEvent;
import org.bukkit.event.entity.EntityTargetEvent;
import org.bukkit.scheduler.BukkitRunnable;
import org.bukkit.scheduler.BukkitTask;
import org.bukkit.util.BoundingBox;
Expand Down Expand Up @@ -672,18 +671,19 @@ else if (nmsSource instanceof net.minecraft.world.entity.LivingEntity) {
}

@Override
public void damage(LivingEntity target, float amount, Entity source, EntityDamageEvent.DamageCause cause) {
public void damage(LivingEntity target, float amount, EntityTag source, Location sourceLoc, EntityDamageEvent.DamageCause cause) {
if (target == null) {
return;
}
net.minecraft.world.entity.LivingEntity nmsTarget = ((CraftLivingEntity) target).getHandle();
net.minecraft.world.entity.Entity nmsSource = source == null ? null : ((CraftEntity) source).getHandle();
net.minecraft.world.entity.Entity nmsSource = source == null ? null : ((CraftEntity) source.getBukkitEntity()).getHandle();
CraftEventFactory.entityDamage = nmsSource;
CraftEventFactory.blockDamage = sourceLoc == null ? null : sourceLoc.getBlock();
try {
DamageSource src = getSourceFor(nmsSource, cause);
if (src instanceof FakeDamageSrc) {
src = ((FakeDamageSrc) src).real;
EntityDamageEvent ede = fireFakeDamageEvent(target, source, cause, amount);
EntityDamageEvent ede = fireFakeDamageEvent(target, source, sourceLoc, cause, amount);
if (ede.isCancelled()) {
return;
}
Expand Down
Expand Up @@ -66,7 +66,6 @@
import org.bukkit.craftbukkit.v1_19_R1.inventory.CraftItemStack;
import org.bukkit.entity.*;
import org.bukkit.event.entity.EntityDamageEvent;
import org.bukkit.event.entity.EntityTargetEvent;
import org.bukkit.scheduler.BukkitRunnable;
import org.bukkit.scheduler.BukkitTask;
import org.bukkit.util.BoundingBox;
Expand Down Expand Up @@ -676,18 +675,19 @@ else if (nmsSource instanceof net.minecraft.world.entity.LivingEntity) {
}

@Override
public void damage(LivingEntity target, float amount, Entity source, EntityDamageEvent.DamageCause cause) {
public void damage(LivingEntity target, float amount, EntityTag source, Location sourceLoc, EntityDamageEvent.DamageCause cause) {
if (target == null) {
return;
}
net.minecraft.world.entity.LivingEntity nmsTarget = ((CraftLivingEntity) target).getHandle();
net.minecraft.world.entity.Entity nmsSource = source == null ? null : ((CraftEntity) source).getHandle();
net.minecraft.world.entity.Entity nmsSource = source == null ? null : ((CraftEntity) source.getBukkitEntity()).getHandle();
CraftEventFactory.entityDamage = nmsSource;
CraftEventFactory.blockDamage = sourceLoc == null ? null : sourceLoc.getBlock();
try {
DamageSource src = getSourceFor(nmsSource, cause);
if (src instanceof FakeDamageSrc) {
src = ((FakeDamageSrc) src).real;
EntityDamageEvent ede = fireFakeDamageEvent(target, source, cause, amount);
EntityDamageEvent ede = fireFakeDamageEvent(target, source, sourceLoc, cause, amount);
if (ede.isCancelled()) {
return;
}
Expand Down

0 comments on commit 2d373e5

Please sign in to comment.