Shifting responsibilities to make all more readable.

This commit is contained in:
marcins78@gmail.com
2011-10-26 12:22:47 +00:00
parent 7c198485b6
commit 46a4342d0e
7 changed files with 174 additions and 148 deletions

View File

@@ -1,16 +1,28 @@
package com.gempukku.lotro.common;
public enum Zone implements Filterable {
FREE_CHARACTERS("play", true), SUPPORT("play", true), SHADOW_CHARACTERS("play", true),
ADVENTURE_PATH("play", true),
HAND("hand", false), VOID("void", false), DECK("deck", false), ATTACHED("play", true), STACKED("stacked", false),
DISCARD("discard", false), DEAD("dead pile", false);
// Public knowledge and in play
FREE_CHARACTERS("play", true, true, true), SUPPORT("play", true, true, true), SHADOW_CHARACTERS("play", true, true, true),
ADVENTURE_PATH("play", true, true, true), ATTACHED("play", true, true, true),
// Public knowledge but not in play
STACKED("stacked", true, true, false), DEAD("dead pile", true, true, false),
// Private knowledge
HAND("hand", false, true, false), DISCARD("discard", false, true, false),
// Nobody sees
VOID("void", false, false, false), DECK("deck", false, false, false);
private String _humanReadable;
private boolean _public;
private boolean _visibleByOwner;
private boolean _inPlay;
private Zone(String humanReadable, boolean inPlay) {
private Zone(String humanReadable, boolean isPublic, boolean visibleByOwner, boolean inPlay) {
_humanReadable = humanReadable;
_public = isPublic;
_visibleByOwner = visibleByOwner;
_inPlay = inPlay;
}
@@ -21,4 +33,12 @@ public enum Zone implements Filterable {
public boolean isInPlay() {
return _inPlay;
}
public boolean isPublic() {
return _public;
}
public boolean isVisibleByOwner() {
return _visibleByOwner;
}
}

View File

@@ -5,18 +5,7 @@ import com.gempukku.lotro.communication.GameStateListener;
import com.gempukku.lotro.game.*;
import com.gempukku.lotro.logic.PlayerOrder;
import com.gempukku.lotro.logic.timing.GameStats;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.File;
import java.util.*;
public class GameState {
@@ -56,8 +45,7 @@ public class GameState {
private List<Assignment> _assignments = new LinkedList<Assignment>();
private Skirmish _skirmish = null;
private Map<String, GatheringParticipantCommunicationChannel> _recordingListeners = new HashMap<String, GatheringParticipantCommunicationChannel>();
private Map<String, GameStateListener> _gameStateListeners = new HashMap<String, GameStateListener>();
private Set<GameStateListener> _gameStateListeners = new HashSet<GameStateListener>();
private int _nextCardId = 0;
@@ -81,29 +69,8 @@ public class GameState {
addPlayerCards(stringListEntry.getKey(), stringListEntry.getValue(), library);
}
for (String playerId : playerOrder.getAllPlayers()) {
GatheringParticipantCommunicationChannel listener = new GatheringParticipantCommunicationChannel(playerId);
listener.setPlayerOrder(playerOrder.getAllPlayers());
_recordingListeners.put(playerId, listener);
for (String playerId : playerOrder.getAllPlayers())
_playerThreats.put(playerId, 0);
}
for (String playerId : _gameStateListeners.keySet())
sendStateToPlayer(playerId, gameStats);
}
private String _possibleChars = "abcdefghijklmnopqrstuvwxyz0123456789";
private int _charsCount = _possibleChars.length();
private String randomUid() {
int length = 16;
char[] chars = new char[length];
Random rnd = new Random();
for (int i = 0; i < length; i++)
chars[i] = _possibleChars.charAt(rnd.nextInt(_charsCount));
return new String(chars);
}
public void setInitiativeSide(Side initiativeSide) {
@@ -114,47 +81,6 @@ public class GameState {
return _initiativeSide;
}
public void gameFinished() {
File gameReplayFolder = new File("i:\\gemp-lotr\\replay");
gameReplayFolder.mkdirs();
for (Map.Entry<String, GatheringParticipantCommunicationChannel> playerRecordings : _recordingListeners.entrySet()) {
String playerId = playerRecordings.getKey();
File playerReplayFolder = new File(gameReplayFolder, playerId);
playerReplayFolder.mkdir();
File replayFile;
do {
replayFile = new File(playerReplayFolder, randomUid() + ".xml");
} while (replayFile.exists());
final List<GameEvent> gameEvents = playerRecordings.getValue().consumeGameEvents();
try {
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
Document doc = documentBuilder.newDocument();
Element gameReplay = doc.createElement("gameReplay");
EventSerializer serializer = new EventSerializer();
for (GameEvent gameEvent : gameEvents) {
gameReplay.appendChild(serializer.serializeEvent(doc, gameEvent));
}
doc.appendChild(gameReplay);
// Prepare the DOM document for writing
Source source = new DOMSource(doc);
// Prepare the output file
Result result = new StreamResult(replayFile);
// Write the DOM document to the file
Transformer xformer = TransformerFactory.newInstance().newTransformer();
xformer.transform(source, result);
} catch (Exception exp) {
}
}
}
private void addPlayerCards(String playerId, List<String> cards, LotroCardBlueprintLibrary library) {
for (String blueprintId : cards) {
LotroCardBlueprint card = library.getLotroCardBlueprint(blueprintId);
@@ -192,34 +118,20 @@ public class GameState {
}
public void addGameStateListener(String playerId, GameStateListener gameStateListener, GameStats gameStats) {
_gameStateListeners.put(playerId, gameStateListener);
sendStateToPlayer(playerId, gameStats);
_gameStateListeners.add(gameStateListener);
sendStateToPlayer(playerId, gameStateListener, gameStats);
}
public void removeGameStateListener(String playerId, GameStateListener gameStateListener) {
_gameStateListeners.remove(playerId);
}
private Collection<GameStateListener> getPrivateGameStateListeners(PhysicalCard physicalCard) {
String owner = physicalCard.getOwner();
Set<GameStateListener> listeners = new HashSet<GameStateListener>();
GameStateListener result = _gameStateListeners.get(owner);
if (result != null)
listeners.add(result);
listeners.add(_recordingListeners.get(owner));
return listeners;
_gameStateListeners.remove(gameStateListener);
}
private Collection<GameStateListener> getAllGameStateListeners() {
Set<GameStateListener> allListeners = new HashSet<GameStateListener>(_gameStateListeners.values());
allListeners.addAll(_recordingListeners.values());
return allListeners;
return Collections.unmodifiableSet(_gameStateListeners);
}
private void sendStateToPlayer(String playerId, GameStats gameStats) {
private void sendStateToPlayer(String playerId, GameStateListener listener, GameStats gameStats) {
if (_playerOrder != null) {
GameStateListener listener = _gameStateListeners.get(playerId);
listener.setPlayerOrder(_playerOrder.getAllPlayers());
if (_currentPlayerId != null)
listener.setCurrentPlayerId(_currentPlayerId);
@@ -281,15 +193,6 @@ public class GameState {
}
}
private boolean isZonePublic(Zone zone) {
return zone == Zone.FREE_CHARACTERS || zone == Zone.SUPPORT || zone == Zone.SHADOW_CHARACTERS || zone == Zone.SUPPORT
|| zone == Zone.ADVENTURE_PATH || zone == Zone.ATTACHED || zone == Zone.STACKED || zone == Zone.DEAD;
}
private boolean isZonePrivate(Zone zone) {
return zone == Zone.DISCARD || zone == Zone.HAND;
}
public void sendMessage(String message) {
for (GameStateListener listener : getAllGameStateListeners())
listener.sendMessage(message);
@@ -383,7 +286,14 @@ public class GameState {
}
public void removeCardsFromZone(String playerPerforming, Collection<PhysicalCard> cards) {
Map<GameStateListener, Set<PhysicalCard>> listenerCards = new HashMap<GameStateListener, Set<PhysicalCard>>();
for (PhysicalCard card : cards) {
List<PhysicalCardImpl> zoneCards = getZoneCards(card.getOwner(), card.getBlueprint().getCardType(), card.getZone());
if (!zoneCards.contains(card))
throw new RuntimeException("Card was not found in the expected zone");
}
for (GameStateListener listener : getAllGameStateListeners())
listener.cardsRemoved(playerPerforming, cards);
for (PhysicalCard card : cards) {
Zone zone = card.getZone();
@@ -395,9 +305,7 @@ public class GameState {
stopAffectingStacked(card);
List<PhysicalCardImpl> zoneCards = getZoneCards(card.getOwner(), card.getBlueprint().getCardType(), zone);
boolean b = zoneCards.remove(card);
if (!b)
throw new RuntimeException("Card was not found in the expected zone");
zoneCards.remove(card);
if (zone == Zone.ATTACHED)
((PhysicalCardImpl) card).attachTo(null);
@@ -417,20 +325,8 @@ public class GameState {
removeAllTokens(card);
if (isZonePublic(zone))
for (GameStateListener listener : getAllGameStateListeners()) {
getValue(listenerCards, listener).add(card);
}
else if (isZonePrivate(zone))
for (GameStateListener listener : getPrivateGameStateListeners(card)) {
getValue(listenerCards, listener).add(card);
}
((PhysicalCardImpl) card).setZone(null);
}
for (Map.Entry<GameStateListener, Set<PhysicalCard>> gameStateListenerSetEntry : listenerCards.entrySet())
gameStateListenerSetEntry.getKey().cardsRemoved(playerPerforming, gameStateListenerSetEntry.getValue());
}
private Set<PhysicalCard> getValue(Map<GameStateListener, Set<PhysicalCard>> map, GameStateListener listener) {
@@ -462,12 +358,8 @@ public class GameState {
for (GameStateListener listener : getAllGameStateListeners())
listener.setSite(card);
} else {
if (isZonePublic(zone))
for (GameStateListener listener : getAllGameStateListeners())
listener.cardCreated(card);
else if (isZonePrivate(zone))
for (GameStateListener listener : getPrivateGameStateListeners(card))
listener.cardCreated(card);
for (GameStateListener listener : getAllGameStateListeners())
listener.cardCreated(card);
}
if (zone.isInPlay()) {

View File

@@ -6,10 +6,7 @@ import com.gempukku.lotro.communication.GameStateListener;
import com.gempukku.lotro.game.PhysicalCard;
import com.gempukku.lotro.logic.timing.GameStats;
import java.util.Collection;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.*;
import static com.gempukku.lotro.game.state.GameEvent.Type.*;
@@ -75,7 +72,8 @@ public class GatheringParticipantCommunicationChannel implements GameStateListen
@Override
public void cardCreated(PhysicalCard card) {
_events.add(new GameEvent(PCIP).card(card));
if (card.getZone().isPublic() || (card.getZone().isVisibleByOwner() && card.getOwner().equals(_self)))
_events.add(new GameEvent(PCIP).card(card));
}
@Override
@@ -85,7 +83,13 @@ public class GatheringParticipantCommunicationChannel implements GameStateListen
@Override
public void cardsRemoved(String playerPerforming, Collection<PhysicalCard> cards) {
_events.add(new GameEvent(RCFP).otherCardIds(getCardIds(cards)).participantId(playerPerforming));
Set<PhysicalCard> removedCardsVisibleByPlayer = new HashSet<PhysicalCard>();
for (PhysicalCard card : cards) {
if (card.getZone().isPublic() || (card.getZone().isVisibleByOwner() && card.getOwner().equals(_self)))
removedCardsVisibleByPlayer.add(card);
}
_events.add(new GameEvent(RCFP).otherCardIds(getCardIds(removedCardsVisibleByPlayer)).participantId(playerPerforming));
}
@Override

View File

@@ -32,7 +32,6 @@ public class DefaultLotroGame implements LotroGame {
private ActionStack _actionStack;
private LotroFormat _format;
private GameResultListener _gameResultListener;
private Set<String> _allPlayers;
@@ -40,9 +39,10 @@ public class DefaultLotroGame implements LotroGame {
private String _winReason;
private Map<String, String> _losers = new HashMap<String, String>();
public DefaultLotroGame(LotroFormat format, Map<String, LotroDeck> decks, UserFeedback userFeedback, GameResultListener gameResultListener, final LotroCardBlueprintLibrary library) {
private Set<GameResultListener> _gameResultListeners = new HashSet<GameResultListener>();
public DefaultLotroGame(LotroFormat format, Map<String, LotroDeck> decks, UserFeedback userFeedback, final LotroCardBlueprintLibrary library) {
_format = format;
_gameResultListener = gameResultListener;
_actionStack = new ActionStack();
_allPlayers = decks.keySet();
@@ -79,6 +79,14 @@ public class DefaultLotroGame implements LotroGame {
ruleSet.applyRuleSet();
}
public void addGameResultListener(GameResultListener listener) {
_gameResultListeners.add(listener);
}
public void removeGameResultListener(GameResultListener listener) {
_gameResultListeners.remove(listener);
}
@Override
public LotroFormat getFormat() {
return _format;
@@ -103,12 +111,10 @@ public class DefaultLotroGame implements LotroGame {
_winReason = reason;
if (_gameState != null)
_gameState.sendMessage(_winnerPlayerId + " is the winner due to: " + reason);
if (_gameState != null)
_gameState.gameFinished();
if (_gameResultListener != null) {
for (GameResultListener gameResultListener : _gameResultListeners) {
Set<String> losers = new HashSet<String>(_allPlayers);
losers.remove(_winnerPlayerId);
_gameResultListener.gameFinished(_winnerPlayerId, losers, reason);
gameResultListener.gameFinished(_winnerPlayerId, losers, reason);
}
}

View File

@@ -0,0 +1,85 @@
package com.gempukku.lotro.game;
import com.gempukku.lotro.game.state.EventSerializer;
import com.gempukku.lotro.game.state.GameEvent;
import com.gempukku.lotro.game.state.GatheringParticipantCommunicationChannel;
import com.gempukku.lotro.logic.timing.GameResultListener;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.File;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
public class GameRecording implements GameResultListener {
private Map<String, GatheringParticipantCommunicationChannel> _gameProgress;
private static String _possibleChars = "abcdefghijklmnopqrstuvwxyz0123456789";
private static int _charsCount = _possibleChars.length();
public GameRecording(Map<String, GatheringParticipantCommunicationChannel> gameProgress) {
_gameProgress = gameProgress;
}
private String randomUid() {
int length = 16;
char[] chars = new char[length];
Random rnd = new Random();
for (int i = 0; i < length; i++)
chars[i] = _possibleChars.charAt(rnd.nextInt(_charsCount));
return new String(chars);
}
@Override
public void gameFinished(String winnerPlayerId, Set<String> loserPlayerIds, String reason) {
File gameReplayFolder = new File("i:\\gemp-lotr\\replay");
gameReplayFolder.mkdirs();
for (Map.Entry<String, GatheringParticipantCommunicationChannel> playerRecordings : _gameProgress.entrySet()) {
String playerId = playerRecordings.getKey();
File playerReplayFolder = new File(gameReplayFolder, playerId);
playerReplayFolder.mkdir();
File replayFile;
do {
replayFile = new File(playerReplayFolder, randomUid() + ".xml");
} while (replayFile.exists());
final List<GameEvent> gameEvents = playerRecordings.getValue().consumeGameEvents();
try {
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
Document doc = documentBuilder.newDocument();
Element gameReplay = doc.createElement("gameReplay");
EventSerializer serializer = new EventSerializer();
for (GameEvent gameEvent : gameEvents) {
gameReplay.appendChild(serializer.serializeEvent(doc, gameEvent));
}
doc.appendChild(gameReplay);
// Prepare the DOM document for writing
Source source = new DOMSource(doc);
// Prepare the output file
Result result = new StreamResult(replayFile);
// Write the DOM document to the file
Transformer xformer = TransformerFactory.newInstance().newTransformer();
xformer.transform(source, result);
} catch (Exception exp) {
}
}
}
}

View File

@@ -32,12 +32,11 @@ public class LotroGameMediator {
private ReentrantReadWriteLock.ReadLock _readLock = _lock.readLock();
private ReentrantReadWriteLock.WriteLock _writeLock = _lock.writeLock();
public LotroGameMediator(LotroFormat lotroFormat, LotroGameParticipant[] participants, LotroCardBlueprintLibrary library, GameResultListener gameResultListener) {
public LotroGameMediator(LotroFormat lotroFormat, LotroGameParticipant[] participants, LotroCardBlueprintLibrary library) {
if (participants.length < 1)
throw new IllegalArgumentException("Game can't have less than one participant");
Map<String, LotroDeck> decks = new HashMap<String, LotroDeck>();
_communicationChannels = new HashMap<String, GatheringParticipantCommunicationChannel>();
for (LotroGameParticipant participant : participants) {
String participantId = participant.getPlayerId();
@@ -45,7 +44,26 @@ public class LotroGameMediator {
_playerClocks.put(participantId, 0);
_playersPlaying.add(participantId);
}
_lotroGame = new DefaultLotroGame(lotroFormat, decks, _userFeedback, gameResultListener, library);
_lotroGame = new DefaultLotroGame(lotroFormat, decks, _userFeedback, library);
final HashMap<String, GatheringParticipantCommunicationChannel> recordingChannels = new HashMap<String, GatheringParticipantCommunicationChannel>();
for (String playerId : _playersPlaying) {
final GatheringParticipantCommunicationChannel playerRecording = new GatheringParticipantCommunicationChannel(playerId);
_lotroGame.addGameStateListener(playerId, playerRecording);
recordingChannels.put(playerId, playerRecording);
}
_lotroGame.addGameResultListener(
new GameRecording(recordingChannels));
}
public void addGameResultListener(GameResultListener listener) {
_lotroGame.addGameResultListener(listener);
}
public void removeGameResultListener(GameResultListener listener) {
_lotroGame.removeGameResultListener(listener);
}
public String getWinner() {

View File

@@ -108,7 +108,8 @@ public class LotroServer extends AbstractServer {
ChatRoomMediator room = _chatServer.createChatRoom(chatRoomName);
room.sendMessage("System", "You're starting a game of " + formatName);
LotroGameMediator lotroGameMediator = new LotroGameMediator(lotroFormat, participants, _lotroCardBlueprintLibrary,
LotroGameMediator lotroGameMediator = new LotroGameMediator(lotroFormat, participants, _lotroCardBlueprintLibrary);
lotroGameMediator.addGameResultListener(
new GameResultListener() {
@Override
public void gameFinished(String winnerPlayerId, Set<String> loserPlayerIds, String reason) {