feat(participation): isolate opted-out combat
This commit is contained in:
@@ -0,0 +1,64 @@
|
||||
package games.dmg.spigottyrant;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.entity.Projectile;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.entity.EntityDamageByEntityEvent;
|
||||
|
||||
public final class ParticipationCombatListener implements Listener {
|
||||
public static final String OPTED_OUT_MESSAGE =
|
||||
"That player has chosen not to take part in the Tyrant event.";
|
||||
|
||||
private final TyrantStateManager stateManager;
|
||||
private final ParticipationCombatService combat;
|
||||
|
||||
public ParticipationCombatListener(
|
||||
TyrantStateManager stateManager,
|
||||
ParticipationCombatService combat
|
||||
) {
|
||||
this.stateManager = stateManager;
|
||||
this.combat = combat;
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
|
||||
public void onDamage(EntityDamageByEntityEvent event) {
|
||||
if (!(event.getEntity() instanceof Player target)) {
|
||||
return;
|
||||
}
|
||||
Optional<Player> attacker = attackingPlayer(event);
|
||||
if (attacker.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
Player source = attacker.orElseThrow();
|
||||
Map<UUID, PlayerState> players = stateManager.players();
|
||||
PlayerState attackerState = players.getOrDefault(
|
||||
source.getUniqueId(),
|
||||
PlayerState.newPlayer(source.getUniqueId(), source.getName())
|
||||
);
|
||||
PlayerState targetState = players.getOrDefault(
|
||||
target.getUniqueId(),
|
||||
PlayerState.newPlayer(target.getUniqueId(), target.getName())
|
||||
);
|
||||
if (combat.blocks(stateManager.game(), attackerState, targetState)) {
|
||||
event.setCancelled(true);
|
||||
source.sendMessage(ChatColor.YELLOW + OPTED_OUT_MESSAGE);
|
||||
}
|
||||
}
|
||||
|
||||
private static Optional<Player> attackingPlayer(EntityDamageByEntityEvent event) {
|
||||
if (event.getDamager() instanceof Player player) {
|
||||
return Optional.of(player);
|
||||
}
|
||||
if (event.getDamager() instanceof Projectile projectile
|
||||
&& projectile.getShooter() instanceof Player player) {
|
||||
return Optional.of(player);
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package games.dmg.spigottyrant;
|
||||
|
||||
public final class ParticipationCombatService {
|
||||
public boolean blocks(
|
||||
GameState game,
|
||||
PlayerState attacker,
|
||||
PlayerState target
|
||||
) {
|
||||
if (game.lifecycle() != GameLifecycle.RUNNING) {
|
||||
return false;
|
||||
}
|
||||
boolean attackerOptedOut = attacker.optedOutUntil().isPresent();
|
||||
boolean targetOptedOut = target.optedOutUntil().isPresent();
|
||||
boolean attackerTyrantSide = isTyrantSide(game, attacker);
|
||||
boolean targetTyrantSide = isTyrantSide(game, target);
|
||||
return (attackerTyrantSide && targetOptedOut)
|
||||
|| (attackerOptedOut && targetTyrantSide);
|
||||
}
|
||||
|
||||
private static boolean isTyrantSide(GameState game, PlayerState player) {
|
||||
return game.tyrantId().filter(player.playerId()::equals).isPresent()
|
||||
|| player.tyrantClass() != TyrantClass.NONE;
|
||||
}
|
||||
}
|
||||
@@ -122,6 +122,12 @@ public final class SpigotTyrantPlugin extends JavaPlugin {
|
||||
),
|
||||
this
|
||||
);
|
||||
getServer().getPluginManager().registerEvents(
|
||||
new ParticipationCombatListener(
|
||||
stateManager, new ParticipationCombatService()
|
||||
),
|
||||
this
|
||||
);
|
||||
getServer().getPluginManager().registerEvents(
|
||||
new VigilanteCombatListener(
|
||||
stateManager, combatTracker, clock, settings.vigilanteCombatDuration()
|
||||
|
||||
Reference in New Issue
Block a user