mirror of
https://github.com/magefree/mage.git
synced 2025-12-30 07:22:03 -08:00
Improved network stability and other related fixes:
* server: fixed that a critical errors ignored in user commands threads (now it will be added to the logs); * network: fixed frozen user responses in some use cases; * network: fixed accidental and incorrect user responses (only latest response will be used now); * network: improved freeze logs, added problem method name and code's line number; * cheats: removed outdated deck and card load logic (only init.txt commands supports now); * cheats: fixed wrong priority after add card dialog (closes #11437); * cheats: improved stability and random errors on cheat executes (related to #11437); * docs: added details on network and thread logic, human feedback life cycle, etc (see HumanPlayer, ThreadExecutorImpl);
This commit is contained in:
parent
4ba3e1fec5
commit
53add71826
33 changed files with 476 additions and 273 deletions
|
|
@ -1,18 +1,21 @@
|
|||
|
||||
package mage.cards.decks;
|
||||
|
||||
import mage.util.CardUtil;
|
||||
import mage.util.Copyable;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author BetaSteward_at_googlemail.com
|
||||
* @author BetaSteward_at_googlemail.com, JayDi85
|
||||
*/
|
||||
public class DeckCardLists implements Serializable {
|
||||
public class DeckCardLists implements Serializable, Copyable<DeckCardLists> {
|
||||
|
||||
private String name;
|
||||
private String author;
|
||||
private String name = null;
|
||||
private String author = null;
|
||||
private List<DeckCardInfo> cards = new ArrayList<>();
|
||||
private List<DeckCardInfo> sideboard = new ArrayList<>();
|
||||
|
||||
|
|
@ -20,6 +23,23 @@ public class DeckCardLists implements Serializable {
|
|||
private DeckCardLayout cardLayout = null;
|
||||
private DeckCardLayout sideboardLayout = null;
|
||||
|
||||
public DeckCardLists() {
|
||||
}
|
||||
|
||||
protected DeckCardLists(final DeckCardLists deck) {
|
||||
this.name = deck.name;
|
||||
this.author = deck.author;
|
||||
this.cards = CardUtil.deepCopyObject(deck.cards);
|
||||
this.sideboard = CardUtil.deepCopyObject(deck.sideboard);
|
||||
this.cardLayout = CardUtil.deepCopyObject(deck.cardLayout);
|
||||
this.sideboardLayout = CardUtil.deepCopyObject(deck.sideboardLayout);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DeckCardLists copy() {
|
||||
return new DeckCardLists(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The layout of the cards
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -534,7 +534,6 @@ public interface Game extends MageItem, Serializable, Copyable<Game> {
|
|||
|
||||
// game cheats (for tests only)
|
||||
void cheat(UUID ownerId, Map<Zone, String> commands);
|
||||
|
||||
void cheat(UUID ownerId, List<Card> library, List<Card> hand, List<PermanentCard> battlefield, List<Card> graveyard, List<Card> command);
|
||||
|
||||
// controlling the behaviour of replacement effects while permanents entering the battlefield
|
||||
|
|
|
|||
|
|
@ -794,7 +794,7 @@ public abstract class GameImpl implements Game {
|
|||
if (!concedingPlayers.contains(playerId)) {
|
||||
logger.debug("Game over for player Id: " + playerId + " gameId " + getId());
|
||||
concedingPlayers.add(playerId);
|
||||
player.signalPlayerConcede();
|
||||
player.signalPlayerConcede(); // will be executed on next priority
|
||||
}
|
||||
} else {
|
||||
// no asynchronous action so check directly
|
||||
|
|
@ -3799,8 +3799,9 @@ public abstract class GameImpl implements Game {
|
|||
for (Player playerObject : getPlayers().values()) {
|
||||
if (playerObject.isHuman() && playerObject.canRespond()) {
|
||||
playerObject.resetStoredBookmark(this);
|
||||
playerObject.abort();
|
||||
playerObject.resetPlayerPassedActions();
|
||||
playerObject.abort();
|
||||
|
||||
}
|
||||
}
|
||||
fireUpdatePlayersEvent();
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ public class GameState implements Serializable, Copyable<GameState> {
|
|||
private Turn turn;
|
||||
private TurnMods turnMods; // one time turn modifications (turn, phase or step)
|
||||
private UUID activePlayerId; // playerId which turn it is
|
||||
private UUID priorityPlayerId; // player that has currently priority
|
||||
private UUID priorityPlayerId; // player that has currently priority (setup before any choose)
|
||||
private UUID playerByOrderId; // player that has currently priority
|
||||
private UUID monarchId; // player that is the monarch
|
||||
private UUID initiativeId; // player that has the initiative
|
||||
|
|
|
|||
|
|
@ -550,6 +550,8 @@ public interface Player extends MageItem, Copyable<Player> {
|
|||
|
||||
void signalPlayerConcede();
|
||||
|
||||
void signalPlayerCheat();
|
||||
|
||||
void skip();
|
||||
|
||||
// priority, undo, ...
|
||||
|
|
|
|||
|
|
@ -5088,7 +5088,10 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
|
||||
@Override
|
||||
public void signalPlayerConcede() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void signalPlayerCheat() {
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
package mage.util;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/**
|
||||
* Devs only: enable or disable debug features
|
||||
* <p>
|
||||
|
|
@ -28,4 +30,47 @@ public class DebugUtil {
|
|||
public static boolean GUI_GAME_DRAW_BATTLEFIELD_BORDER = false;
|
||||
public static boolean GUI_GAME_DRAW_HAND_AND_STACK_BORDER = false;
|
||||
public static boolean GUI_GAME_DIALOGS_DRAW_CARDS_AREA_BORDER = false;
|
||||
|
||||
public static String getMethodNameWithSource(final int depth) {
|
||||
return TraceHelper.getMethodNameWithSource(depth);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Debug: allows to find a caller's method name
|
||||
* <a href="https://stackoverflow.com/a/11726687/1276632">Original code</a>
|
||||
*/
|
||||
class TraceHelper {
|
||||
|
||||
private static Method m;
|
||||
|
||||
static {
|
||||
try {
|
||||
m = Throwable.class.getDeclaredMethod("getStackTraceElement", int.class);
|
||||
m.setAccessible(true);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static String getMethodName(final int depth) {
|
||||
try {
|
||||
StackTraceElement element = (StackTraceElement) m.invoke(new Throwable(), depth + 1);
|
||||
return element.getMethodName();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static String getMethodNameWithSource(final int depth) {
|
||||
try {
|
||||
StackTraceElement element = (StackTraceElement) m.invoke(new Throwable(), depth + 1);
|
||||
return String.format("%s - %s:%d", element.getMethodName(), element.getFileName(), element.getLineNumber());
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue