mirror of
https://github.com/magefree/mage.git
synced 2025-12-21 11:02:00 -08:00
Improved stability and other related fixes:
* server: added limit to max chat message (related to #11285); * gui: fixed possible error after auto-submit deck; * gui: fixed possible error after end game dialog; * refactor: other code improves;
This commit is contained in:
parent
81f97c3b0e
commit
d1f9e9cc90
15 changed files with 86 additions and 48 deletions
|
|
@ -5,6 +5,7 @@ import mage.client.SessionHandler;
|
||||||
import mage.client.cards.BigCard;
|
import mage.client.cards.BigCard;
|
||||||
import mage.client.dialog.PreferencesDialog;
|
import mage.client.dialog.PreferencesDialog;
|
||||||
import mage.client.util.GUISizeHelper;
|
import mage.client.util.GUISizeHelper;
|
||||||
|
import mage.constants.Constants;
|
||||||
import mage.view.ChatMessage.MessageColor;
|
import mage.view.ChatMessage.MessageColor;
|
||||||
import mage.view.ChatMessage.MessageType;
|
import mage.view.ChatMessage.MessageType;
|
||||||
import org.mage.card.arcane.ManaSymbols;
|
import org.mage.card.arcane.ManaSymbols;
|
||||||
|
|
@ -103,7 +104,6 @@ public class ChatPanelBasic extends javax.swing.JPanel {
|
||||||
jScrollPaneTxt.getViewport().setBackground(new Color(0, 0, 0, CHAT_ALPHA));
|
jScrollPaneTxt.getViewport().setBackground(new Color(0, 0, 0, CHAT_ALPHA));
|
||||||
jScrollPaneTxt.setViewportBorder(null);
|
jScrollPaneTxt.setViewportBorder(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void cleanUp() {
|
public void cleanUp() {
|
||||||
|
|
@ -398,6 +398,12 @@ public class ChatPanelBasic extends javax.swing.JPanel {
|
||||||
|
|
||||||
public void handleKeyTyped(java.awt.event.KeyEvent evt) {
|
public void handleKeyTyped(java.awt.event.KeyEvent evt) {
|
||||||
if (evt.getKeyChar() == KeyEvent.VK_ENTER) {
|
if (evt.getKeyChar() == KeyEvent.VK_ENTER) {
|
||||||
|
|
||||||
|
if (this.txtMessage.getText().length() > Constants.MAX_CHAT_MESSAGE_SIZE) {
|
||||||
|
JOptionPane.showMessageDialog(null, "Can't send too long message", "Chat", JOptionPane.WARNING_MESSAGE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (parentChatRef != null) {
|
if (parentChatRef != null) {
|
||||||
SessionHandler.sendChatMessage(parentChatRef.chatId, this.txtMessage.getText());
|
SessionHandler.sendChatMessage(parentChatRef.chatId, this.txtMessage.getText());
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -1497,13 +1497,13 @@ public class DeckEditorPanel extends javax.swing.JPanel {
|
||||||
timeToSubmit = 60;
|
timeToSubmit = 60;
|
||||||
this.btnSubmitTimer.setEnabled(false);
|
this.btnSubmitTimer.setEnabled(false);
|
||||||
|
|
||||||
ScheduledFuture scheduledFuture = scheduledExecutorService.schedule((Callable) () -> {
|
scheduledExecutorService.schedule(() -> {
|
||||||
if (updateDeckTask != null) {
|
if (updateDeckTask != null) {
|
||||||
updateDeckTask.cancel(true);
|
updateDeckTask.cancel(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SessionHandler.submitDeck(mode, tableId, deck.getDeckCardLists())) {
|
if (SessionHandler.submitDeck(mode, tableId, deck.getDeckCardLists())) {
|
||||||
removeDeckEditor();
|
SwingUtilities.invokeLater(this::removeDeckEditor);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}, 60, TimeUnit.SECONDS);
|
}, 60, TimeUnit.SECONDS);
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ import mage.constants.PlayerAction;
|
||||||
import mage.constants.TurnPhase;
|
import mage.constants.TurnPhase;
|
||||||
import org.apache.log4j.Logger;
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
import javax.swing.*;
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.event.ActionEvent;
|
import java.awt.event.ActionEvent;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
@ -40,6 +41,7 @@ public class FeedbackPanel extends javax.swing.JPanel {
|
||||||
private ChatPanelBasic connectedChatPanel;
|
private ChatPanelBasic connectedChatPanel;
|
||||||
private Map<String, Serializable> lastOptions = new HashMap<>();
|
private Map<String, Serializable> lastOptions = new HashMap<>();
|
||||||
|
|
||||||
|
private static final int AUTO_CLOSE_END_DIALOG_TIMEOUT_SECS = 8;
|
||||||
private static final ScheduledExecutorService WORKER = Executors.newSingleThreadScheduledExecutor();
|
private static final ScheduledExecutorService WORKER = Executors.newSingleThreadScheduledExecutor();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -153,6 +155,7 @@ public class FeedbackPanel extends javax.swing.JPanel {
|
||||||
*/
|
*/
|
||||||
private void endWithTimeout() {
|
private void endWithTimeout() {
|
||||||
Runnable task = () -> {
|
Runnable task = () -> {
|
||||||
|
SwingUtilities.invokeLater(() -> {
|
||||||
LOGGER.info("Ending game...");
|
LOGGER.info("Ending game...");
|
||||||
Component c = MageFrame.getGame(gameId);
|
Component c = MageFrame.getGame(gameId);
|
||||||
while (c != null && !(c instanceof GamePane)) {
|
while (c != null && !(c instanceof GamePane)) {
|
||||||
|
|
@ -161,8 +164,9 @@ public class FeedbackPanel extends javax.swing.JPanel {
|
||||||
if (c != null && c.isVisible()) { // check if GamePanel still visible
|
if (c != null && c.isVisible()) { // check if GamePanel still visible
|
||||||
FeedbackPanel.this.btnRight.doClick();
|
FeedbackPanel.this.btnRight.doClick();
|
||||||
}
|
}
|
||||||
|
});
|
||||||
};
|
};
|
||||||
WORKER.schedule(task, 8, TimeUnit.SECONDS);
|
WORKER.schedule(task, AUTO_CLOSE_END_DIALOG_TIMEOUT_SECS, TimeUnit.SECONDS);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateOptions(Map<String, Serializable> options) {
|
public void updateOptions(Map<String, Serializable> options) {
|
||||||
|
|
|
||||||
|
|
@ -87,12 +87,12 @@ public class MageActionCallback implements ActionCallback {
|
||||||
|
|
||||||
private Date enlargeredViewOpened;
|
private Date enlargeredViewOpened;
|
||||||
private volatile EnlargedWindowState enlargedWindowState = EnlargedWindowState.CLOSED;
|
private volatile EnlargedWindowState enlargedWindowState = EnlargedWindowState.CLOSED;
|
||||||
//private volatile boolean enlargedImageWindowOpen = false;
|
|
||||||
// shows the alternative card the normal card or the alternative card (copy source, other flip side, other transformed side)
|
// shows the alternative card the normal card or the alternative card (copy source, other flip side, other transformed side)
|
||||||
private volatile EnlargeMode enlargeMode;
|
private volatile EnlargeMode enlargeMode;
|
||||||
|
|
||||||
private static final ScheduledExecutorService timeoutExecutor = Executors.newScheduledThreadPool(1);
|
private static final ScheduledExecutorService hideEnlargedCardWorker = Executors.newScheduledThreadPool(1);
|
||||||
private ScheduledFuture<?> hideTimeout;
|
private ScheduledFuture<?> hideEnlagedCardTask;
|
||||||
|
private static final int HIDE_ENLARGED_CARD_TIMEOUT_MS = 700;
|
||||||
|
|
||||||
private MageCard prevCardPanel;
|
private MageCard prevCardPanel;
|
||||||
private boolean startedDragging;
|
private boolean startedDragging;
|
||||||
|
|
@ -472,7 +472,7 @@ public class MageActionCallback implements ActionCallback {
|
||||||
}
|
}
|
||||||
|
|
||||||
hideTooltipPopup();
|
hideTooltipPopup();
|
||||||
cancelTimeout();
|
cancelHidingEnlagedCard();
|
||||||
Component parentComponent = SwingUtilities.getRoot(cardPanel);
|
Component parentComponent = SwingUtilities.getRoot(cardPanel);
|
||||||
if (parentComponent == null) {
|
if (parentComponent == null) {
|
||||||
// virtual card (example: show card popup in non cards panel like PickChoiceDialog)
|
// virtual card (example: show card popup in non cards panel like PickChoiceDialog)
|
||||||
|
|
@ -514,7 +514,7 @@ public class MageActionCallback implements ActionCallback {
|
||||||
popupTextWindowOpen = true;
|
popupTextWindowOpen = true;
|
||||||
}
|
}
|
||||||
if (enlargedWindowState != EnlargedWindowState.CLOSED) {
|
if (enlargedWindowState != EnlargedWindowState.CLOSED) {
|
||||||
cancelTimeout();
|
cancelHidingEnlagedCard();
|
||||||
displayEnlargedCard(cardPanel.getOriginal(), data);
|
displayEnlargedCard(cardPanel.getOriginal(), data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -552,7 +552,7 @@ public class MageActionCallback implements ActionCallback {
|
||||||
|
|
||||||
public void hideAll(UUID gameId) {
|
public void hideAll(UUID gameId) {
|
||||||
hideTooltipPopup();
|
hideTooltipPopup();
|
||||||
startHideTimeout();
|
startHidingEnlagedCard();
|
||||||
this.popupTextWindowOpen = false;
|
this.popupTextWindowOpen = false;
|
||||||
if (gameId != null) {
|
if (gameId != null) {
|
||||||
ArrowBuilder.getBuilder().removeArrowsByType(gameId, ArrowBuilder.Type.TARGET);
|
ArrowBuilder.getBuilder().removeArrowsByType(gameId, ArrowBuilder.Type.TARGET);
|
||||||
|
|
@ -740,14 +740,16 @@ public class MageActionCallback implements ActionCallback {
|
||||||
return PreferencesDialog.getCachedValue(PreferencesDialog.KEY_CARD_RENDERING_ABILITY_TEXT_OVERLAY, "true").equals("true");
|
return PreferencesDialog.getCachedValue(PreferencesDialog.KEY_CARD_RENDERING_ABILITY_TEXT_OVERLAY, "true").equals("true");
|
||||||
}
|
}
|
||||||
|
|
||||||
private synchronized void startHideTimeout() {
|
private synchronized void startHidingEnlagedCard() {
|
||||||
cancelTimeout();
|
cancelHidingEnlagedCard();
|
||||||
hideTimeout = timeoutExecutor.schedule(this::hideEnlargedCard, 700, TimeUnit.MILLISECONDS);
|
hideEnlagedCardTask = hideEnlargedCardWorker.schedule(
|
||||||
|
() -> SwingUtilities.invokeLater(this::hideEnlargedCard), HIDE_ENLARGED_CARD_TIMEOUT_MS, TimeUnit.MILLISECONDS
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private synchronized void cancelTimeout() {
|
private synchronized void cancelHidingEnlagedCard() {
|
||||||
if (hideTimeout != null) {
|
if (hideEnlagedCardTask != null) {
|
||||||
hideTimeout.cancel(false);
|
hideEnlagedCardTask.cancel(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -647,7 +647,7 @@ public class DownloadPicturesService extends DefaultBoundedRangeModel implements
|
||||||
while (!executor.isTerminated()) {
|
while (!executor.isTerminated()) {
|
||||||
try {
|
try {
|
||||||
TimeUnit.SECONDS.sleep(1);
|
TimeUnit.SECONDS.sleep(1);
|
||||||
} catch (InterruptedException ie) {
|
} catch (InterruptedException ignore) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,8 @@ public final class Constants {
|
||||||
public static final int MAX_AVATAR_ID = 32;
|
public static final int MAX_AVATAR_ID = 32;
|
||||||
public static final int DEFAULT_AVATAR_ID = 10;
|
public static final int DEFAULT_AVATAR_ID = 10;
|
||||||
|
|
||||||
|
public static final int MAX_CHAT_MESSAGE_SIZE = 500; // ignore too big messages
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Time each player has during the game to play using his\her priority.
|
* Time each player has during the game to play using his\her priority.
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -45,16 +45,20 @@ public interface MageServer {
|
||||||
Object serverGetPromotionMessages(String sessionId) throws MageException;
|
Object serverGetPromotionMessages(String sessionId) throws MageException;
|
||||||
|
|
||||||
// sync cards send sets db
|
// sync cards send sets db
|
||||||
// TODO: outdated, no more client/server sync, can be removed?
|
@Deprecated // TODO: outdated, no more client/server sync, can be removed?
|
||||||
List<ExpansionInfo> syncGetMissingExpansionData(List<String> codes);
|
List<ExpansionInfo> syncGetMissingExpansionData(List<String> codes);
|
||||||
|
@Deprecated // TODO: outdated, no more client/server sync, can be removed?
|
||||||
List<CardInfo> syncGetMissingCardsData(List<String> classNames);
|
List<CardInfo> syncGetMissingCardsData(List<String> classNames);
|
||||||
|
|
||||||
ServerState getServerState() throws MageException; // TODO: need stable update process, so rename it after few releases
|
ServerState getServerState() throws MageException; // TODO: need stable update process, so rename it after few releases
|
||||||
|
|
||||||
|
// TODO: miss session
|
||||||
UUID serverGetMainRoomId() throws MageException;
|
UUID serverGetMainRoomId() throws MageException;
|
||||||
|
|
||||||
|
// TODO: miss session
|
||||||
List<RoomUsersView> roomGetUsers(UUID roomId) throws MageException;
|
List<RoomUsersView> roomGetUsers(UUID roomId) throws MageException;
|
||||||
|
|
||||||
|
// TODO: miss session
|
||||||
List<MatchView> roomGetFinishedMatches(UUID roomId) throws MageException;
|
List<MatchView> roomGetFinishedMatches(UUID roomId) throws MageException;
|
||||||
|
|
||||||
TableView roomCreateTable(String sessionId, UUID roomId, MatchOptions matchOptions) throws MageException;
|
TableView roomCreateTable(String sessionId, UUID roomId, MatchOptions matchOptions) throws MageException;
|
||||||
|
|
@ -81,22 +85,29 @@ public interface MageServer {
|
||||||
|
|
||||||
boolean tableIsOwner(String sessionId, UUID roomId, UUID tableId) throws MageException;
|
boolean tableIsOwner(String sessionId, UUID roomId, UUID tableId) throws MageException;
|
||||||
|
|
||||||
|
// TODO: miss session
|
||||||
TableView roomGetTableById(UUID roomId, UUID tableId) throws MageException;
|
TableView roomGetTableById(UUID roomId, UUID tableId) throws MageException;
|
||||||
|
|
||||||
|
// TODO: miss session
|
||||||
List<TableView> roomGetAllTables(UUID roomId) throws MageException;
|
List<TableView> roomGetAllTables(UUID roomId) throws MageException;
|
||||||
|
|
||||||
|
// TODO: miss session
|
||||||
void chatSendMessage(UUID chatId, String userName, String message) throws MageException;
|
void chatSendMessage(UUID chatId, String userName, String message) throws MageException;
|
||||||
|
|
||||||
void chatJoin(UUID chatId, String sessionId, String userName) throws MageException;
|
void chatJoin(UUID chatId, String sessionId, String userName) throws MageException;
|
||||||
|
|
||||||
void chatLeave(UUID chatId, String sessionId) throws MageException;
|
void chatLeave(UUID chatId, String sessionId) throws MageException;
|
||||||
|
|
||||||
|
// TODO: miss session
|
||||||
UUID chatFindByGame(UUID gameId) throws MageException;
|
UUID chatFindByGame(UUID gameId) throws MageException;
|
||||||
|
|
||||||
|
// TODO: miss session
|
||||||
UUID chatFindByTable(UUID tableId) throws MageException;
|
UUID chatFindByTable(UUID tableId) throws MageException;
|
||||||
|
|
||||||
|
// TODO: miss session
|
||||||
UUID chatFindByTournament(UUID tournamentId) throws MageException;
|
UUID chatFindByTournament(UUID tournamentId) throws MageException;
|
||||||
|
|
||||||
|
// TODO: miss session
|
||||||
UUID chatFindByRoom(UUID roomId) throws MageException;
|
UUID chatFindByRoom(UUID roomId) throws MageException;
|
||||||
|
|
||||||
boolean matchStart(String sessionId, UUID roomId, UUID tableId) throws MageException;
|
boolean matchStart(String sessionId, UUID roomId, UUID tableId) throws MageException;
|
||||||
|
|
@ -135,6 +146,7 @@ public interface MageServer {
|
||||||
|
|
||||||
void tournamentQuit(UUID tournamentId, String sessionId) throws MageException;
|
void tournamentQuit(UUID tournamentId, String sessionId) throws MageException;
|
||||||
|
|
||||||
|
// TODO: miss session
|
||||||
TournamentView tournamentFindById(UUID tournamentId) throws MageException;
|
TournamentView tournamentFindById(UUID tournamentId) throws MageException;
|
||||||
|
|
||||||
void draftJoin(UUID draftId, String sessionId) throws MageException;
|
void draftJoin(UUID draftId, String sessionId) throws MageException;
|
||||||
|
|
|
||||||
|
|
@ -261,6 +261,7 @@ public class Connection {
|
||||||
return userData;
|
return userData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated // TODO: server side cards do not supports now, so remove outdated code (db sync with server)
|
||||||
public boolean isForceDBComparison() {
|
public boolean isForceDBComparison() {
|
||||||
return forceDBComparison;
|
return forceDBComparison;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -424,12 +424,8 @@ public class ComputerPlayer6 extends ComputerPlayer /*implements Player*/ {
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
protected Integer addActionsTimed() {
|
protected Integer addActionsTimed() {
|
||||||
FutureTask<Integer> task = new FutureTask<>(new Callable<Integer>() {
|
// run new game simulation in parallel thread
|
||||||
@Override
|
FutureTask<Integer> task = new FutureTask<>(() -> addActions(root, maxDepth, Integer.MIN_VALUE, Integer.MAX_VALUE));
|
||||||
public Integer call() throws Exception {
|
|
||||||
return addActions(root, maxDepth, Integer.MIN_VALUE, Integer.MAX_VALUE);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
pool.execute(task);
|
pool.execute(task);
|
||||||
try {
|
try {
|
||||||
int maxSeconds = maxThink;
|
int maxSeconds = maxThink;
|
||||||
|
|
@ -437,18 +433,19 @@ public class ComputerPlayer6 extends ComputerPlayer /*implements Player*/ {
|
||||||
maxSeconds = 3600;
|
maxSeconds = 3600;
|
||||||
}
|
}
|
||||||
logger.debug("maxThink: " + maxSeconds + " seconds ");
|
logger.debug("maxThink: " + maxSeconds + " seconds ");
|
||||||
if (task.get(maxSeconds, TimeUnit.SECONDS) != null) {
|
Integer res = task.get(maxSeconds, TimeUnit.SECONDS);
|
||||||
return task.get(maxSeconds, TimeUnit.SECONDS);
|
if (res != null) {
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
} catch (TimeoutException e) {
|
} catch (TimeoutException e) {
|
||||||
logger.info("simulating - timed out");
|
logger.info("simulating - timed out");
|
||||||
task.cancel(true);
|
task.cancel(true);
|
||||||
} catch (ExecutionException e) {
|
} catch (ExecutionException e) {
|
||||||
// exception error in simulated game
|
// exception error in simulated game
|
||||||
e.printStackTrace();
|
|
||||||
task.cancel(true);
|
task.cancel(true);
|
||||||
// real games: must catch
|
// real games: must catch and log
|
||||||
// unit tests: must raise again for test fail
|
// unit tests: must raise again for test fail
|
||||||
|
logger.error("AI simulation game catch error: " + e.getCause(), e);
|
||||||
if (this.isTestsMode()) {
|
if (this.isTestsMode()) {
|
||||||
throw new IllegalStateException("One of the simulated games raise the error: " + e.getCause());
|
throw new IllegalStateException("One of the simulated games raise the error: " + e.getCause());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ import mage.cards.repository.CardInfo;
|
||||||
import mage.cards.repository.CardRepository;
|
import mage.cards.repository.CardRepository;
|
||||||
import mage.cards.repository.ExpansionInfo;
|
import mage.cards.repository.ExpansionInfo;
|
||||||
import mage.cards.repository.ExpansionRepository;
|
import mage.cards.repository.ExpansionRepository;
|
||||||
|
import mage.constants.Constants;
|
||||||
import mage.constants.ManaType;
|
import mage.constants.ManaType;
|
||||||
import mage.constants.PlayerAction;
|
import mage.constants.PlayerAction;
|
||||||
import mage.constants.TableState;
|
import mage.constants.TableState;
|
||||||
|
|
@ -488,7 +489,13 @@ public class MageServerImpl implements MageServer {
|
||||||
@Override
|
@Override
|
||||||
//FIXME: why no sessionId here???
|
//FIXME: why no sessionId here???
|
||||||
public void chatSendMessage(final UUID chatId, final String userName, final String message) throws MageException {
|
public void chatSendMessage(final UUID chatId, final String userName, final String message) throws MageException {
|
||||||
|
if (message.length() > Constants.MAX_CHAT_MESSAGE_SIZE) {
|
||||||
|
logger.error("Chat message too big: " + message.length() + ", from user " + userName);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
// TODO: check and replace all usage of callExecutor.execute() by execute("actionName")
|
||||||
callExecutor.execute(
|
callExecutor.execute(
|
||||||
() -> managerFactory.chatManager().broadcast(chatId, userName, HtmlEscape.escapeHtml4(message), MessageColor.BLUE, true, null, ChatMessage.MessageType.TALK, null)
|
() -> managerFactory.chatManager().broadcast(chatId, userName, HtmlEscape.escapeHtml4(message), MessageColor.BLUE, true, null, ChatMessage.MessageType.TALK, null)
|
||||||
);
|
);
|
||||||
|
|
@ -953,8 +960,14 @@ public class MageServerImpl implements MageServer {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
//TODO: check how often it is used
|
|
||||||
public ServerState getServerState() throws MageException {
|
public ServerState getServerState() throws MageException {
|
||||||
|
// called one time per login, must work without auth and with diff versions
|
||||||
|
try {
|
||||||
|
// some ddos protection
|
||||||
|
Thread.sleep(1000);
|
||||||
|
} catch (InterruptedException ignore) {
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return new ServerState(
|
return new ServerState(
|
||||||
GameFactory.instance.getGameTypes(),
|
GameFactory.instance.getGameTypes(),
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,6 @@ import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||||
public class TableManagerImpl implements TableManager {
|
public class TableManagerImpl implements TableManager {
|
||||||
protected final ScheduledExecutorService expireExecutor = Executors.newSingleThreadScheduledExecutor();
|
protected final ScheduledExecutorService expireExecutor = Executors.newSingleThreadScheduledExecutor();
|
||||||
|
|
||||||
// protected static ScheduledExecutorService expireExecutor = ThreadExecutorImpl.getInstance().getExpireExecutor();
|
|
||||||
private final ManagerFactory managerFactory;
|
private final ManagerFactory managerFactory;
|
||||||
private final Logger logger = Logger.getLogger(TableManagerImpl.class);
|
private final Logger logger = Logger.getLogger(TableManagerImpl.class);
|
||||||
private final DateFormat formatter = new SimpleDateFormat("HH:mm:ss");
|
private final DateFormat formatter = new SimpleDateFormat("HH:mm:ss");
|
||||||
|
|
|
||||||
|
|
@ -26,12 +26,15 @@ public class UserManagerImpl implements UserManager {
|
||||||
private static final int SERVER_TIMEOUTS_USER_DISCONNECT_FROM_SERVER_AFTER_SECS = 3 * 60; // removes from all games and chats too (can be seen in users list with disconnected status)
|
private static final int SERVER_TIMEOUTS_USER_DISCONNECT_FROM_SERVER_AFTER_SECS = 3 * 60; // removes from all games and chats too (can be seen in users list with disconnected status)
|
||||||
private static final int SERVER_TIMEOUTS_USER_REMOVE_FROM_SERVER_AFTER_SECS = 8 * 60; // removes from users list
|
private static final int SERVER_TIMEOUTS_USER_REMOVE_FROM_SERVER_AFTER_SECS = 8 * 60; // removes from users list
|
||||||
|
|
||||||
|
private static final int SERVER_TIMEOUTS_USER_EXPIRE_CHECK_SECS = 60;
|
||||||
|
private static final int SERVER_TIMEOUTS_USERS_LIST_UPDATE_SECS = 4; // server side updates (client use own timeouts to request users list)
|
||||||
|
|
||||||
private static final Logger logger = Logger.getLogger(UserManagerImpl.class);
|
private static final Logger logger = Logger.getLogger(UserManagerImpl.class);
|
||||||
|
|
||||||
protected final ScheduledExecutorService expireExecutor = Executors.newSingleThreadScheduledExecutor();
|
protected final ScheduledExecutorService expireExecutor = Executors.newSingleThreadScheduledExecutor();
|
||||||
protected final ScheduledExecutorService userListExecutor = Executors.newSingleThreadScheduledExecutor();
|
protected final ScheduledExecutorService userListExecutor = Executors.newSingleThreadScheduledExecutor();
|
||||||
|
|
||||||
private List<UserView> userInfoList = new ArrayList<>();
|
private List<UserView> userInfoList = new ArrayList<>(); // all users list for main room/chat
|
||||||
private final ManagerFactory managerFactory;
|
private final ManagerFactory managerFactory;
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -46,9 +49,8 @@ public class UserManagerImpl implements UserManager {
|
||||||
|
|
||||||
public void init() {
|
public void init() {
|
||||||
USER_EXECUTOR = managerFactory.threadExecutor().getCallExecutor();
|
USER_EXECUTOR = managerFactory.threadExecutor().getCallExecutor();
|
||||||
expireExecutor.scheduleAtFixedRate(this::checkExpired, 60, 60, TimeUnit.SECONDS);
|
expireExecutor.scheduleAtFixedRate(this::checkExpired, SERVER_TIMEOUTS_USER_EXPIRE_CHECK_SECS, SERVER_TIMEOUTS_USER_EXPIRE_CHECK_SECS, TimeUnit.SECONDS);
|
||||||
|
userListExecutor.scheduleAtFixedRate(this::updateUserInfoList, SERVER_TIMEOUTS_USERS_LIST_UPDATE_SECS, SERVER_TIMEOUTS_USERS_LIST_UPDATE_SECS, TimeUnit.SECONDS);
|
||||||
userListExecutor.scheduleAtFixedRate(this::updateUserInfoList, 4, 4, TimeUnit.SECONDS);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -254,7 +256,7 @@ public class UserManagerImpl implements UserManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method recreated the user list that will be send to all clients
|
* This method recreated the user list that will be sent to all clients
|
||||||
*/
|
*/
|
||||||
private void updateUserInfoList() {
|
private void updateUserInfoList() {
|
||||||
try {
|
try {
|
||||||
|
|
|
||||||
|
|
@ -335,7 +335,7 @@ public class GameController implements GameCallback {
|
||||||
gameFuture = gameExecutor.submit(worker);
|
gameFuture = gameExecutor.submit(worker);
|
||||||
try {
|
try {
|
||||||
Thread.sleep(1000);
|
Thread.sleep(1000);
|
||||||
} catch (InterruptedException ex) {
|
} catch (InterruptedException ignore) {
|
||||||
}
|
}
|
||||||
if (game.getState().getChoosingPlayerId() != null) {
|
if (game.getState().getChoosingPlayerId() != null) {
|
||||||
// start timer to force player to choose starting player otherwise loosing by being idle
|
// start timer to force player to choose starting player otherwise loosing by being idle
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@ public class GameSessionPlayer extends GameSessionWatcher {
|
||||||
public GameSessionPlayer(ManagerFactory managerFactory, Game game, UUID userId, UUID playerId) {
|
public GameSessionPlayer(ManagerFactory managerFactory, Game game, UUID userId, UUID playerId) {
|
||||||
super(managerFactory.userManager(), userId, game, true);
|
super(managerFactory.userManager(), userId, game, true);
|
||||||
this.userManager = managerFactory.userManager();
|
this.userManager = managerFactory.userManager();
|
||||||
callExecutor = managerFactory.threadExecutor().getCallExecutor();
|
this.callExecutor = managerFactory.threadExecutor().getCallExecutor();
|
||||||
this.playerId = playerId;
|
this.playerId = playerId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -45,11 +45,11 @@ public class GamesRoomImpl extends RoomImpl implements GamesRoom, Serializable {
|
||||||
UPDATE_EXECUTOR.scheduleAtFixedRate(() -> {
|
UPDATE_EXECUTOR.scheduleAtFixedRate(() -> {
|
||||||
try {
|
try {
|
||||||
update();
|
update();
|
||||||
} catch (Exception ex) {
|
} catch (Exception e) {
|
||||||
LOGGER.fatal("Games room update exception! " + ex.toString(), ex);
|
LOGGER.fatal("Games room update error: " + e.getMessage(), e);
|
||||||
}
|
}
|
||||||
|
|
||||||
}, 2, 2, TimeUnit.SECONDS);
|
}, 2, 2, TimeUnit.SECONDS); // TODO: is it ok for performance?
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue