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

feat: LivingEntity fire overhaul #2122

Merged
merged 2 commits into from
May 27, 2024
Merged
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
12 changes: 0 additions & 12 deletions src/main/java/net/minestom/server/entity/Entity.java
Original file line number Diff line number Diff line change
Expand Up @@ -1062,18 +1062,6 @@ public boolean isOnFire() {
return this.entityMeta.isOnFire();
}

/**
* Sets the entity in fire visually.
* <p>
* WARNING: if you want to apply damage or specify a duration,
* see {@link LivingEntity#setFireForDuration(int, TemporalUnit)}.
*
* @param fire should the entity be set in fire
*/
public void setOnFire(boolean fire) {
this.entityMeta.setOnFire(fire);
}

/**
* Gets if the entity is sneaking.
* <p>
Expand Down
102 changes: 33 additions & 69 deletions src/main/java/net/minestom/server/entity/LivingEntity.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@
import net.minestom.server.event.EventDispatcher;
import net.minestom.server.event.entity.EntityDamageEvent;
import net.minestom.server.event.entity.EntityDeathEvent;
import net.minestom.server.event.entity.EntityFireEvent;
import net.minestom.server.event.entity.EntityFireExtinguishEvent;
import net.minestom.server.event.entity.EntitySetFireEvent;
import net.minestom.server.event.item.EntityEquipEvent;
import net.minestom.server.event.item.PickupItemEvent;
import net.minestom.server.instance.EntityTracker;
Expand Down Expand Up @@ -61,14 +62,9 @@ public class LivingEntity extends Entity implements EquipmentHandler {
protected boolean invulnerable;

/**
* Time at which this entity must be extinguished
* Ticks until this entity must be extinguished
*/
private long fireExtinguishTime;

/**
* Period, in ms, between two fire damage applications
*/
private long fireDamagePeriod = 1000L;
private int remainingFireTicks;

private Team team;

Expand Down Expand Up @@ -186,8 +182,9 @@ private ItemStack getEquipmentItem(@NotNull ItemStack itemStack, @NotNull Equipm

@Override
public void update(long time) {
if (isOnFire() && time > fireExtinguishTime) {
setOnFire(false);
// Fire
if (remainingFireTicks > 0 && --remainingFireTicks == 0) {
EventDispatcher.callCancellable(new EntityFireExtinguishEvent(this, true), () -> entityMeta.setOnFire(false));
}

// Items picking
Expand Down Expand Up @@ -272,44 +269,40 @@ public void kill() {
}

/**
* Sets fire to this entity for a given duration.
* Gets the amount of ticks this entity is on fire for.
*
* @param duration duration in ticks of the effect
* @return the remaining duration of fire in ticks, 0 if not on fire
*/
public void setFireForDuration(int duration) {
setFireForDuration(duration, TimeUnit.SERVER_TICK);
public int getFireTicks() {
return remainingFireTicks;
}

/**
* Sets fire to this entity for a given duration.
* Sets this entity on fire for the given ticks.
*
* @param duration duration of the effect
* @param temporalUnit unit used to express the duration
* @see #setOnFire(boolean) if you want it to be permanent without any event callback
*/
public void setFireForDuration(int duration, TemporalUnit temporalUnit) {
setFireForDuration(Duration.of(duration, temporalUnit));
}
* @param ticks duration of fire in ticks
*/
public void setFireTicks(int ticks) {
int fireTicks = Math.max(0, ticks);
if (fireTicks > 0) {
EntitySetFireEvent entitySetFireEvent = new EntitySetFireEvent(this, ticks);
EventDispatcher.call(entitySetFireEvent);
if (entitySetFireEvent.isCancelled()) return;

fireTicks = Math.max(0, entitySetFireEvent.getFireTicks());
if (fireTicks > 0) {
remainingFireTicks = fireTicks;
entityMeta.setOnFire(true);
return;
}
}

/**
* Sets fire to this entity for a given duration.
*
* @param duration duration of the effect
* @see #setOnFire(boolean) if you want it to be permanent without any event callback
*/
public void setFireForDuration(Duration duration) {
EntityFireEvent entityFireEvent = new EntityFireEvent(this, duration);

// Do not start fire event if the fire needs to be removed (< 0 duration)
if (duration.toMillis() > 0) {
EventDispatcher.callCancellable(entityFireEvent, () -> {
final long fireTime = entityFireEvent.getFireTime(TimeUnit.MILLISECOND);
setOnFire(true);
fireExtinguishTime = System.currentTimeMillis() + fireTime;
});
} else {
fireExtinguishTime = System.currentTimeMillis();
if (remainingFireTicks != 0) {
EntityFireExtinguishEvent entityFireExtinguishEvent = new EntityFireExtinguishEvent(this, false);
EventDispatcher.callCancellable(entityFireExtinguishEvent, () -> entityMeta.setOnFire(false));
}

remainingFireTicks = fireTicks;
}

public boolean damage(@NotNull DynamicRegistry.Key<DamageType> type, float amount) {
Expand Down Expand Up @@ -568,35 +561,6 @@ protected void refreshIsDead(boolean isDead) {
return new EntityAttributesPacket(getEntityId(), List.copyOf(attributeModifiers.values()));
}

/**
* Gets the time in ms between two fire damage applications.
*
* @return the time in ms
* @see #setFireDamagePeriod(Duration)
*/
public long getFireDamagePeriod() {
return fireDamagePeriod;
}

/**
* Changes the delay between two fire damage applications.
*
* @param fireDamagePeriod the delay
* @param temporalUnit the time unit
*/
public void setFireDamagePeriod(long fireDamagePeriod, @NotNull TemporalUnit temporalUnit) {
setFireDamagePeriod(Duration.of(fireDamagePeriod, temporalUnit));
}

/**
* Changes the delay between two fire damage applications.
*
* @param fireDamagePeriod the delay
*/
public void setFireDamagePeriod(Duration fireDamagePeriod) {
this.fireDamagePeriod = fireDamagePeriod.toMillis();
}

/**
* Changes the {@link Team} for the entity.
*
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/net/minestom/server/entity/Player.java
Original file line number Diff line number Diff line change
Expand Up @@ -523,8 +523,8 @@ public void respawn() {
if (!isDead())
return;

setFireForDuration(0);
setOnFire(false);
setFireTicks(0);
entityMeta.setOnFire(false);
refreshHealth();

sendPacket(new RespawnPacket(DIMENSION_TYPE_REGISTRY.getId(getDimensionType().namespace()), instance.getDimensionName(),
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package net.minestom.server.event.entity;

import net.minestom.server.entity.Entity;
import net.minestom.server.event.trait.CancellableEvent;
import net.minestom.server.event.trait.EntityInstanceEvent;
import org.jetbrains.annotations.NotNull;

public class EntityFireExtinguishEvent implements EntityInstanceEvent, CancellableEvent {

private final Entity entity;
private boolean natural;

private boolean cancelled;

public EntityFireExtinguishEvent(Entity entity, boolean natural) {
this.entity = entity;
this.natural = natural;
}

public boolean isNatural() {
return natural;
}

@Override
public boolean isCancelled() {
return cancelled;
}

@Override
public void setCancelled(boolean cancel) {
this.cancelled = cancel;
}

@Override
public @NotNull Entity getEntity() {
return entity;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package net.minestom.server.event.entity;

import net.minestom.server.entity.Entity;
import net.minestom.server.event.trait.CancellableEvent;
import net.minestom.server.event.trait.EntityInstanceEvent;
import org.jetbrains.annotations.NotNull;

public class EntitySetFireEvent implements EntityInstanceEvent, CancellableEvent {

private final Entity entity;
private int ticks;

private boolean cancelled;

public EntitySetFireEvent(Entity entity, int ticks) {
this.entity = entity;
this.ticks = ticks;
}

public int getFireTicks() {
return ticks;
}

public void setFireTicks(int ticks) {
this.ticks = ticks;
}

@Override
public boolean isCancelled() {
return cancelled;
}

@Override
public void setCancelled(boolean cancel) {
this.cancelled = cancel;
}

@Override
public @NotNull Entity getEntity() {
return entity;
}
}
Loading