Skip to content
This repository has been archived by the owner on May 3, 2018. It is now read-only.

Commit

Permalink
updates and release for 0.0.1-preR10
Browse files Browse the repository at this point in the history
  • Loading branch information
DefinitlyEvil committed Jan 7, 2015
1 parent 85f796f commit 50d9f69
Show file tree
Hide file tree
Showing 82 changed files with 2,505 additions and 745 deletions.
3 changes: 1 addition & 2 deletions ChangedClasses.txt
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
====[The Class We Edited/Changed]====
net.glowstone.GlowServer: Added dragonet instance getter, set dragonet instance to a private variable.
net.glowstone.GlowServer: Changed getVersion() and getBukkitVersion()
net.glowstone.GlowServer: Added stopping MCPE server call into shutdown() method

net.glowstone.scheduler.GlowScheduler: Added tick trigger

net.glowstone.entity.GlowPlayer: Removed final

net.glowstone.net.handler.login: Change PlayerProfile to generate as same as offline players

net.glowstone.net.GlowSession: Removed final
net.glowstone.net.GlowSession: Changed player variable into protected
net.glowstone.net.GlowSession: Added @Getter at hostname variable
Expand Down
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ buildscript {
maven { url "http://repo.glowstone.net/content/groups/public/" }
}
dependencies {
classpath 'com.github.jengelman.gradle.plugins:shadow:1.1.2'
classpath 'com.github.jengelman.gradle.plugins:shadow:1.2.0'
classpath 'net.glowstone:remapper:1.1'
classpath 'org.ow2.asm:asm:5.0.3'
}
Expand Down
345 changes: 345 additions & 0 deletions src/main/java/net/glowstone/Explosion.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,345 @@
package net.glowstone;

import net.glowstone.block.GlowBlock;
import net.glowstone.block.ItemTable;
import net.glowstone.block.blocktype.BlockTNT;
import net.glowstone.entity.GlowEntity;
import net.glowstone.entity.GlowHumanEntity;
import net.glowstone.entity.GlowLivingEntity;
import net.glowstone.entity.GlowPlayer;
import net.glowstone.net.message.play.game.ExplosionMessage;
import org.bukkit.*;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.LivingEntity;
import org.bukkit.event.block.BlockIgniteEvent;
import org.bukkit.event.entity.EntityDamageEvent;
import org.bukkit.event.entity.EntityExplodeEvent;
import org.bukkit.util.BlockVector;
import org.bukkit.util.Vector;

import java.util.*;

public final class Explosion {

public static final int POWER_TNT = 4;
public static final int POWER_BED = 5;
public static final int POWER_CREEPER = 3;
public static final int POWER_CHARGED_CREEPER = 6;
public static final int POWER_GHAST = 1;
public static final int POWER_WITHER_SKULL = 1;
public static final int POWER_WITHER_CREATION = 7;
public static final int POWER_ENDER_CRYSTAL = 6;

private float power;
private final Entity source;
private final Location location;
private final boolean incendiary;
private final boolean breakBlocks;
private final GlowWorld world;
private float yield = 0.3f;

private static final Random random = new Random();
private final ItemTable itemTable;

/**
* Creates a new explosion
* @param source The entity causing this explosion
* @param world The world this explosion is in
* @param x The X location of the explosion
* @param y The Y location of the explosion
* @param z The Z location of the explosion
* @param power The power of the explosion
* @param incendiary Whether or not blocks should be set on fire
* @param breakBlocks Whether blocks should break through this explosion
*/
public Explosion(Entity source, GlowWorld world, double x, double y, double z, float power, boolean incendiary, boolean breakBlocks) {
this(source, new Location(world, x, y, z), power, incendiary, breakBlocks);
}

/**
* Creates a new explosion
* @param source The entity causing this explosion
* @param location The location this explosion is occuring at. Must contain a GlowWorld
* @param power The power of the explosion
* @param incendiary Whether or not blocks should be set on fire
* @param breakBlocks Whether blocks should break through this explosion
*/
public Explosion(Entity source, Location location, float power, boolean incendiary, boolean breakBlocks) {
if (!(location.getWorld() instanceof GlowWorld)) {
throw new IllegalArgumentException("Supplied location does not have a valid GlowWorld");
}

this.source = source;
this.location = location.clone();
this.power = power;
this.incendiary = incendiary;
this.breakBlocks = breakBlocks;
this.world = (GlowWorld) location.getWorld();
itemTable = ItemTable.instance();
}

public boolean explodeWithEvent() {
if (power < 0.1f)
return true;

Set<BlockVector> droppedBlocks = calculateBlocks();

EntityExplodeEvent event = EventFactory.callEvent(new EntityExplodeEvent(source, location, toBlockList(droppedBlocks), yield));
if (event.isCancelled()) return false;

this.yield = event.getYield();

playOutSoundAndParticles();

List<Block> blocks = toBlockList(droppedBlocks);

for (Block block : blocks) {
handleBlockExplosion((GlowBlock) block);
}

if (incendiary) {
for (Block block : blocks) {
setBlockOnFire((GlowBlock) block);
}
}

Collection<GlowPlayer> affectedPlayers = damageEntities();
for (GlowPlayer player : affectedPlayers) {
playOutExplosion(player, droppedBlocks);
}

return true;
}

///////////////////////////////////////////////////
// Calculate all the dropping blocks

private Set<BlockVector> calculateBlocks() {
if (!breakBlocks)
return new HashSet<>();

Set<BlockVector> blocks = new HashSet<>();

final int value = 16;

for (int x = 0; x < value; x++) {
for (int y = 0; y < value; y++) {
for (int z = 0; z < value; z++) {
if (!(x == 0 || x == value - 1 || y == 0 || y == value - 1 || z == 0 || z == value - 1)) {
continue;
}
calculateRay(x, y, z, blocks);
}
}
}

return blocks;
}

private void calculateRay(int ox, int oy, int oz, Collection<BlockVector> result) {
double x = ox / 7.5 - 1;
double y = oy / 7.5 - 1;
double z = oz / 7.5 - 1;
Vector direction = new Vector(x, y, z);
direction.normalize();
direction.multiply(0.3f); // 0.3 blocks away with each step

Location current = location.clone();

float currentPower = calculateStartPower();

while (currentPower > 0) {
GlowBlock block = world.getBlockAt(current);

if (block.getType() != Material.AIR) {
double blastDurability = getBlastDurability(block) / 5d;
blastDurability += 0.3F;
blastDurability *= 0.3F;
currentPower -= blastDurability;

if (currentPower > 0) {
result.add(new BlockVector(block.getX(), block.getY(), block.getZ()));
}
}

current.add(direction);
currentPower -= 0.225f;
}
}

private void handleBlockExplosion(GlowBlock block) {
if (block.getType() == Material.AIR) {
return;
} else if (block.getType() == Material.TNT) {
BlockTNT.igniteBlock(block, true);
return;
}

block.breakNaturally(yield);
}

private float calculateStartPower() {
float rand = random.nextFloat();
rand *= 0.6F; // (max - 0.7)
rand += 0.7; // min
return rand * power;
}

private double getBlastDurability(GlowBlock block) {
// TODO: return the block's blast durability
return 2.5;
}

private List<Block> toBlockList(Collection<BlockVector> locs) {
List<Block> blocks = new ArrayList<>(locs.size());
for (BlockVector location : locs)
blocks.add(world.getBlockAt(location.getBlockX(), location.getBlockY(), location.getBlockZ()));
return blocks;
}

private void setBlockOnFire(GlowBlock block) {
if (random.nextInt(3) != 0)
return;

Block below = block.getRelative(BlockFace.DOWN);
// TODO: check for flammable blocks
Material belowType = below.getType();
if (belowType == Material.AIR || belowType == Material.FIRE) return;

BlockIgniteEvent event = EventFactory.callEvent(new BlockIgniteEvent(block, BlockIgniteEvent.IgniteCause.EXPLOSION, source));
if (event.isCancelled())
return;

block.setType(Material.FIRE);
}

/////////////////////////////////////////
// Damage entities

private Collection<GlowPlayer> damageEntities() {
float power = this.power;
this.power *= 2f;

Collection<GlowPlayer> affectedPlayers = new ArrayList<>();

Collection<GlowLivingEntity> entities = getNearbyEntities();
for (GlowLivingEntity entity : entities) {
double disDivPower = distanceTo(entity) / (double) this.power;
if (disDivPower > 1.0D) continue;

Vector vecDistance = distanceToHead(entity);
if (vecDistance.length() == 0.0) continue;

vecDistance.normalize();

double basicDamage = calculateDamage(entity, disDivPower);
int explosionDamage = (int) ((basicDamage * basicDamage + basicDamage) * 4 * (double) power + 1.0D);

if (!(entity instanceof GlowHumanEntity && ((GlowHumanEntity) entity).getGameMode() == GameMode.CREATIVE)) {
EntityDamageEvent.DamageCause damageCause;
if (source == null || source.getType() == EntityType.PRIMED_TNT) {
damageCause = EntityDamageEvent.DamageCause.BLOCK_EXPLOSION;
} else {
damageCause = EntityDamageEvent.DamageCause.ENTITY_EXPLOSION;
}
entity.damage(explosionDamage, source, damageCause);
}

double enchantedDamage = calculateEnchantedDamage(basicDamage, entity);
vecDistance.multiply(enchantedDamage);

Vector currentVelocity = entity.getVelocity();
currentVelocity.add(vecDistance);
entity.setVelocity(currentVelocity);

if (entity instanceof GlowPlayer) {
affectedPlayers.add((GlowPlayer) entity);
}
}

this.power = power;

return affectedPlayers;
}

private double calculateEnchantedDamage(double basicDamage, GlowLivingEntity entity) {
int level = 0; // TODO: calculate explosion protection level of entity's equipment

if (level > 0) {
float sub = level * 0.15f;
double damage = basicDamage * sub;
damage = Math.floor(damage);
return basicDamage - damage;
}

return basicDamage;
}

private double calculateDamage(GlowEntity entity, double disDivPower) {
double damage = world.rayTrace(location, entity);
return (damage * (1D - disDivPower));
}

private Collection<GlowLivingEntity> getNearbyEntities() {
// TODO: fetch only necessary entities
List<LivingEntity> entities = world.getLivingEntities();
List<GlowLivingEntity> nearbyEntities = new ArrayList<>();

for (LivingEntity entity : entities) {
if (distanceTo(entity) / (double) power < 1.) {
nearbyEntities.add((GlowLivingEntity) entity);
}
}

return nearbyEntities;
}

private double distanceTo(LivingEntity entity) {
return location.clone().subtract(entity.getLocation()).length();
}

private Vector distanceToHead(LivingEntity entity) {
return entity.getLocation().clone().subtract(location.clone().subtract(0, entity.getEyeHeight(), 0)).toVector();
}

///////////////////////////////////////
// Visualize
private void playOutSoundAndParticles() {
world.playSound(location, Sound.EXPLODE, 4, (1.0F + (random.nextFloat() - random.nextFloat()) * 0.2F) * 0.7F);

if (this.power >= 2.0F && this.breakBlocks) {
// send huge explosion
world.showParticle(location, Particle.EXPLOSION_HUGE, 0, 0, 0, 0, 0);
} else {
// send large explosion
world.showParticle(location, Particle.EXPLOSION_LARGE, 0, 0, 0, 0, 0);
}
}

private void playOutExplosion(GlowPlayer player, Iterable<BlockVector> blocks) {
Collection<ExplosionMessage.Record> records = new ArrayList<>();

Location clientLoc = location.clone();
clientLoc.setX((int) clientLoc.getX());
clientLoc.setY((int) clientLoc.getY());
clientLoc.setZ((int) clientLoc.getZ());

for (BlockVector block : blocks) {
byte x = (byte) (block.getBlockX() - clientLoc.getBlockX());
byte y = (byte) (block.getBlockY() - clientLoc.getBlockY());
byte z = (byte) (block.getBlockZ() - clientLoc.getBlockZ());
records.add(new ExplosionMessage.Record(x, y, z));
}

Vector velocity = player.getVelocity();
ExplosionMessage message = new ExplosionMessage((float) location.getX(), (float) location.getY(), (float) location.getZ(),
5,
(float) velocity.getX(), (float) velocity.getY(), (float) velocity.getZ(),
records);

player.getSession().send(message);
}
}
Loading

0 comments on commit 50d9f69

Please sign in to comment.