Fixing multi-threading issues.
This commit is contained in:
@@ -5,6 +5,8 @@ import com.gempukku.lotro.game.GatheringChatRoomListener;
|
||||
import javax.ws.rs.WebApplicationException;
|
||||
import javax.ws.rs.core.Response;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.locks.ReadWriteLock;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
|
||||
public class ChatRoomMediator {
|
||||
private ChatRoom _chatRoom = new ChatRoom();
|
||||
@@ -14,6 +16,8 @@ public class ChatRoomMediator {
|
||||
private int _channelInactivityTimeoutPeriod = 1000 * 10; // 10 seconds
|
||||
private Set<String> _allowedPlayers;
|
||||
|
||||
private ReadWriteLock _lock = new ReentrantReadWriteLock();
|
||||
|
||||
public ChatRoomMediator(int secondsTimeoutPeriod) {
|
||||
this(secondsTimeoutPeriod, null);
|
||||
}
|
||||
@@ -23,46 +27,76 @@ public class ChatRoomMediator {
|
||||
_channelInactivityTimeoutPeriod = 1000 * secondsTimeoutPeriod;
|
||||
}
|
||||
|
||||
public synchronized List<ChatMessage> joinUser(String playerId) {
|
||||
GatheringChatRoomListener value = new GatheringChatRoomListener();
|
||||
_listeners.put(playerId, value);
|
||||
_chatRoom.joinChatRoom(playerId, value);
|
||||
return value.consumeMessages();
|
||||
}
|
||||
|
||||
public synchronized List<ChatMessage> getPendingMessages(String playerId) {
|
||||
GatheringChatRoomListener gatheringChatRoomListener = _listeners.get(playerId);
|
||||
if (gatheringChatRoomListener == null)
|
||||
throw new WebApplicationException(Response.Status.NOT_FOUND);
|
||||
return gatheringChatRoomListener.consumeMessages();
|
||||
}
|
||||
|
||||
public synchronized void partUser(String playerId) {
|
||||
_chatRoom.partChatRoom(playerId);
|
||||
_listeners.remove(playerId);
|
||||
}
|
||||
|
||||
public synchronized void sendMessage(String playerId, String message, boolean admin) {
|
||||
if (!admin && _allowedPlayers != null && !_allowedPlayers.contains(playerId))
|
||||
throw new WebApplicationException(Response.Status.FORBIDDEN);
|
||||
|
||||
_chatRoom.postMessage(playerId, message);
|
||||
}
|
||||
|
||||
public synchronized void cleanup() {
|
||||
long currentTime = System.currentTimeMillis();
|
||||
Map<String, GatheringChatRoomListener> copy = new HashMap<String, GatheringChatRoomListener>(_listeners);
|
||||
for (Map.Entry<String, GatheringChatRoomListener> playerListener : copy.entrySet()) {
|
||||
String playerId = playerListener.getKey();
|
||||
GatheringChatRoomListener listener = playerListener.getValue();
|
||||
if (currentTime > listener.getLastConsumed().getTime() + _channelInactivityTimeoutPeriod) {
|
||||
_chatRoom.partChatRoom(playerId);
|
||||
_listeners.remove(playerId);
|
||||
}
|
||||
public List<ChatMessage> joinUser(String playerId) {
|
||||
_lock.writeLock();
|
||||
try {
|
||||
GatheringChatRoomListener value = new GatheringChatRoomListener();
|
||||
_listeners.put(playerId, value);
|
||||
_chatRoom.joinChatRoom(playerId, value);
|
||||
return value.consumeMessages();
|
||||
} finally {
|
||||
_lock.writeLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized Collection<String> getUsersInRoom() {
|
||||
return _chatRoom.getUsersInRoom();
|
||||
public List<ChatMessage> getPendingMessages(String playerId) {
|
||||
_lock.readLock().lock();
|
||||
try {
|
||||
GatheringChatRoomListener gatheringChatRoomListener = _listeners.get(playerId);
|
||||
if (gatheringChatRoomListener == null)
|
||||
throw new WebApplicationException(Response.Status.NOT_FOUND);
|
||||
return gatheringChatRoomListener.consumeMessages();
|
||||
} finally {
|
||||
_lock.readLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public void partUser(String playerId) {
|
||||
_lock.writeLock().lock();
|
||||
try {
|
||||
_chatRoom.partChatRoom(playerId);
|
||||
_listeners.remove(playerId);
|
||||
} finally {
|
||||
_lock.writeLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public void sendMessage(String playerId, String message, boolean admin) {
|
||||
_lock.writeLock().lock();
|
||||
try {
|
||||
if (!admin && _allowedPlayers != null && !_allowedPlayers.contains(playerId))
|
||||
throw new WebApplicationException(Response.Status.FORBIDDEN);
|
||||
|
||||
_chatRoom.postMessage(playerId, message);
|
||||
} finally {
|
||||
_lock.writeLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public void cleanup() {
|
||||
_lock.writeLock().lock();
|
||||
try {
|
||||
long currentTime = System.currentTimeMillis();
|
||||
Map<String, GatheringChatRoomListener> copy = new HashMap<String, GatheringChatRoomListener>(_listeners);
|
||||
for (Map.Entry<String, GatheringChatRoomListener> playerListener : copy.entrySet()) {
|
||||
String playerId = playerListener.getKey();
|
||||
GatheringChatRoomListener listener = playerListener.getValue();
|
||||
if (currentTime > listener.getLastConsumed().getTime() + _channelInactivityTimeoutPeriod) {
|
||||
_chatRoom.partChatRoom(playerId);
|
||||
_listeners.remove(playerId);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
_lock.writeLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public Collection<String> getUsersInRoom() {
|
||||
_lock.readLock().lock();
|
||||
try {
|
||||
return _chatRoom.getUsersInRoom();
|
||||
} finally {
|
||||
_lock.readLock().unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.gempukku.lotro.collection;
|
||||
|
||||
import com.gempukku.lotro.common.CardType;
|
||||
import com.gempukku.lotro.db.CollectionDAO;
|
||||
import com.gempukku.lotro.db.PlayerDAO;
|
||||
import com.gempukku.lotro.db.vo.CollectionType;
|
||||
@@ -10,6 +11,7 @@ import java.io.IOException;
|
||||
import java.sql.SQLException;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
|
||||
public class CollectionsManager {
|
||||
@@ -20,10 +22,53 @@ public class CollectionsManager {
|
||||
private CollectionDAO _collectionDAO;
|
||||
private DeliveryService _deliveryService;
|
||||
|
||||
public CollectionsManager(PlayerDAO playerDAO, CollectionDAO collectionDAO, DeliveryService deliveryService) {
|
||||
private CountDownLatch _collectionReadyLatch = new CountDownLatch(1);
|
||||
private DefaultCardCollection _defaultCollection;
|
||||
|
||||
public CollectionsManager(PlayerDAO playerDAO, CollectionDAO collectionDAO, DeliveryService deliveryService, final LotroCardBlueprintLibrary lotroCardBlueprintLibrary) {
|
||||
_playerDAO = playerDAO;
|
||||
_collectionDAO = collectionDAO;
|
||||
_deliveryService = deliveryService;
|
||||
|
||||
_defaultCollection = new DefaultCardCollection();
|
||||
|
||||
// Hunters have 1-194 normal cards, 9 "O" cards, and 3 extra to cover the different culture versions of 15_60
|
||||
|
||||
Thread thr = new Thread() {
|
||||
public void run() {
|
||||
final int[] cardCounts = new int[]{129, 365, 122, 122, 365, 128, 128, 365, 122, 52, 122, 266, 203, 203, 15, 207, 6, 157, 149, 40};
|
||||
|
||||
for (int i = 0; i <= 19; i++) {
|
||||
System.out.println("Loading set " + i);
|
||||
for (int j = 1; j <= cardCounts[i]; j++) {
|
||||
String blueprintId = i + "_" + j;
|
||||
try {
|
||||
if (lotroCardBlueprintLibrary.getBaseBlueprintId(blueprintId).equals(blueprintId)) {
|
||||
LotroCardBlueprint cardBlueprint = lotroCardBlueprintLibrary.getLotroCardBlueprint(blueprintId);
|
||||
CardType cardType = cardBlueprint.getCardType();
|
||||
if (cardType == CardType.SITE || cardType == CardType.THE_ONE_RING)
|
||||
_defaultCollection.addItem(blueprintId, 1);
|
||||
else
|
||||
_defaultCollection.addItem(blueprintId, 4);
|
||||
}
|
||||
} catch (IllegalArgumentException exp) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
_collectionReadyLatch.countDown();
|
||||
}
|
||||
};
|
||||
thr.start();
|
||||
}
|
||||
|
||||
public CardCollection getDefaultCollection() {
|
||||
try {
|
||||
_collectionReadyLatch.await();
|
||||
} catch (InterruptedException exp) {
|
||||
throw new RuntimeException("Error while awaiting loading a default colleciton", exp);
|
||||
}
|
||||
return _defaultCollection;
|
||||
}
|
||||
|
||||
public void clearDBCache() {
|
||||
@@ -36,6 +81,9 @@ public class CollectionsManager {
|
||||
if (collectionType.contains("+"))
|
||||
return createSumCollection(player, collectionType.split("\\+"));
|
||||
|
||||
if (collectionType.equals("default"))
|
||||
return getDefaultCollection();
|
||||
|
||||
Map<String, CardCollection> playerCollections = _collections.get(player.getName());
|
||||
if (playerCollections != null) {
|
||||
final CardCollection cardCollection = playerCollections.get(collectionType);
|
||||
|
||||
@@ -23,11 +23,11 @@ public class DeckDAO {
|
||||
_library = library;
|
||||
}
|
||||
|
||||
public void clearCache() {
|
||||
public synchronized void clearCache() {
|
||||
_decks.clear();
|
||||
}
|
||||
|
||||
public LotroDeck getDeckForPlayer(Player player, String name) {
|
||||
public synchronized LotroDeck getDeckForPlayer(Player player, String name) {
|
||||
Map<String, LotroDeck> deckMap = getPlayerDecks(player);
|
||||
return deckMap.get(name);
|
||||
}
|
||||
@@ -59,7 +59,7 @@ public class DeckDAO {
|
||||
return deck;
|
||||
}
|
||||
|
||||
public Set<String> getPlayerDeckNames(Player player) {
|
||||
public synchronized Set<String> getPlayerDeckNames(Player player) {
|
||||
return Collections.unmodifiableSet(getPlayerDecks(player).keySet());
|
||||
}
|
||||
|
||||
@@ -137,7 +137,7 @@ public class DeckDAO {
|
||||
// }
|
||||
// }
|
||||
|
||||
public LotroDeck buildDeckFromContents(String deckName, String contents) {
|
||||
public synchronized LotroDeck buildDeckFromContents(String deckName, String contents) {
|
||||
if (contents.contains("|")) {
|
||||
return DeckSerialization.buildDeckFromContents(deckName, contents);
|
||||
} else {
|
||||
|
||||
@@ -21,12 +21,12 @@ public class PlayerDAO {
|
||||
_dbAccess = dbAccess;
|
||||
}
|
||||
|
||||
public void clearCache() {
|
||||
public synchronized void clearCache() {
|
||||
_playersByName.clear();
|
||||
_playersById.clear();
|
||||
}
|
||||
|
||||
public Player getPlayer(int id) {
|
||||
public synchronized Player getPlayer(int id) {
|
||||
if (_playersById.containsKey(id))
|
||||
return _playersById.get(id);
|
||||
|
||||
@@ -40,7 +40,7 @@ public class PlayerDAO {
|
||||
}
|
||||
}
|
||||
|
||||
public Player getPlayer(String playerName) {
|
||||
public synchronized Player getPlayer(String playerName) {
|
||||
if (_playersByName.containsKey(playerName))
|
||||
return _playersByName.get(playerName);
|
||||
try {
|
||||
@@ -53,7 +53,7 @@ public class PlayerDAO {
|
||||
}
|
||||
}
|
||||
|
||||
public Player loginUser(String login, String password) throws SQLException {
|
||||
public synchronized Player loginUser(String login, String password) throws SQLException {
|
||||
Connection conn = _dbAccess.getDataSource().getConnection();
|
||||
try {
|
||||
PreparedStatement statement = conn.prepareStatement("select id, name, type, last_login_reward from player where name=? and password=?");
|
||||
@@ -84,7 +84,7 @@ public class PlayerDAO {
|
||||
}
|
||||
}
|
||||
|
||||
public void setLastReward(Player player, int currentReward) throws SQLException {
|
||||
public synchronized void setLastReward(Player player, int currentReward) throws SQLException {
|
||||
Connection conn = _dbAccess.getDataSource().getConnection();
|
||||
try {
|
||||
PreparedStatement statement = conn.prepareStatement("update player set last_login_reward =? where id=?");
|
||||
@@ -101,7 +101,7 @@ public class PlayerDAO {
|
||||
}
|
||||
}
|
||||
|
||||
public boolean updateLastReward(Player player, int previousReward, int currentReward) throws SQLException {
|
||||
public synchronized boolean updateLastReward(Player player, int previousReward, int currentReward) throws SQLException {
|
||||
Connection conn = _dbAccess.getDataSource().getConnection();
|
||||
try {
|
||||
PreparedStatement statement = conn.prepareStatement("update player set last_login_reward =? where id=? and last_login_reward=?");
|
||||
|
||||
@@ -17,11 +17,13 @@ public class DefaultCardCollection implements MutableCardCollection {
|
||||
_currency = cardCollection.getCurrency();
|
||||
}
|
||||
|
||||
public void addCurrency(int currency) {
|
||||
@Override
|
||||
public synchronized void addCurrency(int currency) {
|
||||
_currency += currency;
|
||||
}
|
||||
|
||||
public boolean removeCurrency(int currency) {
|
||||
@Override
|
||||
public synchronized boolean removeCurrency(int currency) {
|
||||
if (_currency < currency)
|
||||
return false;
|
||||
_currency -= currency;
|
||||
@@ -29,12 +31,12 @@ public class DefaultCardCollection implements MutableCardCollection {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCurrency() {
|
||||
public synchronized int getCurrency() {
|
||||
return _currency;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addItem(String itemId, int toAdd) {
|
||||
public synchronized void addItem(String itemId, int toAdd) {
|
||||
Item oldCount = _counts.get(itemId);
|
||||
if (oldCount == null)
|
||||
_counts.put(itemId, Item.createItem(itemId, toAdd));
|
||||
@@ -43,7 +45,7 @@ public class DefaultCardCollection implements MutableCardCollection {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeItem(String itemId, int toRemove) {
|
||||
public synchronized boolean removeItem(String itemId, int toRemove) {
|
||||
Item oldCount = _counts.get(itemId);
|
||||
if (oldCount == null || oldCount.getCount() < toRemove)
|
||||
return false;
|
||||
@@ -54,14 +56,6 @@ public class DefaultCardCollection implements MutableCardCollection {
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean hasSelection(String packId, String selection, PacksStorage packsStorage) {
|
||||
for (Item item : packsStorage.openPack(packId)) {
|
||||
if (item.getBlueprintId().equals(selection))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized CardCollection openPack(String packId, String selection, PacksStorage packsStorage) {
|
||||
Item count = _counts.get(packId);
|
||||
@@ -96,15 +90,23 @@ public class DefaultCardCollection implements MutableCardCollection {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Item> getAll() {
|
||||
public synchronized Map<String, Item> getAll() {
|
||||
return Collections.unmodifiableMap(_counts);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount(String blueprintId) {
|
||||
public synchronized int getItemCount(String blueprintId) {
|
||||
Item count = _counts.get(blueprintId);
|
||||
if (count == null)
|
||||
return 0;
|
||||
return count.getCount();
|
||||
}
|
||||
|
||||
private boolean hasSelection(String packId, String selection, PacksStorage packsStorage) {
|
||||
for (Item item : packsStorage.openPack(packId)) {
|
||||
if (item.getBlueprintId().equals(selection))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,18 +12,18 @@ public class GatheringChatRoomListener implements ChatRoomListener {
|
||||
private Date _lastConsumed = new Date();
|
||||
|
||||
@Override
|
||||
public void messageReceived(ChatMessage message) {
|
||||
public synchronized void messageReceived(ChatMessage message) {
|
||||
_messages.add(message);
|
||||
}
|
||||
|
||||
public List<ChatMessage> consumeMessages() {
|
||||
public synchronized List<ChatMessage> consumeMessages() {
|
||||
List<ChatMessage> messages = _messages;
|
||||
_messages = new LinkedList<ChatMessage>();
|
||||
_lastConsumed = new Date();
|
||||
return messages;
|
||||
}
|
||||
|
||||
public Date getLastConsumed() {
|
||||
public synchronized Date getLastConsumed() {
|
||||
return _lastConsumed;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,17 +2,15 @@ package com.gempukku.lotro.game;
|
||||
|
||||
import com.gempukku.lotro.AbstractServer;
|
||||
import com.gempukku.lotro.chat.ChatServer;
|
||||
import com.gempukku.lotro.common.CardType;
|
||||
import com.gempukku.lotro.db.DeckDAO;
|
||||
import com.gempukku.lotro.logic.timing.GameResultListener;
|
||||
import com.gempukku.lotro.logic.vo.LotroDeck;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.locks.ReadWriteLock;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
|
||||
public class LotroServer extends AbstractServer {
|
||||
private static final Logger log = Logger.getLogger(LotroServer.class);
|
||||
@@ -29,72 +27,24 @@ public class LotroServer extends AbstractServer {
|
||||
private int _nextGameId = 1;
|
||||
|
||||
private DeckDAO _deckDao;
|
||||
private GameHistoryService _gameHistoryService;
|
||||
|
||||
private DefaultCardCollection _defaultCollection;
|
||||
private CountDownLatch _collectionReadyLatch = new CountDownLatch(1);
|
||||
|
||||
private ChatServer _chatServer;
|
||||
private boolean _test;
|
||||
private GameRecorder _gameRecorder;
|
||||
|
||||
public LotroServer(DeckDAO deckDao, GameHistoryService gameHistoryService, LotroCardBlueprintLibrary library, ChatServer chatServer, boolean test) {
|
||||
private ReadWriteLock _lock = new ReentrantReadWriteLock();
|
||||
|
||||
public LotroServer(DeckDAO deckDao, LotroCardBlueprintLibrary library, ChatServer chatServer, GameRecorder gameRecorder) {
|
||||
_deckDao = deckDao;
|
||||
_gameHistoryService = gameHistoryService;
|
||||
_lotroCardBlueprintLibrary = library;
|
||||
_chatServer = chatServer;
|
||||
_test = test;
|
||||
_defaultCollection = new DefaultCardCollection();
|
||||
|
||||
// Hunters have 1-194 normal cards, 9 "O" cards, and 3 extra to cover the different culture versions of 15_60
|
||||
|
||||
Thread thr = new Thread() {
|
||||
public void run() {
|
||||
final int[] cardCounts = new int[]{129, 365, 122, 122, 365, 128, 128, 365, 122, 52, 122, 266, 203, 203, 15, 207, 6, 157, 149, 40};
|
||||
|
||||
for (int i = 0; i <= 19; i++) {
|
||||
System.out.println("Loading set " + i);
|
||||
for (int j = 1; j <= cardCounts[i]; j++) {
|
||||
String blueprintId = i + "_" + j;
|
||||
try {
|
||||
if (_lotroCardBlueprintLibrary.getBaseBlueprintId(blueprintId).equals(blueprintId)) {
|
||||
LotroCardBlueprint cardBlueprint = _lotroCardBlueprintLibrary.getLotroCardBlueprint(blueprintId);
|
||||
CardType cardType = cardBlueprint.getCardType();
|
||||
if (cardType == CardType.SITE || cardType == CardType.THE_ONE_RING)
|
||||
_defaultCollection.addItem(blueprintId, 1);
|
||||
else
|
||||
_defaultCollection.addItem(blueprintId, 4);
|
||||
}
|
||||
} catch (IllegalArgumentException exp) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
_collectionReadyLatch.countDown();
|
||||
}
|
||||
};
|
||||
thr.start();
|
||||
|
||||
_gameRecorder = new GameRecorder(_gameHistoryService);
|
||||
}
|
||||
|
||||
public InputStream getGameRecording(String playerId, String gameId) throws IOException {
|
||||
return _gameRecorder.getRecordedGame(playerId, gameId);
|
||||
}
|
||||
|
||||
public CardCollection getDefaultCollection() {
|
||||
try {
|
||||
_collectionReadyLatch.await();
|
||||
} catch (InterruptedException exp) {
|
||||
throw new RuntimeException("Error while awaiting loading a default colleciton", exp);
|
||||
}
|
||||
return _defaultCollection;
|
||||
_gameRecorder = gameRecorder;
|
||||
}
|
||||
|
||||
protected void cleanup() {
|
||||
long currentTime = System.currentTimeMillis();
|
||||
_lock.writeLock().lock();
|
||||
try {
|
||||
long currentTime = System.currentTimeMillis();
|
||||
|
||||
synchronized (_finishedGamesTime) {
|
||||
LinkedHashMap<String, Date> copy = new LinkedHashMap<String, Date>(_finishedGamesTime);
|
||||
for (Map.Entry<String, Date> finishedGame : copy.entrySet()) {
|
||||
String gameId = finishedGame.getKey();
|
||||
@@ -112,81 +62,103 @@ public class LotroServer extends AbstractServer {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (LotroGameMediator lotroGameMediator : _runningGames.values())
|
||||
lotroGameMediator.cleanup();
|
||||
for (LotroGameMediator lotroGameMediator : _runningGames.values())
|
||||
lotroGameMediator.cleanup();
|
||||
} finally {
|
||||
_lock.writeLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
private String getChatRoomName(String gameId) {
|
||||
return "Game" + gameId;
|
||||
}
|
||||
|
||||
public synchronized String createNewGame(LotroFormat lotroFormat, String tournamentName, final LotroGameParticipant[] participants, boolean allowSpectators, boolean allowCancelling, boolean muteSpectators, boolean competitiveTime
|
||||
) {
|
||||
if (participants.length < 2)
|
||||
throw new IllegalArgumentException("There has to be at least two players");
|
||||
final String gameId = String.valueOf(_nextGameId);
|
||||
public String createNewGame(LotroFormat lotroFormat, String tournamentName, final LotroGameParticipant[] participants, boolean allowSpectators, boolean allowCancelling, boolean muteSpectators, boolean competitiveTime) {
|
||||
_lock.writeLock().lock();
|
||||
try {
|
||||
if (participants.length < 2)
|
||||
throw new IllegalArgumentException("There has to be at least two players");
|
||||
final String gameId = String.valueOf(_nextGameId);
|
||||
|
||||
if (muteSpectators) {
|
||||
Set<String> allowedUsers = new HashSet<String>();
|
||||
for (LotroGameParticipant participant : participants)
|
||||
allowedUsers.add(participant.getPlayerId());
|
||||
_chatServer.createVoicedChatRoom(getChatRoomName(gameId), allowedUsers, 30);
|
||||
} else
|
||||
_chatServer.createChatRoom(getChatRoomName(gameId), 30);
|
||||
if (muteSpectators) {
|
||||
Set<String> allowedUsers = new HashSet<String>();
|
||||
for (LotroGameParticipant participant : participants)
|
||||
allowedUsers.add(participant.getPlayerId());
|
||||
_chatServer.createVoicedChatRoom(getChatRoomName(gameId), allowedUsers, 30);
|
||||
} else
|
||||
_chatServer.createChatRoom(getChatRoomName(gameId), 30);
|
||||
|
||||
LotroGameMediator lotroGameMediator = new LotroGameMediator(lotroFormat, participants, _lotroCardBlueprintLibrary,
|
||||
competitiveTime ? 60 * 40 : 60 * 80, !allowSpectators, allowCancelling);
|
||||
lotroGameMediator.addGameResultListener(
|
||||
new GameResultListener() {
|
||||
@Override
|
||||
public void gameFinished(String winnerPlayerId, String winReason, Map<String, String> loserPlayerIdsWithReasons) {
|
||||
synchronized (_finishedGamesTime) {
|
||||
_finishedGamesTime.put(gameId, new Date());
|
||||
LotroGameMediator lotroGameMediator = new LotroGameMediator(lotroFormat, participants, _lotroCardBlueprintLibrary,
|
||||
competitiveTime ? 60 * 40 : 60 * 80, !allowSpectators, allowCancelling);
|
||||
lotroGameMediator.addGameResultListener(
|
||||
new GameResultListener() {
|
||||
@Override
|
||||
public void gameFinished(String winnerPlayerId, String winReason, Map<String, String> loserPlayerIdsWithReasons) {
|
||||
_lock.writeLock().lock();
|
||||
try {
|
||||
_finishedGamesTime.put(gameId, new Date());
|
||||
} finally {
|
||||
_lock.writeLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void gameCancelled() {
|
||||
_lock.writeLock().lock();
|
||||
try {
|
||||
_finishedGamesTime.put(gameId, new Date());
|
||||
} finally {
|
||||
_lock.writeLock().unlock();
|
||||
}
|
||||
}
|
||||
});
|
||||
lotroGameMediator.sendMessageToPlayers("You're starting a game of " + lotroFormat.getName());
|
||||
|
||||
StringBuffer players = new StringBuffer();
|
||||
Map<String, String> deckNames = new HashMap<String, String>();
|
||||
for (LotroGameParticipant participant : participants) {
|
||||
deckNames.put(participant.getPlayerId(), participant.getDeck().getDeckName());
|
||||
if (players.length() > 0)
|
||||
players.append(", ");
|
||||
players.append(participant.getPlayerId());
|
||||
}
|
||||
|
||||
lotroGameMediator.sendMessageToPlayers("Players in the game are: " + players.toString());
|
||||
|
||||
final GameRecorder.GameRecordingInProgress gameRecordingInProgress = _gameRecorder.recordGame(lotroGameMediator, lotroFormat.getName(), tournamentName, deckNames);
|
||||
lotroGameMediator.addGameResultListener(
|
||||
new GameResultListener() {
|
||||
@Override
|
||||
public void gameFinished(String winnerPlayerId, String winReason, Map<String, String> loserPlayerIdsWithReasons) {
|
||||
_lock.writeLock().lock();
|
||||
try {
|
||||
final Map.Entry<String, String> loserEntry = loserPlayerIdsWithReasons.entrySet().iterator().next();
|
||||
|
||||
gameRecordingInProgress.finishRecording(winnerPlayerId, winReason, loserEntry.getKey(), loserEntry.getValue());
|
||||
} finally {
|
||||
_lock.writeLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void gameCancelled() {
|
||||
_lock.writeLock().lock();
|
||||
try {
|
||||
gameRecordingInProgress.finishRecording(participants[0].getPlayerId(), "Game cancelled due to error", participants[1].getPlayerId(), "Game cancelled due to error");
|
||||
} finally {
|
||||
_lock.writeLock().unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
@Override
|
||||
public void gameCancelled() {
|
||||
synchronized (_finishedGamesTime) {
|
||||
_finishedGamesTime.put(gameId, new Date());
|
||||
}
|
||||
}
|
||||
});
|
||||
lotroGameMediator.sendMessageToPlayers("You're starting a game of " + lotroFormat.getName());
|
||||
|
||||
StringBuffer players = new StringBuffer();
|
||||
Map<String, String> deckNames = new HashMap<String, String>();
|
||||
for (LotroGameParticipant participant : participants) {
|
||||
deckNames.put(participant.getPlayerId(), participant.getDeck().getDeckName());
|
||||
if (players.length() > 0)
|
||||
players.append(", ");
|
||||
players.append(participant.getPlayerId());
|
||||
_runningGames.put(gameId, lotroGameMediator);
|
||||
_nextGameId++;
|
||||
return gameId;
|
||||
} finally {
|
||||
_lock.writeLock().unlock();
|
||||
}
|
||||
|
||||
lotroGameMediator.sendMessageToPlayers("Players in the game are: " + players.toString());
|
||||
|
||||
final GameRecorder.GameRecordingInProgress gameRecordingInProgress = _gameRecorder.recordGame(lotroGameMediator, lotroFormat.getName(), tournamentName, deckNames);
|
||||
lotroGameMediator.addGameResultListener(
|
||||
new GameResultListener() {
|
||||
@Override
|
||||
public void gameFinished(String winnerPlayerId, String winReason, Map<String, String> loserPlayerIdsWithReasons) {
|
||||
final Map.Entry<String, String> loserEntry = loserPlayerIdsWithReasons.entrySet().iterator().next();
|
||||
|
||||
gameRecordingInProgress.finishRecording(winnerPlayerId, winReason, loserEntry.getKey(), loserEntry.getValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void gameCancelled() {
|
||||
gameRecordingInProgress.finishRecording(participants[0].getPlayerId(), "Game cancelled due to error", participants[1].getPlayerId(), "Game cancelled due to error");
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
_runningGames.put(gameId, lotroGameMediator);
|
||||
_nextGameId++;
|
||||
return gameId;
|
||||
}
|
||||
|
||||
public LotroDeck getParticipantDeck(Player player, String deckName) {
|
||||
@@ -217,7 +189,12 @@ public class LotroServer extends AbstractServer {
|
||||
}
|
||||
|
||||
public LotroGameMediator getGameById(String gameId) {
|
||||
return _runningGames.get(gameId);
|
||||
_lock.readLock().lock();
|
||||
try {
|
||||
return _runningGames.get(gameId);
|
||||
} finally {
|
||||
_lock.readLock().unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -99,10 +99,6 @@ public class HallServer extends AbstractServer {
|
||||
}
|
||||
}
|
||||
|
||||
public Map<String, LotroFormat> getSupportedFormats() {
|
||||
return _formatLibrary.getHallFormats();
|
||||
}
|
||||
|
||||
private void cancelWaitingTables() {
|
||||
_awaitingTables.clear();
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ public class LeagueService {
|
||||
_collectionsManager = collectionsManager;
|
||||
}
|
||||
|
||||
public void clearCache() {
|
||||
public synchronized void clearCache() {
|
||||
_leagueSerieStandings.clear();
|
||||
_leagueStandings.clear();
|
||||
_activeLeaguesLoadedDate = 0;
|
||||
@@ -68,7 +68,7 @@ public class LeagueService {
|
||||
}
|
||||
}
|
||||
|
||||
public List<League> getActiveLeagues() {
|
||||
public synchronized List<League> getActiveLeagues() {
|
||||
if (DateUtils.getCurrentDate() == _activeLeaguesLoadedDate)
|
||||
return Collections.unmodifiableList(_activeLeagues);
|
||||
else {
|
||||
@@ -86,11 +86,11 @@ public class LeagueService {
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isPlayerInLeague(League league, Player player) {
|
||||
public synchronized boolean isPlayerInLeague(League league, Player player) {
|
||||
return _leagueParticipationDAO.getUsersParticipating(league.getType()).contains(player.getName());
|
||||
}
|
||||
|
||||
public boolean playerJoinsLeague(League league, Player player) {
|
||||
public synchronized boolean playerJoinsLeague(League league, Player player) {
|
||||
if (isPlayerInLeague(league, player))
|
||||
return false;
|
||||
int cost = league.getCost();
|
||||
@@ -106,7 +106,7 @@ public class LeagueService {
|
||||
}
|
||||
}
|
||||
|
||||
public League getLeagueByType(String type) {
|
||||
public synchronized League getLeagueByType(String type) {
|
||||
for (League league : getActiveLeagues()) {
|
||||
if (league.getType().equals(type))
|
||||
return league;
|
||||
@@ -114,7 +114,7 @@ public class LeagueService {
|
||||
return null;
|
||||
}
|
||||
|
||||
public CollectionType getCollectionTypeByCode(String collectionTypeCode) {
|
||||
public synchronized CollectionType getCollectionTypeByCode(String collectionTypeCode) {
|
||||
for (League league : getActiveLeagues()) {
|
||||
for (LeagueSerieData leagueSerieData : league.getLeagueData().getSeries()) {
|
||||
CollectionType collectionType = leagueSerieData.getCollectionType();
|
||||
@@ -125,7 +125,7 @@ public class LeagueService {
|
||||
return null;
|
||||
}
|
||||
|
||||
public LeagueSerieData getCurrentLeagueSerie(League league) {
|
||||
public synchronized LeagueSerieData getCurrentLeagueSerie(League league) {
|
||||
final int currentDate = DateUtils.getCurrentDate();
|
||||
|
||||
for (LeagueSerieData leagueSerieData : league.getLeagueData().getSeries()) {
|
||||
@@ -136,7 +136,7 @@ public class LeagueService {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void reportLeagueGameResult(League league, LeagueSerieData serie, String winner, String loser) {
|
||||
public synchronized void reportLeagueGameResult(League league, LeagueSerieData serie, String winner, String loser) {
|
||||
_leagueMatchDao.addPlayedMatch(league.getType(), serie.getName(), winner, loser);
|
||||
|
||||
_leagueStandings.remove(LeagueMapKeys.getLeagueMapKey(league));
|
||||
@@ -173,7 +173,7 @@ public class LeagueService {
|
||||
return result;
|
||||
}
|
||||
|
||||
public List<PlayerStanding> getLeagueStandings(League league) {
|
||||
public synchronized List<PlayerStanding> getLeagueStandings(League league) {
|
||||
List<PlayerStanding> leagueStandings = _leagueStandings.get(LeagueMapKeys.getLeagueMapKey(league));
|
||||
if (leagueStandings == null) {
|
||||
synchronized (this) {
|
||||
@@ -184,7 +184,7 @@ public class LeagueService {
|
||||
return leagueStandings;
|
||||
}
|
||||
|
||||
public List<PlayerStanding> getLeagueSerieStandings(League league, LeagueSerieData leagueSerie) {
|
||||
public synchronized List<PlayerStanding> getLeagueSerieStandings(League league, LeagueSerieData leagueSerie) {
|
||||
List<PlayerStanding> serieStandings = _leagueSerieStandings.get(LeagueMapKeys.getLeagueSerieMapKey(league, leagueSerie));
|
||||
if (serieStandings == null) {
|
||||
synchronized (this) {
|
||||
@@ -219,7 +219,7 @@ public class LeagueService {
|
||||
return StandingsProducer.produceStandings(playersParticipating, matches, 2, 1, Collections.<String, Integer>emptyMap());
|
||||
}
|
||||
|
||||
public boolean canPlayRankedGame(League league, LeagueSerieData season, String player) {
|
||||
public synchronized boolean canPlayRankedGame(League league, LeagueSerieData season, String player) {
|
||||
int maxMatches = season.getMaxMatches();
|
||||
Collection<LeagueMatchResult> playedInSeason = getPlayerMatchesInSerie(league, season, player);
|
||||
if (playedInSeason.size() >= maxMatches)
|
||||
@@ -227,7 +227,7 @@ public class LeagueService {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean canPlayRankedGameAgainst(League league, LeagueSerieData season, String playerOne, String playerTwo) {
|
||||
public synchronized boolean canPlayRankedGameAgainst(League league, LeagueSerieData season, String playerOne, String playerTwo) {
|
||||
Collection<LeagueMatchResult> playedInSeason = getPlayerMatchesInSerie(league, season, playerOne);
|
||||
for (LeagueMatchResult leagueMatch : playedInSeason) {
|
||||
if (playerTwo.equals(leagueMatch.getWinner()) || playerTwo.equals(leagueMatch.getLoser()))
|
||||
|
||||
@@ -98,7 +98,7 @@ public class SingleEliminationRecurringQueue implements TournamentQueue {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void leaveAllPlayers(CollectionsManager collectionsManager) {
|
||||
public synchronized void leaveAllPlayers(CollectionsManager collectionsManager) {
|
||||
if (_cost > 0) {
|
||||
for (String player : _playerDecks.keySet())
|
||||
collectionsManager.addCurrencyToPlayerCollection(player, _currencyCollection, _cost);
|
||||
|
||||
@@ -167,10 +167,7 @@ public class CollectionResource extends AbstractResource {
|
||||
}
|
||||
|
||||
private CardCollection getCollection(Player player, String collectionType) {
|
||||
if (collectionType.equals("default"))
|
||||
return _lotroServer.getDefaultCollection();
|
||||
else
|
||||
return _collectionsManager.getPlayerCollection(player, collectionType);
|
||||
return _collectionsManager.getPlayerCollection(player, collectionType);
|
||||
}
|
||||
|
||||
@Path("/{collectionType}")
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.gempukku.lotro.server;
|
||||
import com.gempukku.lotro.common.Side;
|
||||
import com.gempukku.lotro.db.DeckDAO;
|
||||
import com.gempukku.lotro.game.*;
|
||||
import com.gempukku.lotro.game.formats.LotroFormatLibrary;
|
||||
import com.gempukku.lotro.hall.HallServer;
|
||||
import com.gempukku.lotro.logic.GameUtils;
|
||||
import com.gempukku.lotro.logic.vo.LotroDeck;
|
||||
@@ -36,6 +37,8 @@ public class DeckResource extends AbstractResource {
|
||||
private LotroCardBlueprintLibrary _library;
|
||||
@Context
|
||||
private DeckDAO _deckDao;
|
||||
@Context
|
||||
private LotroFormatLibrary _formatLibrary;
|
||||
|
||||
private SortAndFilterCards _sortAndFilterCards = new SortAndFilterCards();
|
||||
|
||||
@@ -217,7 +220,7 @@ public class DeckResource extends AbstractResource {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("<b>Free People</b>: " + fpCount + ", <b>Shadow</b>: " + shadowCount + "<br/>");
|
||||
|
||||
for (LotroFormat format : _hallServer.getSupportedFormats().values()) {
|
||||
for (LotroFormat format : _formatLibrary.getHallFormats().values()) {
|
||||
try {
|
||||
format.validateDeck(resourceOwner, deck);
|
||||
sb.append("<b>" + format.getName() + "</b>: <font color='green'>valid</font><br/>");
|
||||
|
||||
@@ -130,7 +130,7 @@ public class HallResource extends AbstractResource {
|
||||
hall.setAttribute("motd", motd);
|
||||
|
||||
_hallServer.processHall(resourceOwner, new SerializeHallInfoVisitor(doc, hall));
|
||||
for (Map.Entry<String, LotroFormat> format : _hallServer.getSupportedFormats().entrySet()) {
|
||||
for (Map.Entry<String, LotroFormat> format : _formatLibrary.getHallFormats().entrySet()) {
|
||||
Element formatElem = doc.createElement("format");
|
||||
formatElem.setAttribute("type", format.getKey());
|
||||
formatElem.appendChild(doc.createTextNode(format.getValue().getName()));
|
||||
|
||||
@@ -47,6 +47,8 @@ public class ServerResource extends AbstractResource {
|
||||
private ChatServer _chatServer;
|
||||
@Context
|
||||
private GameHistoryService _gameHistoryService;
|
||||
@Context
|
||||
private GameRecorder _gameRecorder;
|
||||
|
||||
public ServerResource() {
|
||||
if (!_test)
|
||||
@@ -126,7 +128,7 @@ public class ServerResource extends AbstractResource {
|
||||
return new StreamingOutput() {
|
||||
@Override
|
||||
public void write(OutputStream outputStream) throws IOException, WebApplicationException {
|
||||
final InputStream recordedGame = _lotroServer.getGameRecording(split[0], split[1]);
|
||||
final InputStream recordedGame = _gameRecorder.getRecordedGame(split[0], split[1]);
|
||||
if (recordedGame == null)
|
||||
throw new WebApplicationException(Response.Status.NOT_FOUND);
|
||||
try {
|
||||
|
||||
@@ -34,13 +34,12 @@ public class DaoProvider implements InjectableProvider<Context, Type> {
|
||||
private DbAccess _dbAccess;
|
||||
private CollectionSerializer _collectionSerializer;
|
||||
|
||||
@Context
|
||||
private LotroCardBlueprintLibrary _library;
|
||||
|
||||
public DaoProvider() {
|
||||
_dbAccess = new DbAccess();
|
||||
_collectionSerializer = new CollectionSerializer();
|
||||
|
||||
_library = new LotroCardBlueprintLibrary();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -5,6 +5,7 @@ import com.gempukku.lotro.collection.CollectionsManager;
|
||||
import com.gempukku.lotro.collection.DeliveryService;
|
||||
import com.gempukku.lotro.db.*;
|
||||
import com.gempukku.lotro.game.GameHistoryService;
|
||||
import com.gempukku.lotro.game.GameRecorder;
|
||||
import com.gempukku.lotro.game.LotroCardBlueprintLibrary;
|
||||
import com.gempukku.lotro.game.LotroServer;
|
||||
import com.gempukku.lotro.game.formats.LotroFormatLibrary;
|
||||
@@ -37,6 +38,7 @@ public class ServerProvider implements InjectableProvider<Context, Type> {
|
||||
private Injectable<CollectionsManager> _collectionsManagerInjectable;
|
||||
private Injectable<DeliveryService> _deliveryServiceInjectable;
|
||||
private Injectable<LotroFormatLibrary> _lotroFormatLibraryInjectable;
|
||||
private Injectable<GameRecorder> _gameRecorderInjectable;
|
||||
|
||||
@Context
|
||||
private PlayerDAO _playerDao;
|
||||
@@ -85,6 +87,8 @@ public class ServerProvider implements InjectableProvider<Context, Type> {
|
||||
return getMerchantServiceInjectable();
|
||||
if (type.equals(TournamentService.class))
|
||||
return getTournamentServiceInjectable();
|
||||
if (type.equals(GameRecorder.class))
|
||||
return getGameRecorderInjectable();
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -135,6 +139,19 @@ public class ServerProvider implements InjectableProvider<Context, Type> {
|
||||
return _gameHistoryServiceInjectable;
|
||||
}
|
||||
|
||||
private synchronized Injectable<GameRecorder> getGameRecorderInjectable() {
|
||||
if (_gameRecorderInjectable == null) {
|
||||
final GameRecorder gameRecorder = new GameRecorder(getGameHistoryServiceInjectable().getValue());
|
||||
_gameRecorderInjectable = new Injectable<GameRecorder>() {
|
||||
@Override
|
||||
public GameRecorder getValue() {
|
||||
return gameRecorder;
|
||||
}
|
||||
};
|
||||
}
|
||||
return _gameRecorderInjectable;
|
||||
}
|
||||
|
||||
private synchronized Injectable<MerchantService> getMerchantServiceInjectable() {
|
||||
if (_merchantServiceInjectable == null) {
|
||||
final MerchantService merchantService = new MerchantService(_library, getCollectionsManagerInjectable().getValue(), _merchantDao);
|
||||
@@ -208,7 +225,7 @@ public class ServerProvider implements InjectableProvider<Context, Type> {
|
||||
|
||||
private synchronized Injectable<LotroServer> getLotroServerInjectable() {
|
||||
if (_lotroServerInjectable == null) {
|
||||
final LotroServer lotroServer = new LotroServer(_deckDao, getGameHistoryServiceInjectable().getValue(), _library, getChatServerInjectable().getValue(), false);
|
||||
final LotroServer lotroServer = new LotroServer(_deckDao, _library, getChatServerInjectable().getValue(), getGameRecorderInjectable().getValue());
|
||||
lotroServer.startServer();
|
||||
_lotroServerInjectable = new Injectable<LotroServer>() {
|
||||
@Override
|
||||
@@ -236,7 +253,7 @@ public class ServerProvider implements InjectableProvider<Context, Type> {
|
||||
|
||||
private synchronized Injectable<CollectionsManager> getCollectionsManagerInjectable() {
|
||||
if (_collectionsManagerInjectable == null) {
|
||||
final CollectionsManager collectionsManager = new CollectionsManager(_playerDao, _collectionDao, getDeliveryServiceInjectable().getValue());
|
||||
final CollectionsManager collectionsManager = new CollectionsManager(_playerDao, _collectionDao, getDeliveryServiceInjectable().getValue(), _library);
|
||||
_collectionsManagerInjectable = new Injectable<CollectionsManager>() {
|
||||
@Override
|
||||
public CollectionsManager getValue() {
|
||||
|
||||
Reference in New Issue
Block a user