mirror of
https://github.com/taoneill/war.git
synced 2025-01-05 07:17:34 +01:00
Rewrote Warzone#handleDeath
NEEDS TESTING
This commit is contained in:
parent
5e93ab6bc4
commit
92002a06a2
@ -1,10 +1,32 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="src" output="target/classes" path="src/main/java"/>
|
||||
<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources"/>
|
||||
<classpathentry kind="src" output="target/test-classes" path="src/test/java"/>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
|
||||
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER"/>
|
||||
<classpathentry kind="src" output="target/classes" path="src/main/java">
|
||||
<attributes>
|
||||
<attribute name="optional" value="true"/>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources">
|
||||
<attributes>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="src" output="target/test-classes" path="src/test/java">
|
||||
<attributes>
|
||||
<attribute name="optional" value="true"/>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6">
|
||||
<attributes>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
|
||||
<attributes>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="con" path="org.maven.ide.eclipse.MAVEN2_CLASSPATH_CONTAINER"/>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/4"/>
|
||||
<classpathentry kind="output" path="target/classes"/>
|
||||
|
@ -34,6 +34,7 @@ import com.tommytony.war.config.TeamConfig;
|
||||
import com.tommytony.war.config.TeamConfigBag;
|
||||
import com.tommytony.war.config.TeamKind;
|
||||
import com.tommytony.war.config.TeamSpawnStyle;
|
||||
import com.tommytony.war.spout.SpoutDisplayer;
|
||||
import com.tommytony.war.utility.Direction;
|
||||
import com.tommytony.war.volume.Volume;
|
||||
|
||||
@ -442,6 +443,27 @@ public class Team {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send an achievement to all players on the team.
|
||||
* Currently implemented using SpoutCraft.
|
||||
* @param line1 Achievement first line
|
||||
* @param line2 Achievement second line
|
||||
* @param icon Item to display in the achievement
|
||||
* @param ticks Duration the achievement should be displayed
|
||||
*/
|
||||
public void sendAchievement(String line1, String line2, ItemStack icon, int ticks) {
|
||||
if (!War.war.isSpoutServer())
|
||||
return;
|
||||
line1 = SpoutDisplayer.cleanForNotification(line1);
|
||||
line2 = SpoutDisplayer.cleanForNotification(line2);
|
||||
for (Player player : this.players) {
|
||||
SpoutPlayer spoutPlayer = SpoutManager.getPlayer(player);
|
||||
if (!spoutPlayer.isSpoutCraftEnabled())
|
||||
continue;
|
||||
spoutPlayer.sendNotification(line1, line2, icon, ticks);
|
||||
}
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
@ -968,196 +968,84 @@ public class Warzone {
|
||||
return true;
|
||||
}
|
||||
|
||||
public void handleDeath(Player player) {
|
||||
// THIS ISN'T THREAD SAFE
|
||||
// Every death and player movement should ideally occur in sequence because
|
||||
// 1) a death can cause the end of the game by emptying a lifepool causing the max score to be reached
|
||||
// 2) a player movement from one block to the next (getting a flag home or causing a bomb to go off perhaps) could win the game
|
||||
//
|
||||
// Concurrent execution of these events could cause the inventory reset of the last players to die to fail as
|
||||
// they get tp'ed back to the lobby, or perhaps kills to bleed into the next round.
|
||||
|
||||
Team playerTeam = Team.getTeamByPlayerName(player.getName());
|
||||
|
||||
// Make sure the player that died is still part of a team, game may have ended while waiting.
|
||||
// Ignore dying players that essentially just got tp'ed to lobby and got their state restored.
|
||||
// Gotta take care of restoring ReallyDeadFighters' game-end state when in onRespawn as well.
|
||||
if (playerTeam != null) {
|
||||
// teleport to team spawn upon fast respawn death, but not for real deaths
|
||||
if (!this.getWarzoneConfig().getBoolean(WarzoneConfig.REALDEATHS)) {
|
||||
this.respawnPlayer(playerTeam, player);
|
||||
} else {
|
||||
// onPlayerRespawn takes care of real deaths
|
||||
//player.setHealth(0);
|
||||
this.getReallyDeadFighters().add(player.getName());
|
||||
}
|
||||
|
||||
int remaining = playerTeam.getRemainingLifes();
|
||||
if (remaining == 0) { // your death caused your team to lose
|
||||
if (this.isReinitializing()) {
|
||||
// Prevent duplicate battle end. You died just after the battle ending death.
|
||||
this.respawnPlayer(playerTeam, player);
|
||||
} else {
|
||||
// Handle team loss
|
||||
List<Team> teams = this.getTeams();
|
||||
String scores = "";
|
||||
for (Team t : teams) {
|
||||
if (War.war.isSpoutServer()) {
|
||||
for (Player p : t.getPlayers()) {
|
||||
SpoutPlayer sp = SpoutManager.getPlayer(p);
|
||||
if (sp.isSpoutCraftEnabled()) {
|
||||
sp.sendNotification(
|
||||
SpoutDisplayer.cleanForNotification("Round over! " + playerTeam.getKind().getColor() + playerTeam.getName()),
|
||||
SpoutDisplayer.cleanForNotification("ran out of lives."),
|
||||
playerTeam.getKind().getBlockHead(),
|
||||
10000);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
t.teamcast("zone.battle.end", playerTeam.getName(), player.getName());
|
||||
|
||||
if (t.getPlayers().size() != 0 && !t.getTeamConfig().resolveBoolean(TeamConfig.FLAGPOINTSONLY)) {
|
||||
if (!t.getName().equals(playerTeam.getName())) {
|
||||
// all other teams get a point
|
||||
t.addPoint();
|
||||
t.resetSign();
|
||||
}
|
||||
scores += '\n' + t.getName() + "(" + t.getPoints() + "/" + t.getTeamConfig().resolveInt(TeamConfig.MAXSCORE) + ") ";
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// whoever didn't lose, reward them
|
||||
//
|
||||
List<Team> winningTeams = new ArrayList<Team>(teams.size());
|
||||
for( Team t : teams ) {
|
||||
if( !t.getPlayers().contains(player)) {
|
||||
winningTeams.add(t);
|
||||
}
|
||||
}
|
||||
WarBattleWinEvent event1 = new WarBattleWinEvent(this, winningTeams);
|
||||
War.war.getServer().getPluginManager().callEvent(event1);
|
||||
|
||||
if (!scores.equals("")) {
|
||||
this.broadcast("zone.battle.newscores", scores);
|
||||
}
|
||||
if (War.war.getMysqlConfig().isEnabled() && War.war.getMysqlConfig().isLoggingEnabled()) {
|
||||
LogKillsDeathsJob logKillsDeathsJob = new LogKillsDeathsJob(ImmutableList.copyOf(this.getKillsDeathsTracker()));
|
||||
War.war.getServer().getScheduler().runTaskAsynchronously(War.war, logKillsDeathsJob);
|
||||
}
|
||||
this.getKillsDeathsTracker().clear();
|
||||
// detect score cap
|
||||
List<Team> scoreCapTeams = new ArrayList<Team>();
|
||||
for (Team t : teams) {
|
||||
if (t.getPoints() == t.getTeamConfig().resolveInt(TeamConfig.MAXSCORE)) {
|
||||
scoreCapTeams.add(t);
|
||||
}
|
||||
}
|
||||
if (!scoreCapTeams.isEmpty()) {
|
||||
String winnersStr = "";
|
||||
for (Team winner : scoreCapTeams) {
|
||||
if (winner.getPlayers().size() != 0) {
|
||||
winnersStr += winner.getName() + " ";
|
||||
}
|
||||
}
|
||||
this.handleScoreCapReached(winnersStr);
|
||||
} else {
|
||||
// A new battle starts. Reset the zone but not the teams.
|
||||
this.broadcast("zone.battle.reset");
|
||||
if (this.getWarzoneConfig().getBoolean(WarzoneConfig.RESETBLOCKS)) {
|
||||
this.reinitialize();
|
||||
} else {
|
||||
this.initializeZone();
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// player died without causing his team's demise
|
||||
if (this.isFlagThief(player.getName())) {
|
||||
// died while carrying flag.. dropped it
|
||||
Team victim = this.getVictimTeamForFlagThief(player.getName());
|
||||
victim.getFlagVolume().resetBlocks();
|
||||
victim.initializeTeamFlag();
|
||||
this.removeFlagThief(player.getName());
|
||||
|
||||
if (War.war.isSpoutServer()) {
|
||||
for (Player p : victim.getPlayers()) {
|
||||
SpoutPlayer sp = SpoutManager.getPlayer(p);
|
||||
if (sp.isSpoutCraftEnabled()) {
|
||||
sp.sendNotification(
|
||||
SpoutDisplayer.cleanForNotification(playerTeam.getKind().getColor() + player.getName() + ChatColor.YELLOW + " dropped"),
|
||||
SpoutDisplayer.cleanForNotification(ChatColor.YELLOW + "your flag."),
|
||||
playerTeam.getKind().getBlockHead(),
|
||||
5000);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.broadcast("drop.flag.broadcast", player.getName(), victim.getName());
|
||||
}
|
||||
|
||||
// Bomb thieves
|
||||
if (this.isBombThief(player.getName())) {
|
||||
// died while carrying bomb.. dropped it
|
||||
Bomb bomb = this.getBombForThief(player.getName());
|
||||
bomb.getVolume().resetBlocks();
|
||||
bomb.addBombBlocks();
|
||||
this.removeBombThief(player.getName());
|
||||
|
||||
for (Team t : this.getTeams()) {
|
||||
t.teamcast("drop.bomb.broadcast", player.getName(), ChatColor.GREEN + bomb.getName() + ChatColor.WHITE);
|
||||
if (War.war.isSpoutServer()) {
|
||||
for (Player p : t.getPlayers()) {
|
||||
SpoutPlayer sp = SpoutManager.getPlayer(p);
|
||||
if (sp.isSpoutCraftEnabled()) {
|
||||
sp.sendNotification(
|
||||
SpoutDisplayer.cleanForNotification(playerTeam.getKind().getColor() + player.getName() + ChatColor.YELLOW + " dropped"),
|
||||
SpoutDisplayer.cleanForNotification(ChatColor.YELLOW + "bomb " + ChatColor.GREEN + bomb.getName() + ChatColor.YELLOW + "."),
|
||||
Material.TNT,
|
||||
(short)0,
|
||||
5000);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (this.isCakeThief(player.getName())) {
|
||||
// died while carrying cake.. dropped it
|
||||
Cake cake = this.getCakeForThief(player.getName());
|
||||
cake.getVolume().resetBlocks();
|
||||
cake.addCakeBlocks();
|
||||
this.removeCakeThief(player.getName());
|
||||
|
||||
for (Team t : this.getTeams()) {
|
||||
t.teamcast("drop.cake.broadcast", player.getName(), ChatColor.GREEN + cake.getName() + ChatColor.WHITE);
|
||||
if (War.war.isSpoutServer()) {
|
||||
for (Player p : t.getPlayers()) {
|
||||
SpoutPlayer sp = SpoutManager.getPlayer(p);
|
||||
if (sp.isSpoutCraftEnabled()) {
|
||||
sp.sendNotification(
|
||||
SpoutDisplayer.cleanForNotification(playerTeam.getKind().getColor() + player.getName() + ChatColor.YELLOW + " dropped"),
|
||||
SpoutDisplayer.cleanForNotification(ChatColor.YELLOW + "cake " + ChatColor.GREEN + cake.getName() + ChatColor.YELLOW + "."),
|
||||
Material.CAKE,
|
||||
(short)0,
|
||||
5000);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Decrement lifepool
|
||||
playerTeam.setRemainingLives(remaining - 1);
|
||||
|
||||
// Lifepool empty warning
|
||||
if (remaining - 1 == 0) {
|
||||
this.broadcast("zone.lifepool.empty", playerTeam.getName());
|
||||
}
|
||||
}
|
||||
playerTeam.resetSign();
|
||||
/**
|
||||
* Cleanup after a player who has died. This decrements the team's
|
||||
* remaining lifepool, drops stolen flags, and respawns the player.
|
||||
* It also handles team lose and score cap conditions.
|
||||
* This method is synchronized to prevent concurrent battle resets.
|
||||
* @param player Player who died
|
||||
*/
|
||||
public synchronized void handleDeath(Player player) {
|
||||
Team playerTeam = this.getPlayerTeam(player.getName());
|
||||
Validate.notNull(playerTeam, "Can't find team for dead player " + player.getName());
|
||||
if (this.getWarzoneConfig().getBoolean(WarzoneConfig.REALDEATHS)) {
|
||||
this.getReallyDeadFighters().add(player.getName());
|
||||
player.setHealth(0D);
|
||||
} else {
|
||||
this.respawnPlayer(playerTeam, player);
|
||||
}
|
||||
if (playerTeam.getRemainingLifes() <= 0) {
|
||||
handleTeamLoss(playerTeam, player);
|
||||
} else {
|
||||
this.dropAllStolenObjects(player, false);
|
||||
playerTeam.setRemainingLives(playerTeam.getRemainingLifes() - 1);
|
||||
// Lifepool empty warning
|
||||
if (playerTeam.getRemainingLifes() - 1 == 0) {
|
||||
this.broadcast("zone.lifepool.empty", playerTeam.getName());
|
||||
}
|
||||
}
|
||||
playerTeam.resetSign();
|
||||
}
|
||||
|
||||
private void handleTeamLoss(Team losingTeam, Player player) {
|
||||
StringBuilder teamScores = new StringBuilder();
|
||||
List<Team> winningTeams = new ArrayList<Team>(teams.size());
|
||||
for (Team team : this.teams) {
|
||||
if (team.getPlayers().isEmpty())
|
||||
continue;
|
||||
if (team != losingTeam) {
|
||||
team.addPoint();
|
||||
team.resetSign();
|
||||
winningTeams.add(team);
|
||||
}
|
||||
teamScores.append(String.format("\n%s (%d/%d) ", team.getName(), team.getPoints(), team.getTeamConfig().resolveInt(TeamConfig.MAXSCORE)));
|
||||
team.sendAchievement("Round over! " + losingTeam.getKind().getFormattedName(), "ran out of lives.", losingTeam.getKind().getBlockHead(), 10000);
|
||||
}
|
||||
this.broadcast("zone.battle.end", losingTeam.getName(), player.getName());
|
||||
WarBattleWinEvent event1 = new WarBattleWinEvent(this, winningTeams);
|
||||
War.war.getServer().getPluginManager().callEvent(event1);
|
||||
if (!teamScores.toString().isEmpty()) {
|
||||
this.broadcast("zone.battle.newscores", teamScores.toString());
|
||||
}
|
||||
if (War.war.getMysqlConfig().isEnabled() && War.war.getMysqlConfig().isLoggingEnabled()) {
|
||||
LogKillsDeathsJob logKillsDeathsJob = new LogKillsDeathsJob(ImmutableList.copyOf(this.getKillsDeathsTracker()));
|
||||
War.war.getServer().getScheduler().runTaskAsynchronously(War.war, logKillsDeathsJob);
|
||||
}
|
||||
this.getKillsDeathsTracker().clear();
|
||||
if (!detectScoreCap()) {
|
||||
this.broadcast("zone.battle.reset");
|
||||
if (this.getWarzoneConfig().getBoolean(WarzoneConfig.RESETBLOCKS)) {
|
||||
this.reinitialize();
|
||||
} else {
|
||||
this.initializeZone();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a team has achieved max score "score cap".
|
||||
* @return true if team has achieved max score, false otherwise.
|
||||
*/
|
||||
public boolean detectScoreCap() {
|
||||
StringBuilder winnersStr = new StringBuilder();
|
||||
for (Team team : this.teams) {
|
||||
if (team.getPoints() >= team.getTeamConfig().resolveInt(TeamConfig.MAXSCORE)) {
|
||||
winnersStr.append(team.getName()).append(' ');
|
||||
}
|
||||
}
|
||||
if (!winnersStr.toString().isEmpty())
|
||||
this.handleScoreCapReached(winnersStr.toString());
|
||||
return !winnersStr.toString().isEmpty();
|
||||
}
|
||||
|
||||
public void reinitialize() {
|
||||
|
Loading…
Reference in New Issue
Block a user