ProjectAres/PGM/src/main/java/tc/oc/pgm/stats/DeathPublishingMatchModule....

239 lines
8.1 KiB
Java

package tc.oc.pgm.stats;
import java.util.Optional;
import javax.inject.Inject;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import java.time.Duration;
import java.time.Instant;
import tc.oc.api.docs.Server;
import tc.oc.api.docs.virtual.DeathDoc;
import tc.oc.api.model.BatchUpdater;
import tc.oc.api.model.BatchUpdaterFactory;
import tc.oc.api.model.IdFactory;
import tc.oc.pgm.classes.ClassMatchModule;
import tc.oc.pgm.classes.PlayerClass;
import tc.oc.pgm.events.ListenerScope;
import tc.oc.pgm.events.MatchPlayerDeathEvent;
import tc.oc.pgm.match.Match;
import tc.oc.pgm.match.MatchModule;
import tc.oc.pgm.match.MatchPlayer;
import tc.oc.pgm.match.MatchScope;
import tc.oc.pgm.match.ParticipantState;
import tc.oc.pgm.tracker.damage.BlockInfo;
import tc.oc.pgm.tracker.damage.DamageInfo;
import tc.oc.pgm.tracker.damage.EntityInfo;
import tc.oc.pgm.tracker.damage.FallInfo;
import tc.oc.pgm.tracker.damage.ItemInfo;
import tc.oc.pgm.tracker.damage.MeleeInfo;
import tc.oc.pgm.tracker.damage.ProjectileInfo;
import tc.oc.pgm.tracker.damage.RangedInfo;
import tc.oc.pgm.tracker.damage.SpleefInfo;
import tc.oc.pgm.tracker.damage.TNTInfo;
import tc.oc.pgm.tracker.damage.TrackerInfo;
@ListenerScope(MatchScope.LOADED)
public class DeathPublishingMatchModule extends MatchModule implements Listener {
private static final Duration UPDATE_DELAY = Duration.ofMinutes(1);
private final Server server;
private final StatisticsConfiguration config;
private final IdFactory idFactory;
private final BatchUpdater<DeathDoc.Partial> batchUpdater;
@Inject DeathPublishingMatchModule(Match match, StatisticsConfiguration config, Server server, BatchUpdaterFactory<DeathDoc.Partial> updaterFactory, IdFactory idFactory) {
super(match);
this.server = server;
this.config = config;
this.idFactory = idFactory;
this.batchUpdater = updaterFactory.createBatchUpdater(UPDATE_DELAY);
}
@Override
public void unload() {
batchUpdater.flush();
super.unload();
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onDeath(MatchPlayerDeathEvent event) {
final MatchPlayer victim = event.getVictim();
final ParticipantState killer = event.getKiller();
if(!victim.isParticipating() || !config.deaths()) return;
final ClassMatchModule classes = match.getMatchModule(ClassMatchModule.class);
final DamageInfo damage = event.getDamageInfo();
final Location location = event.getVictim().getBukkit().getLocation();
final String _id = idFactory.newId();
batchUpdater.update(new DeathDoc.Creation() {
@Override
public String _id() {
return _id;
}
@Override
public String server_id() {
return server._id();
}
@Override
public String match_id() {
return match.getId();
}
@Override
public String family() {
return server.family();
}
@Override
public Instant date() {
return match.getInstantNow();
}
@Override
public String victim() {
return victim.getPlayerId().player_id();
}
@Override
public String killer() {
return killer != null && !event.isSelfKill() ? killer.getPlayerId().player_id() : null;
}
@Override
public String entity_killer() {
return killer() == null && damage instanceof EntityInfo ? ((EntityInfo) damage).getIdentifier() : null;
}
@Override
public String block_killer() {
return killer() == null && damage instanceof BlockInfo ? ((BlockInfo) damage).getIdentifier() : null;
}
@Override
public Boolean player_killer() {
return killer() != null;
}
@Override
public Boolean teamkill() {
return killer() != null && !event.isSelfKill() && event.isTeamKill();
}
@Override
public String victim_class() {
return Optional.ofNullable(classes)
.flatMap(cmm -> cmm.lastPlayedClass(victim.getPlayerId()))
.map(PlayerClass::getName)
.orElse(null);
}
@Override
public String killer_class() {
return Optional.ofNullable(classes)
.filter(cmm -> killer != null)
.flatMap(cmm -> cmm.lastPlayedClass(killer.getPlayerId()))
.map(PlayerClass::getName)
.orElse(null);
}
@Override
public int raindrops() {
return event.getRaindrops();
}
@Override
public double x() {
return location.getX();
}
@Override
public double y() {
return location.getY();
}
@Override
public double z() {
return location.getZ();
}
@Override
public Double distance() {
if(damage instanceof FallInfo) {
TrackerInfo cause = ((FallInfo) damage).getCause();
Location location = event.getVictim().getBukkit().getLocation();
RangedInfo rangedInfo = cause instanceof RangedInfo ? (RangedInfo) damage : (FallInfo) damage;
return rangedInfo.distanceFrom(location);
}
return null;
}
@Override
public Boolean enchanted() {
return weapon() != null && damage instanceof MeleeInfo ? ((MeleeInfo) damage).getWeapon().isEnchanted() : null;
}
@Override
public String weapon() {
final ItemInfo info = damage instanceof MeleeInfo ? ((MeleeInfo) damage).getWeapon() : null;
if(info != null && info.getItem().getType() != Material.AIR) {
return info.getIdentifier();
}
return null;
}
@Override
public String from() {
return damage instanceof FallInfo ? ((FallInfo) damage).getFrom().toString() : null;
}
@Override
public String action() {
if(damage instanceof FallInfo) {
TrackerInfo cause = ((FallInfo) damage).getCause();
if(cause instanceof ProjectileInfo) {
return "SHOOT";
} else if(cause instanceof SpleefInfo) {
return "SPLEEF";
} else if(cause instanceof TNTInfo) {
return "EXPLODE";
} else {
return "HIT";
}
}
return null;
}
@Override
public String cause() {
if(damage instanceof MeleeInfo) {
return "MELEE";
} else if(damage instanceof ProjectileInfo) {
if(((ProjectileInfo) damage).getProjectile() instanceof EntityInfo) {
switch(((EntityInfo)((ProjectileInfo) damage).getProjectile()).getEntityType()) {
case ARROW:
case SPECTRAL_ARROW:
case TIPPED_ARROW:
return "ARROW";
case SPLASH_POTION:
case LINGERING_POTION:
return "POTION";
}
}
}
return null;
}
});
}
}