22
33import java .io .File ;
44import java .lang .reflect .Field ;
5+ import java .lang .reflect .Method ;
56import java .util .ArrayList ;
67import java .util .HashMap ;
78import java .util .List ;
1819import org .bukkit .command .CommandSender ;
1920import org .bukkit .entity .Entity ;
2021import org .bukkit .entity .HumanEntity ;
22+ import org .bukkit .entity .LivingEntity ;
2123import org .bukkit .entity .Player ;
2224import org .bukkit .inventory .ItemStack ;
2325import org .bukkit .inventory .PlayerInventory ;
3739import com .trc202 .settings .SettingsHelper ;
3840import com .trc202 .settings .SettingsLoader ;
3941
42+ import static com .trc202 .CombatTag .Reflection .*;
43+
4044public class CombatTag extends JavaPlugin {
4145
4246 private final SettingsHelper settingsHelper ;
@@ -87,11 +91,13 @@ public CombatTag() {
8791 */
8892 @ Override
8993 public void onDisable () {
90- for (NPC npc : npcm .getNPCs ()) {
91- UUID uuid = npcm .getNPCIdFromEntity (npc .getEntity ());
92- despawnNPC (uuid , NpcDespawnReason .PLUGIN_DISABLED );
93- if (isDebugEnabled ()) {
94- log .info ("[CombatTag] Disabling npc with ID of: " + uuid );
94+ if (npcm != null ) {
95+ for (NPC npc : npcm .getNPCs ()) {
96+ UUID uuid = npcm .getNPCIdFromEntity (npc .getEntity ());
97+ despawnNPC (uuid , NpcDespawnReason .PLUGIN_DISABLED );
98+ if (isDebugEnabled ()) {
99+ log .info ("[CombatTag] Disabling npc with ID of: " + uuid );
100+ }
95101 }
96102 }
97103 //Just in case...
@@ -367,7 +373,7 @@ public boolean onCommand(CommandSender sender, Command command, String commandLa
367373 sender .sendMessage ("Please specify a player to force into combat" );
368374 return true ;
369375 }
370- if (isInCombat (toForce .getUniqueId ())) {
376+ if (! isInCombat (toForce .getUniqueId ())) {
371377 tagged .put (toForce .getUniqueId (), PvPTimeout (60 ));
372378 if (!toForce .equals (sender )) sender .sendMessage ("You have been forced into combat for one minute" );
373379 sender .sendMessage ("Sucessfuly forced " + toForce .getName () + " into combat." );
@@ -457,7 +463,7 @@ public void updatePlayerData(NPC npc, UUID playerUUID) {
457463 emptyArmorStack [x ] = airItem ;
458464 }
459465 target .getInventory ().setArmorContents (emptyArmorStack );
460- target . setHealth ( 0 );
466+ setHealth ( target , healthCheck ( source . getHealth ()) );
461467 } else {
462468 copyTo (target , source );
463469 }
@@ -480,13 +486,7 @@ public void copyTo(Player target, Player source) {
480486 target .setExhaustion (source .getExhaustion ());
481487 target .setSaturation (source .getSaturation ());
482488 target .setFireTicks (source .getFireTicks ());
483- if (target instanceof HumanEntity ) {
484- HumanEntity humanTarget = (HumanEntity ) target ;
485- double healthSet = healthCheck (source .getHealth ());
486- humanTarget .setHealth ((float ) healthSet );
487- } else {
488- log .info ("[CombatTag] An error has occurred! Target is not a HumanEntity!" );
489- }
489+ setHealth (target , healthCheck (source .getHealth ()));
490490 }
491491
492492 public double healthCheck (double health ) {
@@ -506,13 +506,22 @@ public SettingsHelper getSettingsHelper() {
506506 public static boolean isVersionSupported () {
507507 return NPCLib .isSupported ();
508508 }
509-
510- public static final Field ENTITY_PLAYER_INVULNERABLE_TICKS_FIELD = Reflection .makeField (Reflection .getNmsClass ("EntityPlayer" ), "invulnerableTicks" );
511-
509+
510+ public static final Field ENTITY_PLAYER_INVULNERABLE_TICKS_FIELD = Reflection .makeField (getNmsClass ("EntityPlayer" ), "invulnerableTicks" );
511+ public static final Method ENTITY_LIVING_SET_HEALTH_METHOD = Reflection .makeMethod (getNmsClass ("EntityLiving" ), "setHealth" , float .class );
512+
512513 public static void setInvulnerableTicks (Entity bukkitEntity , int invulnerableTicks ) { //Entity.setNoDamageTicks() doesn't set EntityPlayer.invulnerableTicks
513514 Object entity = Reflection .getHandle (bukkitEntity );
514- if (Reflection . getNmsClass ("EntityPlayer" ).isInstance (entity )) {
515+ if (getNmsClass ("EntityPlayer" ).isInstance (entity )) {
515516 Reflection .setField (ENTITY_PLAYER_INVULNERABLE_TICKS_FIELD , entity , invulnerableTicks );
516517 }
517518 }
519+ /*
520+ * EntityLiving.setHealth() calls die() if the entity is a player.
521+ * EntityPlayer.die() tries to close any open inventories, causing the offline player to throw an exception.
522+ */
523+ public static void setHealth (LivingEntity bukkitEntity , double health ) {
524+ Object entity = Reflection .getHandle (bukkitEntity );
525+ Reflection .callMethod (ENTITY_LIVING_SET_HEALTH_METHOD , entity , (float )health );
526+ }
518527}
0 commit comments