Skip to content
Open
Show file tree
Hide file tree
Changes from 2 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).damageBlock(1, block, EntityDamageEvent.DamageCause.FIRE);
} else {
entity.damage(1.0, EntityDamageEvent.DamageCause.FIRE);
}
}
}
43 changes: 33 additions & 10 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 @@ -1442,6 +1462,9 @@ public void damage(double amount, DamageCause cause) {
damage(amount, null, cause);
}

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

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

Expand Down
80 changes: 72 additions & 8 deletions src/main/java/net/glowstone/entity/GlowLivingEntity.java
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@
import org.bukkit.entity.Projectile;
import org.bukkit.event.entity.EntityAirChangeEvent;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
import org.bukkit.event.entity.EntityDamageByBlockEvent;
import org.bukkit.event.entity.EntityDamageEvent;
import org.bukkit.event.entity.EntityDamageEvent.DamageCause;
import org.bukkit.event.entity.EntityDeathEvent;
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);
damageBlock(1, eyeBlock, DamageCause.DROWNING);
}
}
} else {
remainingAir = maximumAir;
}

if (isTouchingMaterial(Material.CACTUS)) {
damage(1, DamageCause.CONTACT);
for(Block block : getTouchingBlocks()) {
if(block.getType() == Material.CACTUS) {
damageBlock(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);
damageBlock(1, eyeBlock, DamageCause.SUFFOCATION);
}

// fire and lava damage
if (getLocation().getBlock().getType() == Material.FIRE) {
damage(1, DamageCause.FIRE);
damageBlock(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);
damageBlock(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) {
damageBlock(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,50 @@ public void setHealth(double health) {
}
}

@Override
public void damageBlock(double amount, Block block, DamageCause cause) {
if (!canTakeDamage() || !canTakeDamage(cause)) {
return;
} else {
noDamageTicks = maximumNoDamageTicks;
}

// 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);

// fire event
EntityDamageByBlockEvent event = EventFactory.getInstance().onEntityDamage(
new EntityDamageByBlockEvent(block, this, cause, amount));

if (event.isCancelled()) {
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 (!canTakeDamage() || !canTakeDamage(cause)) {
return;
} else {
noDamageTicks = maximumNoDamageTicks;
Expand Down