Skip to content

Commit

Permalink
Fix mob always dropping xp when killed (#823)
Browse files Browse the repository at this point in the history
  • Loading branch information
XuZhen86 authored and mastercoms committed Feb 4, 2018
1 parent 8707480 commit 89a3784
Show file tree
Hide file tree
Showing 5 changed files with 109 additions and 9 deletions.
19 changes: 16 additions & 3 deletions src/main/java/net/glowstone/block/blocktype/BlockTnt.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,20 +15,33 @@
public class BlockTnt extends BlockType {

/**
* Convert a TNT block into a primed TNT entity.
* Convert a TNT block into a primed TNT entity with the player who ignited the TNT.
*
* @param tntBlock The block to ignite.
* @param ignitedByExplosion True if another explosion caused this ignition.
* @param player The player who ignited the TNT.
*/
public static void igniteBlock(Block tntBlock, boolean ignitedByExplosion) {
public static void igniteBlock(
Block tntBlock, boolean ignitedByExplosion, GlowPlayer player) {
tntBlock.setType(Material.AIR);
World world = tntBlock.getWorld();
GlowTntPrimed tnt = (GlowTntPrimed) world
.spawnEntity(tntBlock.getLocation().add(0.5, 0, 0.5), EntityType.PRIMED_TNT);
tnt.setSource(player);
tnt.setIgnitedByExplosion(ignitedByExplosion);
world.playSound(tntBlock.getLocation(), Sound.ENTITY_TNT_PRIMED, 1, 1);
}

/**
* Convert a TNT block into a primed TNT entity.
*
* @param tntBlock The block to ignite.
* @param ignitedByExplosion True if another explosion caused this ignition.
*/
public static void igniteBlock(Block tntBlock, boolean ignitedByExplosion) {
igniteBlock(tntBlock, ignitedByExplosion, null);
}

@Override
public void afterPlace(GlowPlayer player, GlowBlock block, ItemStack holding,
GlowBlockState oldState) {
Expand All @@ -44,7 +57,7 @@ public void onNearBlockChanged(GlowBlock block, BlockFace face, GlowBlock change
@Override
public void updatePhysics(GlowBlock me) {
if (me.isBlockIndirectlyPowered()) {
igniteBlock(me, false);
igniteBlock(me, false, null);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public boolean onToolRightClick(GlowPlayer player, GlowBlock target, BlockFace f
return true;
}
if (target.getType() == Material.TNT) {
fireTnt(target);
fireTnt(target, player);
return true;
}
if (target.isFlammable() || target.getType().isOccluding()) {
Expand All @@ -49,8 +49,8 @@ private void fireNetherPortal(GlowBlock target, BlockFace face) {
}
}

private void fireTnt(GlowBlock tnt) {
BlockTnt.igniteBlock(tnt, false);
private void fireTnt(GlowBlock tnt,GlowPlayer player) {
BlockTnt.igniteBlock(tnt, false, player);
}

private boolean setBlockOnFire(GlowPlayer player, GlowBlock clicked, BlockFace face,
Expand Down
77 changes: 76 additions & 1 deletion src/main/java/net/glowstone/entity/GlowLivingEntity.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import net.glowstone.entity.meta.MetadataIndex;
import net.glowstone.entity.objects.GlowExperienceOrb;
import net.glowstone.entity.objects.GlowLeashHitch;
import net.glowstone.entity.passive.GlowWolf;
import net.glowstone.entity.projectile.GlowProjectile;
import net.glowstone.inventory.EquipmentMonitor;
import net.glowstone.net.GlowSession;
Expand Down Expand Up @@ -97,6 +98,15 @@ public abstract class GlowLivingEntity extends GlowEntity implements LivingEntit
@Getter
@Setter
private Player killer;

/**
* The tick that the entity got hit by a player.
* The default value was set to -101 rather than 0.
*/
@Getter
@Setter
private int playerDamageTick = -101;

/**
* Whether entities can collide with this entity.
*/
Expand Down Expand Up @@ -815,7 +825,8 @@ public void setHealth(double health) {
if (world.getGameRuleMap().getBoolean("doMobLoot")) {
LootData data = LootingManager.generate(this);
deathEvent.getDrops().addAll(data.getItems());
if (data.getExperience() > 0) {
// Only drop experience when hit by a player within 5 seconds (100 game ticks)
if (ticksLived - playerDamageTick <= 100 && data.getExperience() > 0) {
// split experience
Integer[] values = ExperienceSplitter.cut(data.getExperience());
for (Integer exp : values) {
Expand Down Expand Up @@ -891,6 +902,14 @@ public void damage(double amount, Entity source, DamageCause cause) {
// apply damage
amount = event.getFinalDamage();
lastDamage = amount;

if (isPlayerHit(source)) {
playerDamageTick = ticksLived;
if (health - amount <= 0) {
killer = determinePlayer(source);
}
}

setHealth(health - amount);
playEffect(EntityEffect.HURT);

Expand All @@ -915,6 +934,62 @@ public void damage(double amount, Entity source, DamageCause cause) {
setLastDamager(source);
}

/**
* Checks if the source of damage was caused by a player.
*
* @param source The source of damage
* @return true if the source of damage was caused by a player, false otherwise.
*/
private boolean isPlayerHit(Entity source) {
// If directly damaged by a player
if (source instanceof GlowPlayer) {
return true;
}

// If damaged by a TNT ignited by a player
if (source instanceof GlowTntPrimed) {
GlowPlayer player = (GlowPlayer)((GlowTntPrimed) source).getSource();
return
player != null
&& (player.getGameMode() == GameMode.SURVIVAL
|| player.getGameMode() == GameMode.ADVENTURE);
}

// If damaged by a tamed wolf
if (source instanceof GlowWolf) {
return ((GlowWolf) source).isTamed();
}

// All other cases
return false;
}

/**
* Determines the player who did the damage from source of damage.
*
* @param source The incoming source of damage
* @return Player object if the source of damage was caused by a player, null otherwise.
*/
private Player determinePlayer(Entity source) {
// If been killed by an ignited tnt
if (source instanceof GlowTntPrimed) {
return (Player)((GlowTntPrimed) source).getSource();
}

// If been killed by a player
if (source instanceof GlowPlayer) {
return (Player) source;
}

// If been killed by a tamed wolf
if (source instanceof GlowWolf) {
return (Player)((GlowWolf) source).getOwner();
}

// All other cases
return null;
}

@Override
public double getMaxHealth() {
return attributeManager.getPropertyValue(Key.KEY_MAX_HEALTH);
Expand Down
13 changes: 12 additions & 1 deletion src/main/java/net/glowstone/entity/GlowTntPrimed.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,19 @@ public class GlowTntPrimed extends GlowExplosive implements TNTPrimed {
@Getter
@Setter
private int fuseTicks;
@Setter
private Entity source;

/**
* Get the player that ignited the TNT.
*
* @return Player that ignited the TNT
*/
public GlowPlayer getPlayer() {
Entity source = getSource();
return (source instanceof GlowPlayer) ? (GlowPlayer) source : null;
}

/**
* Creates a primed TNT block.
*
Expand Down Expand Up @@ -98,7 +109,7 @@ public List<Message> createSpawnMessage() {

@Override
public final Entity getSource() {
return source.isValid() ? source : null;
return (source != null && source.isValid()) ? source : null;
}

@Override
Expand Down
3 changes: 2 additions & 1 deletion src/main/java/net/glowstone/entity/projectile/GlowArrow.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import lombok.Getter;
import lombok.Setter;
import net.glowstone.block.GlowBlock;
import net.glowstone.block.blocktype.BlockTnt;
import net.glowstone.entity.meta.MetadataIndex;
import net.glowstone.net.message.play.entity.SpawnObjectMessage;
Expand Down Expand Up @@ -81,7 +82,7 @@ public void collide(Block block) {
setFireTicks(0); // Arrows stop burning when they land, and ignite only TNT
switch (block.getType()) {
case TNT:
BlockTnt.igniteBlock(block, false);
BlockTnt.igniteBlock((GlowBlock) block, false);
break;
case WOOD_BUTTON:
case STONE_BUTTON:
Expand Down

0 comments on commit 89a3784

Please sign in to comment.