Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement EntityDamageByBlockEvent firing #1065

Open
wants to merge 8 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion src/main/java/net/glowstone/block/blocktype/BlockMagma.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package net.glowstone.block.blocktype;

import net.glowstone.block.GlowBlock;
import net.glowstone.entity.GlowEntity;
import net.glowstone.inventory.ToolType;
import org.bukkit.Material;
import org.bukkit.entity.LivingEntity;
Expand All @@ -14,6 +15,10 @@ public BlockMagma() {

@Override
public void onEntityStep(GlowBlock block, LivingEntity entity) {
entity.damage(1.0, EntityDamageEvent.DamageCause.FIRE);
if (entity instanceof GlowEntity) {
((GlowEntity) entity).damage(1, block, EntityDamageEvent.DamageCause.FIRE);
} else {
entity.damage(1.0, EntityDamageEvent.DamageCause.FIRE);
}
}
}
47 changes: 35 additions & 12 deletions src/main/java/net/glowstone/entity/GlowEntity.java
Original file line number Diff line number Diff line change
Expand Up @@ -982,22 +982,42 @@ public boolean isTouchingMaterial(Material material) {
}
}
} else {
// bounding box-based calculation
Vector min = boundingBox.minCorner;
Vector max = boundingBox.maxCorner;
for (int x = min.getBlockX(); x <= max.getBlockX(); ++x) {
for (int y = min.getBlockY(); y <= max.getBlockY(); ++y) {
for (int z = min.getBlockZ(); z <= max.getBlockZ(); ++z) {
if (world.getBlockTypeIdAt(x, y, z) == material.getId()) {
return true;
}
}
for (Block touchingBlock : getTouchingBlocks()) {
if (touchingBlock.getType().getId() == material.getId()) {
return true;
}
}
}
return false;
}

/**
* Gets a list containing all the blocks a player is touching
*
* <p>If the entity has not a defined bounding box, the list will be empty.
*
* @return the list of blocks a player is touching
*/
public List<Block> getTouchingBlocks() {
if (boundingBox == null) {
return Collections.emptyList();
}

List<Block> blocks = new ArrayList<>();

// bounding box-based calculation
Vector min = boundingBox.minCorner;
Vector max = boundingBox.maxCorner;
for (int x = min.getBlockX(); x <= max.getBlockX(); ++x) {
for (int y = min.getBlockY(); y <= max.getBlockY(); ++y) {
for (int z = min.getBlockZ(); z <= max.getBlockZ(); ++z) {
blocks.add(world.getBlockAt(x, y, z));
}
}
}
return blocks;
}

protected final void setBoundingBox(double xz, double y) {
boundingBox = new EntityBoundingBox(xz, y);
updateBoundingBox();
Expand Down Expand Up @@ -1431,15 +1451,18 @@ public void setMetadata(String metadataKey, MetadataValue newMetadataValue) {
}

public void damage(double amount) {
damage(amount, null, DamageCause.CUSTOM);
damage(amount, (Entity) null, DamageCause.CUSTOM);
}

public void damage(double amount, Entity source) {
damage(amount, source, DamageCause.CUSTOM);
}

public void damage(double amount, DamageCause cause) {
damage(amount, null, cause);
damage(amount, (Entity) null, cause);
}

public void damage(double amount, Block block, DamageCause cause) {
}

public void damage(double amount, Entity source, DamageCause cause) {
Expand Down
102 changes: 87 additions & 15 deletions src/main/java/net/glowstone/entity/GlowLivingEntity.java
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@
import org.bukkit.entity.Player;
import org.bukkit.entity.Projectile;
import org.bukkit.event.entity.EntityAirChangeEvent;
import org.bukkit.event.entity.EntityDamageByBlockEvent;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
import org.bukkit.event.entity.EntityDamageEvent;
import org.bukkit.event.entity.EntityDamageEvent.DamageCause;
Expand Down Expand Up @@ -299,39 +300,46 @@ public void pulse() {
--noDamageTicks;
}

Material mat = getEyeLocation().getBlock().getType();
Block eyeBlock = getEyeLocation().getBlock();
Material mat = eyeBlock.getType();
// breathing
if (mat == Material.WATER || mat == Material.STATIONARY_WATER) {
if (canTakeDamage(DamageCause.DROWNING)) {
--remainingAir;
if (remainingAir <= -20) {
remainingAir = 0;
damage(1, DamageCause.DROWNING);
damage(1, eyeBlock, DamageCause.DROWNING);
}
}
} else {
remainingAir = maximumAir;
}

if (isTouchingMaterial(Material.CACTUS)) {
damage(1, DamageCause.CONTACT);
for (Block block : getTouchingBlocks()) {
if (block.getType() == Material.CACTUS) {
damage(1, block, DamageCause.CONTACT);
break;
}
}
}

if (location.getY() < -64) { // no canTakeDamage call - pierces through game modes
damage(4, DamageCause.VOID);
}

if (isWithinSolidBlock()) {
damage(1, DamageCause.SUFFOCATION);
damage(1, eyeBlock, DamageCause.SUFFOCATION);
}

// fire and lava damage
if (getLocation().getBlock().getType() == Material.FIRE) {
damage(1, DamageCause.FIRE);
damage(1, getLocation().getBlock(), DamageCause.FIRE);
// not applying additional fire ticks after dying in fire
stoodInFire = !isDead();
} else if (getLocation().getBlock().getType() == Material.LAVA
|| getLocation().getBlock().getType() == Material.STATIONARY_LAVA) {
damage(4, DamageCause.LAVA);
damage(4, getLocation().getBlock(), DamageCause.LAVA);
if (swamInLava) {
setFireTicks(getFireTicks() + 2);
} else {
Expand All @@ -341,7 +349,12 @@ public void pulse() {
} else if (isTouchingMaterial(Material.FIRE)
|| isTouchingMaterial(Material.LAVA)
|| isTouchingMaterial(Material.STATIONARY_LAVA)) {
damage(1, DamageCause.FIRE);
for (Block block : getTouchingBlocks()) {
if (block.getType() == Material.FIRE || block.getType() == Material.LAVA || block.getType() == Material.STATIONARY_LAVA) {
damage(1, block, DamageCause.CONTACT);
break;
}
}
// increment the ticks stood adjacent to fire or lava
adjacentBurnTicks++;
if (adjacentBurnTicks > 40) {
Expand Down Expand Up @@ -620,6 +633,17 @@ public boolean canTakeDamage(DamageCause damageCause) {
return true;
}

/**
* Get whether this entity should take damage from any source.
*
* <p>Usually used to check environmental sources such as drowning.
*
* @return whether this entity can take damage
*/
public boolean canTakeDamage() {
return noDamageTicks == 0 && health > 0 && !isInvulnerable();
}

/**
* Get whether of not this entity is an arthropod.
*
Expand Down Expand Up @@ -936,10 +960,64 @@ public void setHealth(double health) {
}
}

private boolean callDamageEvent(EntityDamageEvent event) {
if (event.isCancelled()) {
return true;
}
// apply damage
lastDamage = event.getFinalDamage();
return false;
}

private double getEffectiveDamage(double amount) {
// armor damage protection
// formula source: http://minecraft.gamepedia.com/Armor#Damage_Protection
double defensePoints = getAttributeManager().getPropertyValue(Key.KEY_ARMOR);
double toughness = getAttributeManager().getPropertyValue(Key.KEY_ARMOR_TOUGHNESS);
return amount * (1 - Math.min(20.0,
Math.max(defensePoints / 5.0,
defensePoints - amount / (2.0 + toughness / 4.0))) / 25);
}

@Override
public void damage(double amount, Block block, DamageCause cause) {
if (noDamageTicks > 0 || health <= 0 || isInvulnerable() || !canTakeDamage(cause)) {
return;
} else {
noDamageTicks = maximumNoDamageTicks;
}

amount = getEffectiveDamage(amount);


// fire event
EntityDamageByBlockEvent event = EventFactory.getInstance().onEntityDamage(
ytnoos marked this conversation as resolved.
Show resolved Hide resolved
new EntityDamageByBlockEvent(block, this, cause, amount));

if (callDamageEvent(event)) {
return;
}

// apply damage
amount = event.getFinalDamage();
lastDamage = amount;

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

// play sounds, handle death
if (health > 0) {
Sound hurtSound = getHurtSound();
if (hurtSound != null && !isSilent()) {
world.playSound(location, hurtSound, getSoundVolume(), getSoundPitch());
}
}
}

@Override
public void damage(double amount, Entity source, DamageCause cause) {
// invincibility timer
if (noDamageTicks > 0 || health <= 0 || !canTakeDamage(cause) || isInvulnerable()) {
if (noDamageTicks > 0 || health <= 0 || isInvulnerable() || !canTakeDamage(cause)) {
return;
} else {
noDamageTicks = maximumNoDamageTicks;
Expand All @@ -962,13 +1040,7 @@ public void damage(double amount, Entity source, DamageCause cause) {
}
}

// armor damage protection
// formula source: http://minecraft.gamepedia.com/Armor#Damage_Protection
double defensePoints = getAttributeManager().getPropertyValue(Key.KEY_ARMOR);
double toughness = getAttributeManager().getPropertyValue(Key.KEY_ARMOR_TOUGHNESS);
amount = amount * (1 - Math.min(20.0,
Math.max(defensePoints / 5.0,
defensePoints - amount / (2.0 + toughness / 4.0))) / 25);
amount = getEffectiveDamage(amount);

// fire event
EntityDamageEvent event = EventFactory.getInstance().onEntityDamage(source == null
Expand Down