Skip to content

Commit

Permalink
Added an OnPvP compatability event (#356)
Browse files Browse the repository at this point in the history
* Added an OnPvP compatability event

See Issue #338: #338

* Fixed duplicate LivingAttackEvents

Alleviate the Forge bug causing duplicate posts of the LivingAttackEvent. Forge posts this event twice, once in EntityPlayer, and once in EntityLivingBase, so this tells if an EntityPlayer got hurt but the event was posted as an EntityLivingBase, then immediately returns, so nothing important gets run twice.

* Review 1: Added an OnPvP compatability event

* Improved pvpadmin command

`pvpadmin resetCooldown <player>`
and
`pvpadmin spy <player> [on|off]`

* Review 2: Added an OnPvP compatability event

Co-Authored-By: Mahtaran <[email protected]>
  • Loading branch information
VinyarionHyarmendacil and mahtaran authored Jul 31, 2019
1 parent 22b95eb commit cccc19c
Show file tree
Hide file tree
Showing 3 changed files with 129 additions and 2 deletions.
31 changes: 31 additions & 0 deletions src/main/java/pvpmode/api/common/utils/PvPCommonUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,13 @@

import org.apache.commons.io.IOUtils;

import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraftforge.event.entity.living.LivingAttackEvent;
import pvpmode.PvPMode;
import pvpmode.api.common.SimpleLogger;
import sun.reflect.CallerSensitive;
import sun.reflect.Reflection;

public class PvPCommonUtils
{
Expand Down Expand Up @@ -426,6 +430,33 @@ public static <T> Collection<T> createInstances (
return createInstances (classes, null, null);
}

/**
* Returns whether this is a bugged duplicate post of the LivingAttackEvent.
* Forge posts this event twice, once in EntityPlayer, and once in
* EntityLivingBase, so this will tell if an EntityPlayer got hurt but the
* event was posted as an EntityLivingBase. This should only be called from
* an {@link SubscribeEvent @SubscribeEvent} method with the event type of
* {@link LivingAttackEvent}.
*
* @param event
* The event to be checked
* @return If an EntityPlayer got hurt but the event was posted as an
* EntityLivingBase
*/
@SuppressWarnings("deprecation")
@CallerSensitive
public static boolean isCurrentAttackDuplicate (LivingAttackEvent event)
{
if (! (event.entityLiving instanceof EntityPlayer))
return false;
for (StackTraceElement element : Thread.currentThread ().getStackTrace ())
{
if (Reflection.getCallerClass (7) == EntityLivingBase.class)
return true;
}
return false;
}

/**
* Returns a {@link SimpleLogger} instance assigned to the specified name.
*
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package pvpmode.api.server.compatibility.events;

import cpw.mods.fml.common.eventhandler.*;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.DamageSource;
import pvpmode.api.common.EnumPvPMode;

/**
* Fired when a player attacks another player.
*
* @author Vinyarion
*
*/
@Cancelable
public class OnPvPEvent extends Event
{

private final EntityPlayer attacker;
private final EnumPvPMode attackerMode;
private final EntityPlayer victim;
private final EnumPvPMode victimMode;
private final float damageAmount;
private final DamageSource source;

public OnPvPEvent (EntityPlayer attacker, EnumPvPMode attackerMode, EntityPlayer victim, EnumPvPMode victimMode, float damageAmount, DamageSource source)
{
this.attacker = attacker;
this.attackerMode = attackerMode;
this.victim = victim;
this.victimMode = victimMode;
this.damageAmount = damageAmount;
this.source = source;
}

/**
* Returns the attacker
*/
public EntityPlayer getAttacker ()
{
return attacker;
}

/**
* Returns the attacker's mode
*/
public EnumPvPMode getAttackerMode ()
{
return attackerMode;
}

/**
* Returns the victim
*/
public EntityPlayer getVictim ()
{
return victim;
}

/**
* Returns the victim's mode
*/
public EnumPvPMode getVictimMode ()
{
return victimMode;
}

/**
* Returns the dealt damage amount
*/
public float getDamageAmount ()
{
return damageAmount;
}

/**
* Returns the damage source
*/
public DamageSource getSource ()
{
return source;
}

}
17 changes: 15 additions & 2 deletions src/main/java/pvpmode/internal/server/PvPServerEventHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import net.minecraftforge.event.entity.player.PlayerDropsEvent;
import pvpmode.PvPMode;
import pvpmode.api.common.EnumPvPMode;
import pvpmode.api.common.utils.PvPCommonUtils;
import pvpmode.api.common.version.*;
import pvpmode.api.server.PvPData;
import pvpmode.api.server.compatibility.events.*;
Expand All @@ -42,12 +43,18 @@ public PvPServerEventHandler ()
}

/**
* Cancels combat events associated with PvP-disabled players. Note that this
* function will be invoked twice per attack - this is because of a Forge bug.
* Cancels combat events associated with PvP-disabled players. Note that
* this function will be invoked twice per attack - this is because of a
* Forge bug, but the {@link PvPCommonUtils#isCurrentAttackDuplicate()} call
* checks and returns if this call is a duplicate
*/
@SubscribeEvent
public void interceptPvP (LivingAttackEvent event)
{
// This alleviates duplicate entries.
if (PvPCommonUtils.isCurrentAttackDuplicate (event))
return;

EntityPlayerMP attacker = PvPServerUtils.getMaster (event.source.getEntity ());
EntityPlayerMP victim = PvPServerUtils.getMaster (event.entity);

Expand All @@ -59,6 +66,12 @@ public void interceptPvP (LivingAttackEvent event)

boolean cancel = false;

if (MinecraftForge.EVENT_BUS.post (new OnPvPEvent (attacker, attackerMode, victim, victimMode, event.ammount, event.source)))
{
event.setCanceled (true);
return;
}

if (attackerMode != EnumPvPMode.ON)
{
if (attacker == event.source.getEntity ())
Expand Down

0 comments on commit cccc19c

Please sign in to comment.