mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-16 18:58:00 +00:00
futher doctoring of InputQueues: ai input no longer locks UI,
priorityAutoPass is executed even without switching to EDT showMessage is executed for the current input of InputProxy, not the one passed as parameter FThreads.invokeInNewThread is wrapped into InputQueue.invokeGameAction that may run action is same thread if it is not EDT
This commit is contained in:
@@ -115,18 +115,6 @@ public class FThreads {
|
|||||||
getCachedPool().execute(toRun);
|
getCachedPool().execute(toRun);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void dumpStackTrace(PrintStream stream) {
|
|
||||||
StackTraceElement[] trace = Thread.currentThread().getStackTrace();
|
|
||||||
stream.printf("%s > %s called from %s%n", debugGetCurrThreadId(), trace[2].getClassName()+"."+trace[2].getMethodName(), trace[3].toString());
|
|
||||||
int i = 0;
|
|
||||||
for(StackTraceElement se : trace) {
|
|
||||||
if(i<2) i++;
|
|
||||||
else stream.println(se.toString());
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO: Write javadoc for this method.
|
* TODO: Write javadoc for this method.
|
||||||
* @return
|
* @return
|
||||||
@@ -150,7 +138,34 @@ public class FThreads {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static String debugGetCurrThreadId() {
|
public static String debugGetCurrThreadId() {
|
||||||
return isEDT() ? "EDT" : Long.toString(Thread.currentThread().getId());
|
return isEDT() ? "EDT" : Thread.currentThread().getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void dumpStackTrace(PrintStream stream) {
|
||||||
|
StackTraceElement[] trace = Thread.currentThread().getStackTrace();
|
||||||
|
stream.printf("%s > %s called from %s%n", debugGetCurrThreadId(), trace[2].getClassName()+"."+trace[2].getMethodName(), trace[3].toString());
|
||||||
|
int i = 0;
|
||||||
|
for(StackTraceElement se : trace) {
|
||||||
|
if(i<2) i++;
|
||||||
|
else stream.println(se.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String debugGetStackTraceItem(int depth, boolean shorter) {
|
||||||
|
StackTraceElement[] trace = Thread.currentThread().getStackTrace();
|
||||||
|
String lastItem = trace[depth].toString();
|
||||||
|
if( shorter ) {
|
||||||
|
int lastPeriod = lastItem.lastIndexOf('.');
|
||||||
|
lastPeriod = lastItem.lastIndexOf('.', lastPeriod-1);
|
||||||
|
lastPeriod = lastItem.lastIndexOf('.', lastPeriod-1);
|
||||||
|
lastItem = lastItem.substring(lastPeriod+1);
|
||||||
|
return String.format("%s > from %s", debugGetCurrThreadId(), lastItem);
|
||||||
|
}
|
||||||
|
return String.format("%s > %s called from %s", debugGetCurrThreadId(), trace[2].getClassName()+"."+trace[2].getMethodName(), lastItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String debugGetStackTraceItem(int depth) {
|
||||||
|
return debugGetStackTraceItem(depth, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ public class InputCleanup extends InputPassPriorityBase {
|
|||||||
if (!player.getZone(ZoneType.Hand).contains(card))
|
if (!player.getZone(ZoneType.Hand).contains(card))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
game.getInputQueue().LockAndInvokeGameAction(new Runnable() {
|
game.getInputQueue().lockAndInvokeGameAction(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
card.getController().discard(card, null);
|
card.getController().discard(card, null);
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ public class InputPassPriority extends InputPassPriorityBase {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
player.getGame().getInputQueue().LockAndInvokeGameAction(execAbility);
|
player.getGame().getInputQueue().lockAndInvokeGameAction(execAbility);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
flashIncorrectAction();
|
flashIncorrectAction();
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
package forge.control.input;
|
package forge.control.input;
|
||||||
|
|
||||||
import forge.FThreads;
|
|
||||||
import forge.game.phase.PhaseHandler;
|
import forge.game.phase.PhaseHandler;
|
||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
|
|
||||||
@@ -20,11 +19,7 @@ public abstract class InputPassPriorityBase extends InputBase {
|
|||||||
|
|
||||||
protected final void pass() { // no futher overloads possible
|
protected final void pass() { // no futher overloads possible
|
||||||
setFinished();
|
setFinished();
|
||||||
|
getQueue().invokeGameAction(passPriority);
|
||||||
if( FThreads.isEDT() )
|
|
||||||
FThreads.invokeInNewThread(passPriority);
|
|
||||||
else
|
|
||||||
passPriority.run();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected String getTurnPhasePriorityMessage() {
|
protected String getTurnPhasePriorityMessage() {
|
||||||
|
|||||||
@@ -197,7 +197,7 @@ public abstract class InputPayManaBase extends InputSyncronizedBase implements I
|
|||||||
onManaAbilityPlayed(chosen);
|
onManaAbilityPlayed(chosen);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
game.getInputQueue().LockAndInvokeGameAction(proc);
|
game.getInputQueue().lockAndInvokeGameAction(proc);
|
||||||
// EDT that removes lockUI from input stack will call our showMessage() method
|
// EDT that removes lockUI from input stack will call our showMessage() method
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -130,13 +130,17 @@ public class InputQueue extends MyObservable implements java.io.Serializable {
|
|||||||
*/
|
*/
|
||||||
public final Input getActualInput() {
|
public final Input getActualInput() {
|
||||||
GameAge age = game.getAge();
|
GameAge age = game.getAge();
|
||||||
if ( age != GameAge.Play && age != GameAge.Mulligan)
|
|
||||||
|
if ( game.isGameOver() )
|
||||||
return inputLock;
|
return inputLock;
|
||||||
|
|
||||||
Input topMost = inputStack.peek(); // incoming input to Control
|
Input topMost = inputStack.peek(); // incoming input to Control
|
||||||
if (topMost != null )
|
if (topMost != null )
|
||||||
return topMost;
|
return topMost;
|
||||||
|
|
||||||
|
if ( age != GameAge.Play )
|
||||||
|
return inputLock;
|
||||||
|
|
||||||
final PhaseHandler handler = game.getPhaseHandler();
|
final PhaseHandler handler = game.getPhaseHandler();
|
||||||
final PhaseType phase = handler.getPhase();
|
final PhaseType phase = handler.getPhase();
|
||||||
final Player playerTurn = handler.getPlayerTurn();
|
final Player playerTurn = handler.getPlayerTurn();
|
||||||
@@ -216,7 +220,7 @@ public class InputQueue extends MyObservable implements java.io.Serializable {
|
|||||||
input.awaitLatchRelease();
|
input.awaitLatchRelease();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void LockAndInvokeGameAction(final Runnable proc) {
|
public void lockAndInvokeGameAction(final Runnable proc) {
|
||||||
Runnable toRun = new Runnable() {
|
Runnable toRun = new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
@@ -225,10 +229,14 @@ public class InputQueue extends MyObservable implements java.io.Serializable {
|
|||||||
InputQueue.this.unlock();
|
InputQueue.this.unlock();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
invokeGameAction(toRun);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void invokeGameAction(final Runnable proc) {
|
||||||
if(FThreads.isEDT()) {
|
if(FThreads.isEDT()) {
|
||||||
FThreads.invokeInNewThread(toRun);
|
FThreads.invokeInNewThread(proc);
|
||||||
} else { // this branch is experimental
|
} else { // this branch is experimental
|
||||||
toRun.run();
|
proc.run();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ import forge.CardPredicates;
|
|||||||
import forge.CardUtil;
|
import forge.CardUtil;
|
||||||
import forge.Command;
|
import forge.Command;
|
||||||
import forge.CounterType;
|
import forge.CounterType;
|
||||||
|
import forge.FThreads;
|
||||||
import forge.GameEntity;
|
import forge.GameEntity;
|
||||||
import forge.card.CardType;
|
import forge.card.CardType;
|
||||||
import forge.card.TriggerReplacementBase;
|
import forge.card.TriggerReplacementBase;
|
||||||
@@ -854,6 +855,7 @@ public class GameAction {
|
|||||||
|
|
||||||
/** */
|
/** */
|
||||||
public final void checkStaticAbilities() {
|
public final void checkStaticAbilities() {
|
||||||
|
FThreads.assertExecutedByEdt(false);
|
||||||
|
|
||||||
if (game.isGameOver())
|
if (game.isGameOver())
|
||||||
return;
|
return;
|
||||||
@@ -904,6 +906,7 @@ public class GameAction {
|
|||||||
*/
|
*/
|
||||||
public final void checkStateEffects() {
|
public final void checkStateEffects() {
|
||||||
|
|
||||||
|
|
||||||
// sol(10/29) added for Phase updates, state effects shouldn't be
|
// sol(10/29) added for Phase updates, state effects shouldn't be
|
||||||
// checked during Spell Resolution (except when persist-returning
|
// checked during Spell Resolution (except when persist-returning
|
||||||
if (game.getStack().isResolving()) {
|
if (game.getStack().isResolving()) {
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import org.apache.commons.lang3.tuple.Pair;
|
|||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
|
|
||||||
import forge.Card;
|
import forge.Card;
|
||||||
import forge.FThreads;
|
|
||||||
import forge.Singletons;
|
import forge.Singletons;
|
||||||
import forge.control.FControl;
|
import forge.control.FControl;
|
||||||
import forge.error.BugReporter;
|
import forge.error.BugReporter;
|
||||||
@@ -130,7 +129,7 @@ public class MatchController {
|
|||||||
final Player firstPlayer = determineFirstTurnPlayer(getLastGameOutcome(), currentGame);
|
final Player firstPlayer = determineFirstTurnPlayer(getLastGameOutcome(), currentGame);
|
||||||
|
|
||||||
// This code was run from EDT.
|
// This code was run from EDT.
|
||||||
FThreads.invokeInNewThread( new Runnable() {
|
currentGame.getInputQueue().invokeGameAction(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
currentGame.getInputQueue().clearInput();
|
currentGame.getInputQueue().clearInput();
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ public class AiInputCommon extends InputPassPriorityBase implements AiInput {
|
|||||||
* the \"Detailed Error Trace\" to the Forge forum.");
|
* the \"Detailed Error Trace\" to the Forge forum.");
|
||||||
*/
|
*/
|
||||||
|
|
||||||
computer.getGame().getInputQueue().LockAndInvokeGameAction(aiActions);
|
computer.getGame().getInputQueue().invokeGameAction(aiActions);
|
||||||
|
|
||||||
} // getMessage();
|
} // getMessage();
|
||||||
|
|
||||||
|
|||||||
@@ -40,7 +40,6 @@ import forge.CardCharacteristicName;
|
|||||||
import forge.CardLists;
|
import forge.CardLists;
|
||||||
import forge.CardPredicates;
|
import forge.CardPredicates;
|
||||||
import forge.CounterType;
|
import forge.CounterType;
|
||||||
import forge.FThreads;
|
|
||||||
import forge.Singletons;
|
import forge.Singletons;
|
||||||
import forge.card.spellability.AbilityManaPart;
|
import forge.card.spellability.AbilityManaPart;
|
||||||
import forge.card.spellability.SpellAbility;
|
import forge.card.spellability.SpellAbility;
|
||||||
@@ -136,10 +135,10 @@ public final class GuiDisplayUtil {
|
|||||||
private static void setupGameState(final int humanLife, final int computerLife, final Map<ZoneType, String> humanCardTexts,
|
private static void setupGameState(final int humanLife, final int computerLife, final Map<ZoneType, String> humanCardTexts,
|
||||||
final Map<ZoneType, String> aiCardTexts, final String tChangePlayer, final String tChangePhase) {
|
final Map<ZoneType, String> aiCardTexts, final String tChangePlayer, final String tChangePhase) {
|
||||||
|
|
||||||
FThreads.invokeInNewThread(new Runnable() {
|
final GameState game = getGame();
|
||||||
|
game.getInputQueue().invokeGameAction(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
final GameState game = getGame();
|
|
||||||
final Player human = game.getPlayers().get(0);
|
final Player human = game.getPlayers().get(0);
|
||||||
final Player ai = game.getPlayers().get(1);
|
final Player ai = game.getPlayers().get(1);
|
||||||
|
|
||||||
@@ -411,7 +410,7 @@ public final class GuiDisplayUtil {
|
|||||||
return; // happens if cancelled
|
return; // happens if cancelled
|
||||||
}
|
}
|
||||||
|
|
||||||
FThreads.invokeInNewThread(new Runnable() {
|
game.getInputQueue().invokeGameAction(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
game.getAction().moveToHand(forgeCard); // this is really needed (for rollbacks at least)
|
game.getAction().moveToHand(forgeCard); // this is really needed (for rollbacks at least)
|
||||||
@@ -472,7 +471,7 @@ public final class GuiDisplayUtil {
|
|||||||
|
|
||||||
PlanarDice.roll(p, res);
|
PlanarDice.roll(p, res);
|
||||||
|
|
||||||
FThreads.invokeInNewThread(new Runnable() {
|
getGame().getInputQueue().invokeGameAction(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
p.getGame().getStack().chooseOrderOfSimultaneousStackEntryAll();
|
p.getGame().getStack().chooseOrderOfSimultaneousStackEntryAll();
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import java.util.concurrent.atomic.AtomicReference;
|
|||||||
import forge.Card;
|
import forge.Card;
|
||||||
import forge.FThreads;
|
import forge.FThreads;
|
||||||
import forge.control.input.Input;
|
import forge.control.input.Input;
|
||||||
|
import forge.control.input.InputAutoPassPriority;
|
||||||
import forge.game.GameState;
|
import forge.game.GameState;
|
||||||
import forge.game.phase.PhaseHandler;
|
import forge.game.phase.PhaseHandler;
|
||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
@@ -59,7 +60,7 @@ public class InputProxy implements Observer {
|
|||||||
final PhaseHandler ph = game.getPhaseHandler();
|
final PhaseHandler ph = game.getPhaseHandler();
|
||||||
|
|
||||||
if(INPUT_DEBUG)
|
if(INPUT_DEBUG)
|
||||||
System.out.printf("%s > InputProxy.update() =>%n", FThreads.debugGetCurrThreadId());
|
System.out.println(FThreads.debugGetStackTraceItem(6, true));
|
||||||
|
|
||||||
if ( game.getInputQueue().isEmpty() && ph.hasPhaseEffects()) {
|
if ( game.getInputQueue().isEmpty() && ph.hasPhaseEffects()) {
|
||||||
if(INPUT_DEBUG)
|
if(INPUT_DEBUG)
|
||||||
@@ -76,14 +77,15 @@ public class InputProxy implements Observer {
|
|||||||
Runnable showMessage = new Runnable() {
|
Runnable showMessage = new Runnable() {
|
||||||
@Override public void run() {
|
@Override public void run() {
|
||||||
if(INPUT_DEBUG)
|
if(INPUT_DEBUG)
|
||||||
System.out.printf("%s > showMessage @ %s during %s%n", FThreads.debugGetCurrThreadId(), nextInput.getClass().getSimpleName(), ph.debugPrintState());
|
System.out.printf("%s > showMessage @ %s/%s during %s%n%n", FThreads.debugGetCurrThreadId(), nextInput.getClass().getSimpleName(), getInput().getClass().getSimpleName(), ph.debugPrintState());
|
||||||
nextInput.showMessage(game.getInputQueue());
|
getInput().showMessage(game.getInputQueue());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
// if( nextInput instanceof AiInput )
|
|
||||||
// FThreads.invokeInNewThread(showMessage, true);
|
if( nextInput instanceof InputAutoPassPriority )
|
||||||
// else
|
nextInput.showMessage(game.getInputQueue());
|
||||||
FThreads.invokeInEdtLater(showMessage);
|
else
|
||||||
|
FThreads.invokeInEdtLater(showMessage);
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
|
|||||||
@@ -95,8 +95,7 @@ public enum CDock implements ICDoc {
|
|||||||
if( p == null ) return;
|
if( p == null ) return;
|
||||||
// if( c.isMindSlaved() ) return
|
// if( c.isMindSlaved() ) return
|
||||||
|
|
||||||
FThreads.invokeInNewThread(new Runnable() {
|
game.getInputQueue().invokeGameAction(new Runnable() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
p.concede();
|
p.concede();
|
||||||
|
|||||||
@@ -155,7 +155,7 @@ public class CField implements ICDoc {
|
|||||||
// should I check for who owns these cards? Are there any abilities to be played from opponent's graveyard?
|
// should I check for who owns these cards? Are there any abilities to be played from opponent's graveyard?
|
||||||
final SpellAbility ab = player.getController().getAbilityToPlay(game.getAbilitesOfCard(c, player));
|
final SpellAbility ab = player.getController().getAbilityToPlay(game.getAbilitesOfCard(c, player));
|
||||||
if ( null != ab) {
|
if ( null != ab) {
|
||||||
FThreads.invokeInNewThread(new Runnable(){ @Override public void run(){
|
game.getInputQueue().invokeGameAction(new Runnable(){ @Override public void run(){
|
||||||
HumanPlay.playSpellAbility(player, c, ab);
|
HumanPlay.playSpellAbility(player, c, ab);
|
||||||
}});
|
}});
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user