Instances can now create explosions

This commit is contained in:
jglrxavpok 2020-05-14 15:33:36 +02:00
parent 498384d2f4
commit 041f9ffb4d
3 changed files with 140 additions and 0 deletions

View File

@ -0,0 +1,75 @@
package net.minestom.server.instance;
import net.minestom.server.network.packet.server.play.ExplosionPacket;
import net.minestom.server.utils.BlockPosition;
import java.util.List;
/**
* Abstract explosion.
* Instance can provide a supplier through {@link Instance#setExplosionSupplier}
*/
public abstract class Explosion {
private final float centerX;
private final float centerY;
private final float centerZ;
private final float strength;
public Explosion(float centerX, float centerY, float centerZ, float strength) {
this.centerX = centerX;
this.centerY = centerY;
this.centerZ = centerZ;
this.strength = strength;
}
public float getStrength() {
return strength;
}
public float getCenterX() {
return centerX;
}
public float getCenterY() {
return centerY;
}
public float getCenterZ() {
return centerZ;
}
/**
* Prepares the list of blocks that will be broken. Also pushes and damage entities affected by this explosion
* @param instance instance to perform this explosion in
* @return list of blocks that will be broken.
*/
protected abstract List<BlockPosition> prepare(Instance instance);
/**
* Performs the explosion and send the corresponding packet
* @param instance instance to perform this explosion in
*/
public void apply(Instance instance) {
List<BlockPosition> blocks = prepare(instance);
ExplosionPacket packet = new ExplosionPacket();
packet.x = getCenterX();
packet.y = getCenterY();
packet.z = getCenterZ();
packet.radius = getStrength();
packet.playerMotionX = 0.0f; // TODO: figure out why this is here
packet.playerMotionY = 0.0f; // TODO: figure out why this is here
packet.playerMotionZ = 0.0f; // TODO: figure out why this is here
packet.records = new byte[3*blocks.size()];
for (int i = 0; i < blocks.size(); i++) {
BlockPosition pos = blocks.get(i);
byte x = (byte) (pos.getX()-Math.floor(getCenterX()));
byte y = (byte) (pos.getY()-Math.floor(getCenterY()));
byte z = (byte) (pos.getZ()-Math.floor(getCenterZ()));
packet.records[i*3+0] = x;
packet.records[i*3+1] = y;
packet.records[i*3+2] = z;
}
}
}

View File

@ -0,0 +1,19 @@
package net.minestom.server.instance;
import net.minestom.server.data.Data;
@FunctionalInterface
public interface ExplosionSupplier {
/**
* Creates a new explosion
* @param centerX center of the explosion
* @param centerY center of the explosion
* @param centerZ center of the explosion
* @param strength strength of the explosion
* @param additionalData data passed via {@link Instance#explode)}. Can be null
* @return Explosion object representing the algorithm to use
*/
Explosion createExplosion(float centerX, float centerY, float centerZ, float strength, Data additionalData);
}

View File

@ -50,6 +50,7 @@ public abstract class Instance implements BlockModifier, EventHandler, DataConta
private UUID uniqueId;
private Data data;
private ExplosionSupplier explosionSupplier;
protected Instance(UUID uniqueId, Dimension dimension) {
this.uniqueId = uniqueId;
@ -404,4 +405,49 @@ public abstract class Instance implements BlockModifier, EventHandler, DataConta
*/
public void tick(long time) {
}
/**
* Creates an explosion at the given position with the given strength. The algorithm used to compute damages is provided by {@link #getExplosionSupplier()}.
* If no {@link ExplosionSupplier} was supplied, this method will throw an {@link IllegalStateException}
* @param centerX
* @param centerY
* @param centerZ
* @param strength
*/
public void explode(float centerX, float centerY, float centerZ, float strength) {
explode(centerX, centerY, centerZ, strength, null);
}
/**
* Creates an explosion at the given position with the given strength. The algorithm used to compute damages is provided by {@link #getExplosionSupplier()}.
* If no {@link ExplosionSupplier} was supplied, this method will throw an {@link IllegalStateException}
* @param centerX
* @param centerY
* @param centerZ
* @param strength
* @param additionalData data to pass to the explosion supplier
*/
public void explode(float centerX, float centerY, float centerZ, float strength, Data additionalData) {
ExplosionSupplier explosionSupplier = getExplosionSupplier();
if(explosionSupplier == null)
throw new IllegalStateException("Tried to create an explosion with no explosion supplier");
Explosion explosion = explosionSupplier.createExplosion(centerX, centerY, centerZ, strength, additionalData);
explosion.apply(this);
}
/**
* Return the registered explosion supplier, or null if none was provided
* @return
*/
public ExplosionSupplier getExplosionSupplier() {
return explosionSupplier;
}
/**
* Registers the explosion supplier to use in this instance
* @param supplier
*/
public void setExplosionSupplier(ExplosionSupplier supplier) {
this.explosionSupplier = supplier;
}
}