Merge remote-tracking branch 'origin/rewrite/death' into develop

This commit is contained in:
cmastudios 2014-06-13 21:42:49 -05:00
commit 4f60ebb780
3 changed files with 126 additions and 194 deletions

View File

@ -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"/>

View File

@ -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;
}

View File

@ -982,196 +982,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() {