ProjectAres/PGM/src/main/java/tc/oc/pgm/tracker/trackers/FireTracker.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());
}
}