package tc.oc.pgm.proximity;
import com.google.common.collect.Sets;
import org.bukkit.ChatColor;
import org.bukkit.Color;
import org.bukkit.FireworkEffect;
import org.bukkit.Location;
import org.bukkit.Sound;
import org.bukkit.entity.Firework;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.util.Vector;
import tc.oc.pgm.events.ListenerScope;
import tc.oc.pgm.match.Match;
import tc.oc.pgm.match.MatchPlayer;
import tc.oc.commons.bukkit.chat.BukkitSound;
import tc.oc.commons.bukkit.event.CoarsePlayerMoveEvent;
import tc.oc.pgm.fireworks.FireworkUtil;
import tc.oc.commons.bukkit.util.NMSHacks;
import tc.oc.pgm.match.MatchScope;
import tc.oc.pgm.spawns.events.ParticipantDespawnEvent;
import tc.oc.pgm.spawns.events.ParticipantSpawnEvent;
import java.util.HashSet;
import java.util.Random;
import java.util.Set;
@ListenerScope(MatchScope.LOADED)
public class ProximityAlarm implements Listener {
private static final long MESSAGE_INTERVAL = 5000;
private static final float FLARE_CHANCE = 0.25f;
private static final BukkitSound SOUND = new BukkitSound(Sound.ENTITY_FIREWORK_LARGE_BLAST_FAR, 1f, 0.7f);
protected final Random random;
protected final Match match;
protected final ProximityAlarmDefinition definition;
protected final Set<MatchPlayer> playersInside = Sets.newHashSet();
protected long lastMessageTime = 0;
public ProximityAlarm(Match match, ProximityAlarmDefinition definition, Random random) {
this.random = random;
this.match = match;
this.definition = definition;
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onPlayerMove(final CoarsePlayerMoveEvent event) {
updatePlayer(this.match.getPlayer(event.getPlayer()), event.getTo());
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onPlayerSpawn(final ParticipantSpawnEvent event) {
updatePlayer(event.getPlayer(), event.getPlayer().getBukkit().getLocation());
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onPlayerDespawn(final ParticipantDespawnEvent event) {
this.playersInside.remove(event.getPlayer());
}
private void updatePlayer(MatchPlayer player, Location location) {
if(player != null && player.canInteract() && this.definition.detectFilter.query(player).isAllowed()) {
if(!player.isDead() && this.definition.detectRegion.contains(location.toVector())) {
this.playersInside.add(player);
} else {
this.playersInside.remove(player);
}
}
}
public void showAlarm() {
if(this.random.nextFloat() < FLARE_CHANCE) {
if(!this.playersInside.isEmpty()) {
this.showFlare();
this.showMessage();
}
}
}
private void showFlare() {
float angle = (float) (this.random.nextFloat() * Math.PI * 2);
Location location = this.definition.detectRegion.getBounds().center()
.plus(
new Vector(
Math.sin(angle) * this.definition.flareRadius,
0,
Math.cos(angle) * this.definition.flareRadius
)
).toLocation(this.match.getWorld());
Set<Color> colors = new HashSet<>();
for(MatchPlayer player : this.playersInside) {
colors.add(player.getParty().getFullColor());
}
Firework firework = FireworkUtil.spawnFirework(location,
FireworkEffect.builder()
.with(FireworkEffect.Type.BALL)
.withColor(colors)
.build(),
0);
NMSHacks.skipFireworksLaunch(firework);
}
private void showMessage() {
if(this.definition.alertMessage == null) {
return;
}
long now = System.currentTimeMillis();
if(this.lastMessageTime + MESSAGE_INTERVAL < now) {
this.lastMessageTime = now;
for(MatchPlayer player : this.match.getPlayers()) {
if(this.definition.alertFilter.query(player).isAllowed()) {
player.sendMessage(ChatColor.RED + this.definition.alertMessage);
player.playSound(SOUND);
}
}
}
}
}