110 lines
4.2 KiB
Java
110 lines
4.2 KiB
Java
package tc.oc.pgm.tracker.trackers;
|
|
|
|
import java.util.Map;
|
|
import java.util.WeakHashMap;
|
|
import javax.annotation.Nullable;
|
|
import javax.inject.Inject;
|
|
|
|
import org.bukkit.Material;
|
|
import org.bukkit.entity.Entity;
|
|
import org.bukkit.event.EventHandler;
|
|
import org.bukkit.event.EventPriority;
|
|
import org.bukkit.event.Listener;
|
|
import org.bukkit.event.entity.EntityCombustByBlockEvent;
|
|
import org.bukkit.event.entity.EntityCombustByEntityEvent;
|
|
import org.bukkit.event.entity.EntityDamageEvent;
|
|
import org.bukkit.event.entity.EntityExtinguishEvent;
|
|
import tc.oc.commons.bukkit.util.Materials;
|
|
import tc.oc.pgm.events.BlockTransformEvent;
|
|
import tc.oc.pgm.events.ParticipantBlockTransformEvent;
|
|
import tc.oc.pgm.match.ParticipantState;
|
|
import tc.oc.pgm.tracker.EntityResolver;
|
|
import tc.oc.pgm.tracker.damage.BlockInfo;
|
|
import tc.oc.pgm.tracker.damage.EntityInfo;
|
|
import tc.oc.pgm.tracker.damage.FireInfo;
|
|
import tc.oc.pgm.tracker.damage.PhysicalInfo;
|
|
import tc.oc.pgm.tracker.resolvers.DamageResolver;
|
|
|
|
/**
|
|
* - Updates the state of owned fire and lava blocks from events
|
|
* - Tracks burning entities that were ignited by players, directly or indirectly
|
|
* - Resolves fire tick damage to those entities
|
|
*/
|
|
public class FireTracker implements DamageResolver, Listener {
|
|
|
|
private final EntityResolver entities;
|
|
private final BlockTracker blocks;
|
|
|
|
// An entity can be owned by one player but ignited by another, so we need an independent map for burning
|
|
private final Map<Entity, FireInfo> burningEntities = new WeakHashMap<>();
|
|
|
|
@Inject FireTracker(EntityResolver entities, BlockTracker blocks) {
|
|
this.entities = entities;
|
|
this.blocks = blocks;
|
|
}
|
|
|
|
@Override
|
|
public @Nullable FireInfo resolveDamage(EntityDamageEvent.DamageCause damageType, Entity victim, @Nullable PhysicalInfo damager) {
|
|
switch(damageType) {
|
|
case FIRE_TICK:
|
|
FireInfo info = resolveBurning(victim);
|
|
if(info != null) return info;
|
|
// fall through
|
|
|
|
case FIRE:
|
|
case LAVA:
|
|
return new FireInfo(damager);
|
|
}
|
|
return null;
|
|
}
|
|
|
|
public @Nullable FireInfo resolveBurning(Entity entity) {
|
|
return burningEntities.get(entity);
|
|
}
|
|
|
|
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
|
|
public void onBlockTransform(BlockTransformEvent event) {
|
|
boolean wasLava = Materials.isLava(event.getOldState());
|
|
boolean isLava = Materials.isLava(event.getNewState());
|
|
|
|
if(event.changedFrom(Material.FIRE) || (wasLava && !isLava)) {
|
|
blocks.clearBlock(event.getBlock());
|
|
}
|
|
if(event instanceof ParticipantBlockTransformEvent && (event.changedTo(Material.FIRE) || (!wasLava && isLava))) {
|
|
ParticipantState placer = ((ParticipantBlockTransformEvent) event).getPlayerState();
|
|
blocks.trackBlockState(event.getNewState(), new FireInfo(new BlockInfo(event.getNewState(), placer)));
|
|
}
|
|
}
|
|
|
|
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
|
|
public void onEntityIgnite(EntityCombustByBlockEvent event) {
|
|
if(event.getDuration() == 0) return;
|
|
|
|
ParticipantState owner = blocks.getOwner(event.getCombuster());
|
|
if(owner != null) {
|
|
burningEntities.put(event.getEntity(), new FireInfo(blocks.resolveBlock(event.getCombuster())));
|
|
}
|
|
}
|
|
|
|
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
|
|
public void onEntityIgnite(EntityCombustByEntityEvent event) {
|
|
if(event.getDuration() == 0) return;
|
|
|
|
FireInfo info = resolveBurning(event.getCombuster());
|
|
if(info != null) {
|
|
// First, try to resolve the player who ignited the combuster
|
|
info = new FireInfo(new EntityInfo(event.getCombuster(), info.getOwner()));
|
|
} else {
|
|
// If an igniter is not found, fall back to the owner of the entity
|
|
info = new FireInfo(entities.resolveEntity(event.getCombuster()));
|
|
}
|
|
|
|
burningEntities.put(event.getEntity(), info);
|
|
}
|
|
|
|
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
|
|
public void onEntityExtinguish(EntityExtinguishEvent event) {
|
|
this.burningEntities.remove(event.getEntity());
|
|
}
|
|
}
|