diff --git a/.gitattributes b/.gitattributes index 39d13a6da3d..0050b913385 100644 --- a/.gitattributes +++ b/.gitattributes @@ -13766,6 +13766,7 @@ src/main/java/forge/GameEntity.java -text src/main/java/forge/GameEventType.java -text src/main/java/forge/GameLog.java -text src/main/java/forge/GameLogEntry.java -text +src/main/java/forge/GameLogFormatter.java -text src/main/java/forge/ImageCache.java svneol=native#text/plain src/main/java/forge/ImageLoader.java -text src/main/java/forge/Singletons.java svneol=native#text/plain @@ -14256,6 +14257,7 @@ src/main/java/forge/game/event/LandPlayedEvent.java -text src/main/java/forge/game/event/LifeLossEvent.java -text src/main/java/forge/game/event/ManaBurnEvent.java -text src/main/java/forge/game/event/MulliganEvent.java -text +src/main/java/forge/game/event/PlayerControlEvent.java -text src/main/java/forge/game/event/PoisonCounterEvent.java -text src/main/java/forge/game/event/SetTappedEvent.java -text src/main/java/forge/game/event/ShuffleEvent.java -text diff --git a/src/main/java/forge/GameEventType.java b/src/main/java/forge/GameEventType.java index 8fd68ec09f9..622e2cd2244 100644 --- a/src/main/java/forge/GameEventType.java +++ b/src/main/java/forge/GameEventType.java @@ -6,6 +6,7 @@ public enum GameEventType { TURN("Turn"), MULLIGAN("Mulligan"), ANTE("Ante"), + PLAYER_CONROL("Player contol"), COMBAT("Combat"), EFFECT_REPLACED("Replacement Effect"), LAND("Land"), diff --git a/src/main/java/forge/GameLog.java b/src/main/java/forge/GameLog.java index 6dbf71ce5ef..d99f2307678 100644 --- a/src/main/java/forge/GameLog.java +++ b/src/main/java/forge/GameLog.java @@ -20,18 +20,12 @@ package forge; import java.util.ArrayList; import java.util.List; -import java.util.Map.Entry; import org.apache.commons.lang3.StringUtils; import com.google.common.eventbus.Subscribe; -import forge.game.GameOutcome; -import forge.game.event.DuelOutcomeEvent; import forge.game.event.Event; import forge.game.phase.Combat; -import forge.game.player.LobbyPlayer; -import forge.game.player.PlayerStatistics; -import forge.util.Lang; import forge.util.MyObservable; @@ -74,15 +68,11 @@ public class GameLog extends MyObservable { this.updateObservers(); } - /** - * Gets the log text. - * - * @return the log text - */ - public String getLogText() { - return getLogText(null); - } - + private void add(GameLogEntry entry) { + log.add(entry); + this.updateObservers(); + } + public String getLogText(final GameEventType logLevel) { List filteredAndReversed = getLogEntries(logLevel); return StringUtils.join(filteredAndReversed, "\r\n"); @@ -121,127 +111,19 @@ public class GameLog extends MyObservable { @Subscribe public void receiveGameEvent(Event ev) { - if(ev instanceof DuelOutcomeEvent) { - fillOutcome( ((DuelOutcomeEvent) ev).result, ((DuelOutcomeEvent) ev).history ); + GameLogEntry record = GameLogFormatter.logEvent(ev, this); + if( null != record ) { + add(record); } } - /** - * Generates and adds - */ - private void fillOutcome(GameOutcome result, List history) { - - // add result entries to the game log - final LobbyPlayer human = Singletons.getControl().getLobby().getGuiPlayer(); - - - final List outcomes = new ArrayList(); - for (Entry p : result) { - String whoHas = p.getKey().equals(human) ? "You have" : p.getKey().getName() + " has"; - String outcome = String.format("%s %s", whoHas, p.getValue().getOutcome().toString()); - outcomes.add(outcome); - this.add(GameEventType.GAME_OUTCOME, outcome); - } - - final String statsSummary = generateSummary(history); - this.add(GameEventType.MATCH_RESULTS, statsSummary); - } - - private static String generateSummary(List gamesPlayed) { - GameOutcome outcome1 = gamesPlayed.get(0); - int[] wins = new int[outcome1.getNumPlayers()]; - LobbyPlayer[] players = new LobbyPlayer[outcome1.getNumPlayers()]; - for(int i = 0; i < wins.length; wins[i++] = 0); - - for (GameOutcome go : gamesPlayed) { - int i = 0; - for(Entry ps : go) { - players[i] = ps.getKey(); - if( ps.getValue().getOutcome().hasWon() ) - wins[i]++; - i++; - } - } - - StringBuilder sb = new StringBuilder(); - for(int i = 0; i < wins.length; i++) { - sb.append(players[i].getName()).append(": ").append(wins[i]).append(" "); - } - return sb.toString(); - } - - - public void addCombatAttackers(Combat combat) { - this.add(GameEventType.COMBAT, describeAttack(combat)); + this.add(GameLogFormatter.describeAttack(combat)); } public void addCombatBlockers(Combat combat) { - this.add(GameEventType.COMBAT, describeBlock(combat)); + this.add(GameLogFormatter.describeBlock(combat)); } // Special methods - - private static String describeAttack(final Combat combat) { - final StringBuilder sb = new StringBuilder(); - - // Loop through Defenders - // Append Defending Player/Planeswalker - - - - // Not a big fan of the triple nested loop here - for (GameEntity defender : combat.getDefenders()) { - List attackers = combat.getAttackersOf(defender); - if (attackers == null || attackers.isEmpty()) { - continue; - } - if ( sb.length() > 0 ) sb.append("\n"); - - sb.append(combat.getAttackingPlayer()).append(" declared ").append(Lang.joinHomogenous(attackers)); - sb.append(" to attack ").append(defender.toString()).append("."); - } - - return sb.toString(); - } - - - private static String describeBlock(final Combat combat) { - final StringBuilder sb = new StringBuilder(); - - // Loop through Defenders - // Append Defending Player/Planeswalker - - List blockers = null; - - - for (GameEntity defender : combat.getDefenders()) { - List attackers = combat.getAttackersOf(defender); - if (attackers == null || attackers.isEmpty()) { - continue; - } - if ( sb.length() > 0 ) sb.append("\n"); - - String controllerName = defender instanceof Card ? ((Card)defender).getController().getName() : defender.getName(); - boolean firstAttacker = true; - for (final Card attacker : attackers) { - if ( !firstAttacker ) sb.append("\n"); - - blockers = combat.getBlockers(attacker); - if ( blockers.isEmpty() ) { - sb.append(controllerName).append(" didn't block "); - } else { - sb.append(controllerName).append(" assigned ").append(Lang.joinHomogenous(blockers)).append(" to block "); - } - - sb.append(attacker).append("."); - firstAttacker = false; - } - } - - return sb.toString(); - } - - - -} // end class GameLog +} diff --git a/src/main/java/forge/GameLogFormatter.java b/src/main/java/forge/GameLogFormatter.java new file mode 100644 index 00000000000..c7d62278383 --- /dev/null +++ b/src/main/java/forge/GameLogFormatter.java @@ -0,0 +1,145 @@ +package forge; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map.Entry; + +import forge.game.GameOutcome; +import forge.game.event.DuelOutcomeEvent; +import forge.game.event.Event; +import forge.game.event.PlayerControlEvent; +import forge.game.phase.Combat; +import forge.game.player.LobbyPlayer; +import forge.game.player.Player; +import forge.game.player.PlayerStatistics; +import forge.util.Lang; + +public class GameLogFormatter { + + // Some events produce several log entries. I've let them added into log directly + static GameLogEntry logEvent(Event ev, GameLog log) { + if(ev instanceof DuelOutcomeEvent) { + return GameLogFormatter.fillOutcome(log, ((DuelOutcomeEvent) ev).result, ((DuelOutcomeEvent) ev).history ); + + } else if ( ev instanceof PlayerControlEvent ) { + LobbyPlayer newController = ((PlayerControlEvent) ev).getNewController(); + Player p = ((PlayerControlEvent) ev).getPlayer(); + + final String message; + if( newController == null ) + message = p.getName() + " has restored control over themself"; + else + message = String.format("%s is controlled by %s", p.getName(), newController.getName()); + + return new GameLogEntry(GameEventType.PLAYER_CONROL, message); + } + return null; + } + + + /** + * Generates and adds + */ + private static GameLogEntry fillOutcome(GameLog log, GameOutcome result, List history) { + + // add result entries to the game log + final LobbyPlayer human = Singletons.getControl().getLobby().getGuiPlayer(); + + + final List outcomes = new ArrayList(); + for (Entry p : result) { + String whoHas = p.getKey().equals(human) ? "You have" : p.getKey().getName() + " has"; + String outcome = String.format("%s %s", whoHas, p.getValue().getOutcome().toString()); + outcomes.add(outcome); + log.add(GameEventType.GAME_OUTCOME, outcome); + } + + return generateSummary(history); + } + + private static GameLogEntry generateSummary(List gamesPlayed) { + GameOutcome outcome1 = gamesPlayed.get(0); + int[] wins = new int[outcome1.getNumPlayers()]; + LobbyPlayer[] players = new LobbyPlayer[outcome1.getNumPlayers()]; + for(int i = 0; i < wins.length; wins[i++] = 0); + + for (GameOutcome go : gamesPlayed) { + int i = 0; + for(Entry ps : go) { + players[i] = ps.getKey(); + if( ps.getValue().getOutcome().hasWon() ) + wins[i]++; + i++; + } + } + + StringBuilder sb = new StringBuilder(); + for(int i = 0; i < wins.length; i++) { + sb.append(players[i].getName()).append(": ").append(wins[i]).append(" "); + } + return new GameLogEntry(GameEventType.MATCH_RESULTS, sb.toString()); + } + + static GameLogEntry describeAttack(final Combat combat) { + final StringBuilder sb = new StringBuilder(); + + // Loop through Defenders + // Append Defending Player/Planeswalker + + + + // Not a big fan of the triple nested loop here + for (GameEntity defender : combat.getDefenders()) { + List attackers = combat.getAttackersOf(defender); + if (attackers == null || attackers.isEmpty()) { + continue; + } + if ( sb.length() > 0 ) sb.append("\n"); + + sb.append(combat.getAttackingPlayer()).append(" declared ").append(Lang.joinHomogenous(attackers)); + sb.append(" to attack ").append(defender.toString()).append("."); + } + + return new GameLogEntry(GameEventType.COMBAT, sb.toString()); + } + + + static GameLogEntry describeBlock(final Combat combat) { + final StringBuilder sb = new StringBuilder(); + + // Loop through Defenders + // Append Defending Player/Planeswalker + + List blockers = null; + + + for (GameEntity defender : combat.getDefenders()) { + List attackers = combat.getAttackersOf(defender); + if (attackers == null || attackers.isEmpty()) { + continue; + } + if ( sb.length() > 0 ) sb.append("\n"); + + String controllerName = defender instanceof Card ? ((Card)defender).getController().getName() : defender.getName(); + boolean firstAttacker = true; + for (final Card attacker : attackers) { + if ( !firstAttacker ) sb.append("\n"); + + blockers = combat.getBlockers(attacker); + if ( blockers.isEmpty() ) { + sb.append(controllerName).append(" didn't block "); + } else { + sb.append(controllerName).append(" assigned ").append(Lang.joinHomogenous(blockers)).append(" to block "); + } + + sb.append(attacker).append("."); + firstAttacker = false; + } + } + + return new GameLogEntry(GameEventType.COMBAT, sb.toString()); + } + + + +} // end class GameLog \ No newline at end of file diff --git a/src/main/java/forge/game/event/CounterAddedEvent.java b/src/main/java/forge/game/event/CounterAddedEvent.java index 0bbbba63c4f..86d9346f92e 100644 --- a/src/main/java/forge/game/event/CounterAddedEvent.java +++ b/src/main/java/forge/game/event/CounterAddedEvent.java @@ -1,14 +1,9 @@ package forge.game.event; -/** - * - * - */ public class CounterAddedEvent extends Event { public final int Amount; public CounterAddedEvent(int n) { Amount = n; } -} - +} \ No newline at end of file diff --git a/src/main/java/forge/game/event/PlayerControlEvent.java b/src/main/java/forge/game/event/PlayerControlEvent.java new file mode 100644 index 00000000000..f63550af8e3 --- /dev/null +++ b/src/main/java/forge/game/event/PlayerControlEvent.java @@ -0,0 +1,28 @@ +package forge.game.event; + +import forge.game.player.LobbyPlayer; +import forge.game.player.Player; + +public class PlayerControlEvent extends Event { + private final Player player; + private final LobbyPlayer oldController; + private final LobbyPlayer newController; + + public PlayerControlEvent(Player p, LobbyPlayer old, LobbyPlayer new1) { + player = p; + oldController = old; + newController = new1; + } + + public final Player getPlayer() { + return player; + } + + public final LobbyPlayer getOldController() { + return oldController; + } + + public final LobbyPlayer getNewController() { + return newController; + } +} \ No newline at end of file diff --git a/src/main/java/forge/game/player/Player.java b/src/main/java/forge/game/player/Player.java index d1ae22dffb5..4a56bf74ccb 100644 --- a/src/main/java/forge/game/player/Player.java +++ b/src/main/java/forge/game/player/Player.java @@ -62,6 +62,7 @@ import forge.game.event.DrawCardEvent; import forge.game.event.LandPlayedEvent; import forge.game.event.LifeLossEvent; import forge.game.event.MulliganEvent; +import forge.game.event.PlayerControlEvent; import forge.game.event.PoisonCounterEvent; import forge.game.event.ShuffleEvent; import forge.game.phase.PhaseHandler; @@ -2727,10 +2728,13 @@ public class Player extends GameEntity implements Comparable { public final void releaseControl() { controller = controllerCreator; + game.getEvents().post(new PlayerControlEvent(this, getLobbyPlayer(), null)); } public final void obeyNewMaster(PlayerController pc) { + LobbyPlayer oldController = getLobbyPlayer(); controller = pc; + game.getEvents().post(new PlayerControlEvent(this, oldController, pc.getLobbyPlayer())); } diff --git a/src/main/java/forge/gui/match/ViewWinLose.java b/src/main/java/forge/gui/match/ViewWinLose.java index fb4bb60c395..522ecea0e57 100644 --- a/src/main/java/forge/gui/match/ViewWinLose.java +++ b/src/main/java/forge/gui/match/ViewWinLose.java @@ -106,7 +106,7 @@ public class ViewWinLose { // Assemble game log scroller. final FTextArea txtLog = new FTextArea(); - txtLog.setText(match.getCurrentGame().getGameLog().getLogText()); + txtLog.setText(match.getCurrentGame().getGameLog().getLogText(null)); txtLog.setFont(FSkin.getFont(14)); txtLog.setFocusable(true); // allow highlighting and copying of log