Merge branch 'newBranch' into 'master'

Improve Online Lobby (Mobile Port)

Closes #659, #658, #172, and #914

See merge request core-developers/forge!2738
This commit is contained in:
Michael Kamensky
2020-04-22 04:24:19 +00:00
13 changed files with 422 additions and 105 deletions

View File

@@ -71,7 +71,7 @@ public class PhaseHandler implements java.io.Serializable {
private int turn = 0;
private final transient Stack<ExtraTurn> extraTurns = new Stack<>();
private final transient Map<PhaseType, Stack<PhaseType>> extraPhases = Maps.newEnumMap(PhaseType.class);
private final transient Map<PhaseType, Deque<PhaseType>> DextraPhases = Maps.newEnumMap(PhaseType.class);
private int nUpkeepsThisTurn = 0;
private int nUpkeepsThisGame = 0;
@@ -151,12 +151,12 @@ public class PhaseHandler implements java.io.Serializable {
else {
// If the phase that's ending has a stack of additional phases
// Take the LIFO one and move to that instead of the normal one
if (extraPhases.containsKey(phase)) {
PhaseType nextPhase = extraPhases.get(phase).pop();
if (DextraPhases.containsKey(phase)) {
PhaseType nextPhase = DextraPhases.get(phase).removeFirst();
// If no more additional phases are available, remove it from the map
// and let the next add, reput the key
if (extraPhases.get(phase).isEmpty()) {
extraPhases.remove(phase);
if (DextraPhases.get(phase).isEmpty()) {
DextraPhases.remove(phase);
}
setPhase(nextPhase);
}
@@ -918,10 +918,10 @@ public class PhaseHandler implements java.io.Serializable {
public final void addExtraPhase(final PhaseType afterPhase, final PhaseType extraPhase) {
// 500.8. Some effects can add phases to a turn. They do this by adding the phases directly after the specified phase.
// If multiple extra phases are created after the same phase, the most recently created phase will occur first.
if (!extraPhases.containsKey(afterPhase)) {
extraPhases.put(afterPhase, new Stack<>());
if (!DextraPhases.containsKey(afterPhase)) {
DextraPhases.put(afterPhase, new ArrayDeque<>());
}
extraPhases.get(afterPhase).push(extraPhase);
DextraPhases.get(afterPhase).addFirst(extraPhase);
}
public final boolean isFirstCombat() {
@@ -1159,7 +1159,7 @@ public class PhaseHandler implements java.io.Serializable {
public final void endTurnByEffect() {
endCombat();
extraPhases.clear();
DextraPhases.clear();
setPhase(PhaseType.CLEANUP);
onPhaseBegin();
}

View File

@@ -135,8 +135,8 @@ public class RegisteredPlayer {
start.planes = planes;
}
if (appliedVariants.contains(GameType.Vanguard) || appliedVariants.contains(GameType.MomirBasic)
|| appliedVariants.contains(GameType.MoJhoSto)) {
start.setVanguardAvatars(vanguardAvatar.toFlatList());
|| appliedVariants.contains(GameType.MoJhoSto)) { //fix the crash, if somehow the avatar is null, get it directly from the deck
start.setVanguardAvatars(vanguardAvatar == null ? deck.get(DeckSection.Avatar).toFlatList():vanguardAvatar.toFlatList());
}
return start;
}

View File

@@ -38,9 +38,10 @@ import forge.util.Utils;
import java.io.File;
import java.io.FileFilter;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Deque;
import java.util.List;
import java.util.Stack;
public class Forge implements ApplicationListener {
public static final String CURRENT_VERSION = "1.6.33.001";
@@ -57,7 +58,7 @@ public class Forge implements ApplicationListener {
private static KeyInputAdapter keyInputAdapter;
private static boolean exited;
private static int continuousRenderingCount = 1; //initialize to 1 since continuous rendering is the default
private static final Stack<FScreen> screens = new Stack<>();
private static final Deque<FScreen> Dscreens = new ArrayDeque<>();
private static boolean textureFiltering = false;
private static boolean destroyThis = false;
public static String extrawide = "default";
@@ -259,13 +260,13 @@ public class Forge implements ApplicationListener {
}
public static boolean onHomeScreen() {
return screens.size() == 1;
return Dscreens.size() == 1;
}
public static void back() {
if(destroyThis && isLandscapeMode())
return;
if (screens.size() < 2) {
if (Dscreens.size() < 2) {
exit(false); //prompt to exit if attempting to go back from home screen
return;
}
@@ -273,8 +274,8 @@ public class Forge implements ApplicationListener {
@Override
public void run(Boolean result) {
if (result) {
screens.pop();
setCurrentScreen(screens.lastElement());
Dscreens.removeFirst();
setCurrentScreen(Dscreens.getFirst());
}
}
});
@@ -282,12 +283,12 @@ public class Forge implements ApplicationListener {
//set screen that will be gone to on pressing Back before going to current Back screen
public static void setBackScreen(final FScreen screen0, boolean replace) {
screens.remove(screen0); //remove screen from previous position in navigation history
int index = screens.size() - 1;
Dscreens.remove(screen0); //remove screen from previous position in navigation history
int index = Dscreens.size() - 1;
if (index > 0) {
screens.add(index, screen0);
Dscreens.addLast(screen0);
if (replace) { //remove previous back screen if replacing back screen
screens.remove(index - 1);
Dscreens.removeFirst();
}
}
}
@@ -349,7 +350,7 @@ public class Forge implements ApplicationListener {
if (currentScreen == screen0) { return; }
if (currentScreen == null) {
screens.push(screen0);
Dscreens.addFirst(screen0);
setCurrentScreen(screen0);
return;
}
@@ -358,11 +359,11 @@ public class Forge implements ApplicationListener {
@Override
public void run(Boolean result) {
if (result) {
if (replaceBackScreen && !screens.isEmpty()) {
screens.pop();
if (replaceBackScreen && !Dscreens.isEmpty()) {
Dscreens.removeFirst();
}
if (screens.peek() != screen0) { //prevent screen being its own back screen
screens.push(screen0);
if (Dscreens.peekFirst() != screen0) { //prevent screen being its own back screen
Dscreens.addFirst(screen0);
}
setCurrentScreen(screen0);
}
@@ -505,7 +506,7 @@ public class Forge implements ApplicationListener {
currentScreen.onClose(null);
currentScreen = null;
}
screens.clear();
Dscreens.clear();
graphics.dispose();
SoundSystem.instance.dispose();
try {

View File

@@ -19,7 +19,9 @@ import forge.assets.FSkinFont;
import forge.toolbox.FDisplayObject;
import forge.util.Utils;
import forge.util.TextBounds;
import java.util.Stack;
import java.util.ArrayDeque;
import java.util.Deque;
public class Graphics {
private static final int GL_BLEND = GL20.GL_BLEND;
@@ -27,13 +29,14 @@ public class Graphics {
private final SpriteBatch batch = new SpriteBatch();
private final ShapeRenderer shapeRenderer = new ShapeRenderer();
private final Stack<Matrix4> transforms = new Stack<>();
private final Deque<Matrix4> Dtransforms = new ArrayDeque<>();
private final Vector3 tmp = new Vector3();
private float regionHeight;
private Rectangle bounds;
private Rectangle visibleBounds;
private int failedClipCount;
private float alphaComposite = 1;
private int transformCount = 0;
public Graphics() {
}
@@ -70,7 +73,7 @@ public class Graphics {
batch.flush(); //must flush batch to prevent other things not rendering
Rectangle clip = new Rectangle(adjustX(x), adjustY(y, h), w, h);
if (!transforms.isEmpty()) { //transform position if needed
if (!Dtransforms.isEmpty()) { //transform position if needed
tmp.set(clip.x, clip.y, 0);
tmp.mul(batch.getTransformMatrix());
float minX = tmp.x;
@@ -121,7 +124,7 @@ public class Graphics {
final Rectangle parentBounds = bounds;
bounds = new Rectangle(parentBounds.x + displayObj.getLeft(), parentBounds.y + displayObj.getTop(), displayObj.getWidth(), displayObj.getHeight());
if (!transforms.isEmpty()) { //transform screen position if needed by applying transform matrix to rectangle
if (!Dtransforms.isEmpty()) { //transform screen position if needed by applying transform matrix to rectangle
updateScreenPosForRotation(displayObj);
}
else {
@@ -542,7 +545,7 @@ public class Graphics {
}
private void startShape(ShapeType shapeType) {
if (!transforms.isEmpty()) {
if (!Dtransforms.isEmpty()) {
//must copy matrix before starting shape if transformed
shapeRenderer.setTransformMatrix(batch.getTransformMatrix());
}
@@ -624,7 +627,8 @@ public class Graphics {
public void startRotateTransform(float originX, float originY, float rotation) {
batch.end();
transforms.add(0, new Matrix4(batch.getTransformMatrix().idt())); //startshape is using this above as reference
Dtransforms.addFirst(new Matrix4(batch.getTransformMatrix().idt())); //startshape is using this above as reference
transformCount++;
batch.getTransformMatrix().idt().translate(adjustX(originX), adjustY(originY, 0), 0).rotate(Vector3.Z, rotation).translate(-adjustX(originX), -adjustY(originY, 0), 0);
batch.begin();
}
@@ -632,7 +636,13 @@ public class Graphics {
public void endTransform() {
batch.end();
shapeRenderer.setTransformMatrix(batch.getTransformMatrix().idt());
transforms.pop();
Dtransforms.removeFirst();
transformCount--;
if(transformCount != Dtransforms.size()) {
System.err.println(String.format("Stack count: %d, transformCount: %d", Dtransforms.size(), transformCount));
transformCount = 0;
Dtransforms.clear();
}
batch.getTransformMatrix().idt(); //reset
shapeRenderer.getTransformMatrix().idt(); //reset
batch.begin();

View File

@@ -11,7 +11,7 @@ import forge.toolbox.FOptionPane;
import forge.util.Utils;
public abstract class LaunchScreen extends FScreen {
private static final float MAX_START_BUTTON_HEIGHT = 2 * Utils.AVG_FINGER_HEIGHT;
private static final float MAX_START_BUTTON_HEIGHT = 1.75f * Utils.AVG_FINGER_HEIGHT;
private float START_BUTTON_RATIO = 0.f;
private static final float PADDING = FOptionPane.PADDING;

View File

@@ -14,6 +14,8 @@ import forge.deck.FDeckChooser;
import forge.net.server.FServerManager;
import forge.util.Localizer;
import forge.util.MyRandom;
import forge.util.TextUtil;
import org.apache.commons.lang3.StringUtils;
import com.badlogic.gdx.Gdx;
@@ -281,7 +283,10 @@ public abstract class LobbyScreen extends LaunchScreen implements ILobbyView {
@Override
protected void startMatch() {
for (int i = 0; i < getNumPlayers(); i++) {
updateDeck(i);//TODO: Investigate why AI names cannot be overriden?
if(!lobby.isAllowNetworking()) //on networkplay, update deck will be handled differently
updateDeck(i);
//TODO: Investigate why AI names cannot be overriden?
updateName(i, getPlayerName(i));
}
FThreads.invokeInBackgroundThread(new Runnable() { //must call startGame in background thread in case there are alerts
@@ -326,6 +331,15 @@ public abstract class LobbyScreen extends LaunchScreen implements ILobbyView {
String[] avatarPrefs = prefs.getPref(FPref.UI_AVATARS).split(",");
for (int i = 0; i < avatarPrefs.length; i++) {
int avatarIndex = Integer.parseInt(avatarPrefs[i]);
if (avatarIndex < 0) {
int random = 0;
List<Integer> usedAvatars = getUsedAvatars();
do {
random = MyRandom.getRandom().nextInt(GuiBase.getInterface().getAvatarCount());
} while (usedAvatars.contains(random));
avatarIndex = random;
}
playerPanels.get(i).setAvatarIndex(avatarIndex);
}
@@ -333,6 +347,15 @@ public abstract class LobbyScreen extends LaunchScreen implements ILobbyView {
String[] sleevePrefs = prefs.getPref(FPref.UI_SLEEVES).split(",");
for (int i = 0; i < sleevePrefs.length; i++) {
int sleeveIndex = Integer.parseInt(sleevePrefs[i]);
if (sleeveIndex < 0) {
int random = 0;
List<Integer> usedSleeves = getUsedSleeves();
do {
random = MyRandom.getRandom().nextInt(GuiBase.getInterface().getSleevesCount());
} while (usedSleeves.contains(random));
sleeveIndex = random;
}
playerPanels.get(i).setSleeveIndex(sleeveIndex);
}
@@ -557,7 +580,7 @@ public abstract class LobbyScreen extends LaunchScreen implements ILobbyView {
}
if (i == 0) {
slot.setIsDevMode(prefs.getPrefBoolean(FPref.DEV_MODE_ENABLED));
slot.setIsDevMode(slot.isDevMode());
}
final LobbySlotType type = slot.getType();
@@ -582,8 +605,21 @@ public abstract class LobbyScreen extends LaunchScreen implements ILobbyView {
panel.setMayEdit(lobby.mayEdit(i));
panel.setMayControl(lobby.mayControl(i));
panel.setMayRemove(lobby.mayRemove(i));
if(allowNetworking) {
if(slot.getDeckName() != null)
panel.setDeckSelectorButtonText(slot.getDeckName());
if (fullUpdate && (type == LobbySlotType.LOCAL || type == LobbySlotType.AI)) {
if(slot.getPlanarDeckName()!= null)
panel.setPlanarDeckName(slot.getPlanarDeckName());
if(slot.getSchemeDeckName()!= null)
panel.setSchemeDeckName(slot.getSchemeDeckName());
if(slot.getAvatarVanguard()!= null)
panel.setVanguarAvatarName(slot.getAvatarVanguard());
}
if (fullUpdate && (type == LobbySlotType.LOCAL || type == LobbySlotType.AI) && !allowNetworking) {
updateDeck(i);
}
if (isNewPanel) {
@@ -606,35 +642,46 @@ public abstract class LobbyScreen extends LaunchScreen implements ILobbyView {
if (playerIndex >= getNumPlayers()) { return; }
PlayerPanel playerPanel = playerPanels.get(playerIndex);
String deckName = "";
Deck deck;
if (hasVariant(GameType.Commander)) {
deck = playerPanel.getCommanderDeck();
if (deck != null) {
playerPanel.getCommanderDeckChooser().saveState();
deckName = localizer.getMessage("lblCommanderDeck") + ": "
+ playerPanel.getCommanderDeckChooser().getDeck().getName();
}
}
else if (hasVariant(GameType.Oathbreaker)) {
deck = playerPanel.getOathbreakerDeck();
if (deck != null) {
playerPanel.getOathbreakerDeckChooser().saveState();
deckName = localizer.getMessage("lblOathbreakerDeck") + ": "
+ playerPanel.getOathbreakerDeckChooser().getDeck().getName();
}
}
else if (hasVariant(GameType.TinyLeaders)) {
deck = playerPanel.getTinyLeadersDeck();
if (deck != null) {
playerPanel.getTinyLeadersDeckChooser().saveState();
deckName = localizer.getMessage("lblTinyLeadersDeck") + ": "
+ playerPanel.getTinyLeadersDeckChooser().getDeck().getName();
}
}
else if (hasVariant(GameType.Brawl)) {
deck = playerPanel.getBrawlDeck();
if (deck != null) {
playerPanel.getBrawlDeckChooser().saveState();
deckName = localizer.getMessage("lblBrawlDeck") + ": "
+ playerPanel.getBrawlDeckChooser().getDeck().getName();
}
}else {
deck = playerPanel.getDeck();
if (deck != null) {
playerPanel.getDeckChooser().saveState();
deckName = playerPanel.getDeckChooser().getSelectedDeckType().toString() + ": "
+ playerPanel.getDeckChooser().getDeck().getName();
}
}
@@ -642,18 +689,31 @@ public abstract class LobbyScreen extends LaunchScreen implements ILobbyView {
return;
}
//playerPanel.setDeckSelectorButtonText(deckName);
Deck playerDeck = deck;
String VanguardAvatar = null;
String SchemeDeckName= null;
String PlanarDeckname= null;
if (hasVariant(GameType.Archenemy) || hasVariant(GameType.ArchenemyRumble)) {
if (playerDeck == deck) {
playerDeck = new Deck(deck); //create copy that can be modified
}
playerDeck.putSection(DeckSection.Schemes, playerPanel.getSchemeDeck().get(DeckSection.Schemes));
if (!playerPanel.getSchemeDeck().getName().isEmpty()) {
SchemeDeckName = localizer.getMessage("lblSchemeDeck") + ": " + playerPanel.getSchemeDeck().getName();
playerPanel.setSchemeDeckName(SchemeDeckName);
}
}
if (hasVariant(GameType.Planechase)) {
if (playerDeck == deck) {
playerDeck = new Deck(deck); //create copy that can be modified
}
playerDeck.putSection(DeckSection.Planes, playerPanel.getPlanarDeck().get(DeckSection.Planes));
if(!playerPanel.getPlanarDeck().getName().isEmpty()) {
PlanarDeckname = localizer.getMessage("lblPlanarDeck") + ": " + playerPanel.getPlanarDeck().getName();
playerPanel.setPlanarDeckName(PlanarDeckname);
}
}
if (hasVariant(GameType.Vanguard)) {
if (playerDeck == deck) {
@@ -662,11 +722,14 @@ public abstract class LobbyScreen extends LaunchScreen implements ILobbyView {
CardPool avatarPool = new CardPool();
avatarPool.add(playerPanel.getVanguardAvatar());
playerDeck.putSection(DeckSection.Avatar, avatarPool);
VanguardAvatar = localizer.getMessage("lblVanguard") + ": " + playerPanel.getVanguardAvatar().getName();
playerPanel.setVanguarAvatarName(VanguardAvatar);
}
decks[playerIndex] = playerDeck;
if (playerChangeListener != null) {
playerChangeListener.update(playerIndex, UpdateLobbyPlayerEvent.deckUpdate(playerDeck));
playerChangeListener.update(playerIndex, UpdateLobbyPlayerEvent.setDeckSchemePlaneVanguard(TextUtil.fastReplace(deckName," Generated Deck", ""), SchemeDeckName, PlanarDeckname, VanguardAvatar));
}
}
@@ -689,6 +752,11 @@ public abstract class LobbyScreen extends LaunchScreen implements ILobbyView {
}
void setReady(final int index, final boolean ready) {
if (lobby.isAllowNetworking()){
updateDeck(index);
fireReady(index, ready);
return;
}
if (ready) {
updateDeck(index);
if (decks[index] == null) {
@@ -697,7 +765,6 @@ public abstract class LobbyScreen extends LaunchScreen implements ILobbyView {
return;
}
}
firePlayerChangeListener(index);
}
void setDevMode(final int index) {
@@ -714,7 +781,27 @@ public abstract class LobbyScreen extends LaunchScreen implements ILobbyView {
playerChangeListener.update(index, getSlot(index));
}
}
void fireReady(final int index, boolean ready){
playerPanels.get(index).setIsReady(ready);
if (playerChangeListener != null) {
playerChangeListener.update(index, UpdateLobbyPlayerEvent.isReadyUpdate(ready));
}
}
void updatemyTeam(int index, int team) {
if (playerChangeListener != null) {
playerChangeListener.update(index, UpdateLobbyPlayerEvent.teamUpdate(team));
}
}
void updateMyDeck(int index) {
/* updateMyDeck is called via button handler when the user set their deck on network play*/
//safety check
if(playerPanels.size() < 2)
return;
updateDeck(index);
//fireReady(index, playerPanels.get(index).isReady());
}
public void removePlayer(final int index) {
lobby.removeSlot(index);
}

View File

@@ -112,9 +112,12 @@ public class PlayerPanel extends FContainer {
deckChooser = new FDeckChooser(GameType.Constructed, isAi, new FEventHandler() {
@Override
public void handleEvent(FEvent e) {
btnDeck.setEnabled(true);
btnDeck.setEnabled(mayEdit);
btnDeck.setText(deckChooser.getSelectedDeckType().toString() + ": " +
Lang.joinHomogenous(((DeckManager)e.getSource()).getSelectedItems(), DeckProxy.FN_GET_NAME));
if (allowNetworking && btnDeck.isEnabled() && humanAiSwitch.isToggled()) { //if its ready but changed the deck, update it
screen.updateMyDeck(index);
}
}
});
lstCommanderDecks = new FDeckChooser(GameType.Commander, isAi, new FEventHandler() {
@@ -123,6 +126,9 @@ public class PlayerPanel extends FContainer {
if( ((DeckManager)e.getSource()).getSelectedItem() != null) {
btnCommanderDeck.setText(localizer.getMessage("lblCommanderDeck") + ": " + ((DeckManager) e.getSource()).getSelectedItem().getName());
lstCommanderDecks.saveState();
if (allowNetworking && btnCommanderDeck.isEnabled() && humanAiSwitch.isToggled()) {
screen.updateMyDeck(index);
}
}else{
btnCommanderDeck.setText(localizer.getMessage("lblCommanderDeck"));
}
@@ -134,6 +140,9 @@ public class PlayerPanel extends FContainer {
if( ((DeckManager)e.getSource()).getSelectedItem() != null) {
btnOathbreakDeck.setText(localizer.getMessage("lblOathbreakerDeck") + ": " + ((DeckManager) e.getSource()).getSelectedItem().getName());
lstOathbreakerDecks.saveState();
if (allowNetworking && btnOathbreakDeck.isEnabled() && humanAiSwitch.isToggled()) {
screen.updateMyDeck(index);
}
}else{
btnOathbreakDeck.setText(localizer.getMessage("lblOathbreakerDeck"));
}
@@ -145,6 +154,9 @@ public class PlayerPanel extends FContainer {
if( ((DeckManager)e.getSource()).getSelectedItem() != null) {
btnTinyLeadersDeck.setText(localizer.getMessage("lblTinyLeadersDeck") + ": " + ((DeckManager) e.getSource()).getSelectedItem().getName());
lstTinyLeadersDecks.saveState();
if (allowNetworking && btnTinyLeadersDeck.isEnabled() && humanAiSwitch.isToggled()) {
screen.updateMyDeck(index);
}
}else{
btnTinyLeadersDeck.setText(localizer.getMessage("lblTinyLeadersDeck"));
}
@@ -156,6 +168,9 @@ public class PlayerPanel extends FContainer {
if( ((DeckManager)e.getSource()).getSelectedItem() != null) {
btnBrawlDeck.setText(localizer.getMessage("lblBrawlDeck") + ": " + ((DeckManager) e.getSource()).getSelectedItem().getName());
lstBrawlDecks.saveState();
if (allowNetworking && btnBrawlDeck.isEnabled() && humanAiSwitch.isToggled()) {
screen.updateMyDeck(index);
}
}else{
btnBrawlDeck.setText(localizer.getMessage("lblBrawlDeck"));
}
@@ -166,6 +181,9 @@ public class PlayerPanel extends FContainer {
public void handleEvent(FEvent e) {
if( ((DeckManager)e.getSource()).getSelectedItem() != null){
btnSchemeDeck.setText(localizer.getMessage("lblSchemeDeck") + ": " + ((DeckManager)e.getSource()).getSelectedItem().getName());
if (allowNetworking && btnSchemeDeck.isEnabled() && humanAiSwitch.isToggled()) {
screen.updateMyDeck(index);
}
}else{
btnSchemeDeck.setText(localizer.getMessage("lblSchemeDeck"));
}
@@ -176,6 +194,9 @@ public class PlayerPanel extends FContainer {
public void handleEvent(FEvent e) {
if( ((DeckManager)e.getSource()).getSelectedItem() != null){
btnPlanarDeck.setText(localizer.getMessage("lblPlanarDeck") + ": " + ((DeckManager)e.getSource()).getSelectedItem().getName());
if (allowNetworking && btnPlanarDeck.isEnabled() && humanAiSwitch.isToggled()) {
screen.updateMyDeck(index);
}
}else{
btnPlanarDeck.setText(localizer.getMessage("lblPlanarDeck"));
}
@@ -185,6 +206,9 @@ public class PlayerPanel extends FContainer {
@Override
public void handleEvent(FEvent e) {
btnVanguardAvatar.setText(localizer.getMessage("lblVanguard") + ": " + ((CardManager)e.getSource()).getSelectedItem().getName());
if (allowNetworking && btnVanguardAvatar.isEnabled() && humanAiSwitch.isToggled()) {
screen.updateMyDeck(index);
}
}
});
@@ -512,7 +536,32 @@ public class PlayerPanel extends FContainer {
};
public void setDeckSelectorButtonText(String text) {
btnDeck.setText(text);
if (btnDeck.isVisible())
btnDeck.setText(text);
if (btnCommanderDeck.isVisible())
btnCommanderDeck.setText(text);
if (btnOathbreakDeck.isVisible())
btnOathbreakDeck.setText(text);
if (btnTinyLeadersDeck.isVisible())
btnTinyLeadersDeck.setText(text);
if (btnBrawlDeck.isVisible())
btnBrawlDeck.setText(text);
}
public void setVanguarAvatarName(String text) {
btnVanguardAvatar.setText(text);
}
public void setSchemeDeckName(String text) {
btnSchemeDeck.setText(text);
}
public void setPlanarDeckName(String text) {
btnPlanarDeck.setText(text);
}
public void updateVariantControlsVisibility() {
@@ -525,6 +574,7 @@ public class PlayerPanel extends FContainer {
boolean isArchenemyApplied = false;
boolean archenemyVisiblity = false;
boolean isDeckBuildingAllowed = mayEdit;
boolean replacedbasicdeck = false;
for (GameType variant : screen.getLobby().getAppliedVariants()) {
switch (variant) {
@@ -540,18 +590,22 @@ public class PlayerPanel extends FContainer {
case Commander:
isCommanderApplied = true;
isDeckBuildingAllowed = false; //Commander deck replaces basic deck, so hide that
replacedbasicdeck = true;
break;
case Oathbreaker:
isOathbreakerApplied = true;
isDeckBuildingAllowed = false; //Oathbreaker deck replaces basic deck, so hide that
replacedbasicdeck = true;
break;
case TinyLeaders:
isTinyLeadersApplied = true;
isDeckBuildingAllowed = false; //Tiny Leaders deck replaces basic deck, so hide that
replacedbasicdeck = true;
break;
case Brawl:
isBrawlApplied = true;
isDeckBuildingAllowed = false; //Tiny Leaders deck replaces basic deck, so hide that
replacedbasicdeck = true;
break;
case Planechase:
isPlanechaseApplied = true;
@@ -562,24 +616,85 @@ public class PlayerPanel extends FContainer {
default:
if (variant.isAutoGenerated()) {
isDeckBuildingAllowed = false;
replacedbasicdeck = true;
}
break;
}
}
btnDeck.setVisible(isDeckBuildingAllowed);
btnCommanderDeck.setVisible(isCommanderApplied && mayEdit);
btnOathbreakDeck.setVisible(isOathbreakerApplied && mayEdit);
btnTinyLeadersDeck.setVisible(isTinyLeadersApplied && mayEdit);
btnBrawlDeck.setVisible(isBrawlApplied && mayEdit);
if(allowNetworking) {
if (replacedbasicdeck) {
btnDeck.setVisible(false);
} else {
btnDeck.setVisible(true);
btnDeck.setEnabled(mayEdit);
}
if (isCommanderApplied) {
btnCommanderDeck.setVisible(true);
btnCommanderDeck.setEnabled(mayEdit);
} else {
btnCommanderDeck.setVisible(false);
}
if (isOathbreakerApplied) {
btnOathbreakDeck.setVisible(true);
btnOathbreakDeck.setEnabled(mayEdit);
} else {
btnOathbreakDeck.setVisible(false);
}
if (isTinyLeadersApplied) {
btnTinyLeadersDeck.setVisible(true);
btnTinyLeadersDeck.setEnabled(mayEdit);
} else {
btnTinyLeadersDeck.setVisible(false);
}
if (isBrawlApplied) {
btnBrawlDeck.setVisible(true);
btnBrawlDeck.setEnabled(mayEdit);
} else {
btnBrawlDeck.setVisible(false);
}
if (archenemyVisiblity) {
btnSchemeDeck.setVisible(true);
btnSchemeDeck.setEnabled(mayEdit);
} else {
btnSchemeDeck.setVisible(false);
}
if (!isArchenemyApplied) {
cbTeam.setVisible(true);
cbTeam.setEnabled(mayEdit);
cbArchenemyTeam.setVisible(false);
} else {
cbTeam.setVisible(false);
cbArchenemyTeam.setVisible(true);
cbArchenemyTeam.setEnabled(mayEdit);
}
if (isPlanechaseApplied) {
btnPlanarDeck.setVisible(true);
btnPlanarDeck.setEnabled(mayEdit);
} else {
btnPlanarDeck.setVisible(false);
}
if (isVanguardApplied) {
btnVanguardAvatar.setVisible(true);
btnVanguardAvatar.setEnabled(mayEdit);
} else {
btnVanguardAvatar.setVisible(false);
}
} else {
btnDeck.setVisible(isDeckBuildingAllowed);
btnCommanderDeck.setVisible(isCommanderApplied && mayEdit);
btnOathbreakDeck.setVisible(isOathbreakerApplied && mayEdit);
btnTinyLeadersDeck.setVisible(isTinyLeadersApplied && mayEdit);
btnBrawlDeck.setVisible(isBrawlApplied && mayEdit);
btnSchemeDeck.setVisible(archenemyVisiblity && mayEdit);
btnSchemeDeck.setVisible(archenemyVisiblity && mayEdit);
cbTeam.setVisible(!isArchenemyApplied);
cbArchenemyTeam.setVisible(isArchenemyApplied);
cbTeam.setVisible(!isArchenemyApplied);
cbArchenemyTeam.setVisible(isArchenemyApplied);
btnPlanarDeck.setVisible(isPlanechaseApplied && mayEdit);
btnVanguardAvatar.setVisible(isVanguardApplied && mayEdit);
btnPlanarDeck.setVisible(isPlanechaseApplied && mayEdit);
btnVanguardAvatar.setVisible(isVanguardApplied && mayEdit);
}
}
public boolean isNetworkHost() {
@@ -626,6 +741,8 @@ public class PlayerPanel extends FContainer {
pp.toggleIsPlayerArchenemy();
}
}
} else {
screen.updatemyTeam(index, getTeam());
}
}
};
@@ -823,6 +940,16 @@ public class PlayerPanel extends FContainer {
if (devModeSwitch != null) {
devModeSwitch.setEnabled(mayEdit);
}
if(allowNetworking) {
btnDeck.setEnabled(mayEdit);
btnCommanderDeck.setEnabled(mayEdit);
btnOathbreakDeck.setEnabled(mayEdit);
btnTinyLeadersDeck.setEnabled(mayEdit);
btnBrawlDeck.setEnabled(mayEdit);
btnSchemeDeck.setEnabled(mayEdit);
btnPlanarDeck.setEnabled(mayEdit);
cbArchenemyTeam.setEnabled(mayEdit);
}
updateVariantControlsVisibility();
//if panel has height already, ensure height updated to account for button visibility changes

View File

@@ -146,6 +146,7 @@ public class MatchController extends AbstractGuiGame {
}
}
view = new MatchScreen(playerPanels);
view.resetFields();
if (noHumans) {
//add special object that pauses game if screen touched
@@ -215,6 +216,13 @@ public class MatchController extends AbstractGuiGame {
if (lbl != null) {
lbl.setActive(true);
}
if(GuiBase.isNetworkplay())
checkStack();
}
public void checkStack() {
view.getStack().checkEmptyStack();
}
@Override

View File

@@ -481,6 +481,20 @@ public class MatchScreen extends FScreen {
}
}
public void resetFields() {
for (VPlayerPanel playerPanel : getPlayerPanels().values()) {
for (CardAreaPanel p : playerPanel.getField().getCardPanels()){
p.resetForNewGame();
p.reset();
}
playerPanel.getZoneTab(ZoneType.Hand).getDisplayArea().clear();
playerPanel.getZoneTab(ZoneType.Library).getDisplayArea().clear();
playerPanel.getZoneTab(ZoneType.Graveyard).getDisplayArea().clear();
playerPanel.getZoneTab(ZoneType.Exile).getDisplayArea().clear();
}
}
public void updateZones(final Iterable<PlayerZoneUpdate> zonesToUpdate) {
for (final PlayerZoneUpdate update : zonesToUpdate) {
final PlayerView owner = update.getPlayer();
@@ -566,6 +580,9 @@ public class MatchScreen extends FScreen {
float y;
float w = getWidth();
Color color = Color.CYAN;
GameView game = MatchController.instance.getGameView();
CombatView combat = game.getCombat();
PlayerView currentPlayer = MatchController.instance.getCurrentPlayer();
//field separator lines
if (!Forge.isLandscapeMode()) {
@@ -592,8 +609,7 @@ public class MatchScreen extends FScreen {
//Draw Priority Human Multiplayer 2 player
float oldAlphaComposite = g.getfloatAlphaComposite();
//TODO: support up to 4 players
if ((getPlayerPanels().keySet().size() == 2) && (countHuman() == 2)){
for (VPlayerPanel playerPanel: playerPanelsList){
midField = playerPanel.getTop();
@@ -606,28 +622,22 @@ public class MatchScreen extends FScreen {
else
g.setAlphaComposite(0f);
if(MatchController.instance.getGameView()!= null) {
if(MatchController.instance.getGameView().getPhase()!=null)
{
if(MatchController.instance.getGameView().getPhase().isCombatPhase()){
if(playerPanel.getPlayer() == MatchController.instance.getCurrentPlayer())
g.setAlphaComposite(0.8f);
else
g.setAlphaComposite(0f);
}
}
if(MatchController.instance.getGameView().getCombat() != null) {
if(playerPanel.getPlayer() == MatchController.instance.getGameView().getPlayerTurn())
color = Color.RED;
if(game!= null) {
if(combat!=null) {
//hide rectangle
if(playerPanel.getPlayer() == currentPlayer)
g.setAlphaComposite(0.8f);
else
color = Color.LIME;
}
else
g.setAlphaComposite(0f);
//color rectangle
if(playerPanel.getPlayer() == game.getPlayerTurn())
color = Color.RED; //attacking player
else
color = Color.LIME; //defending player
} else {
color = Color.CYAN;
}
}
g.drawRect(4f, color, playerPanel.getField().getLeft(), adjustY, playerPanel.getField().getWidth(), adjustH);
g.setAlphaComposite(oldAlphaComposite);
}

View File

@@ -95,6 +95,15 @@ public class VStack extends FDropDown {
restorablePlayerZones = null;
}
public void checkEmptyStack() { //sort the bug in client when desynch happens
final FCollectionView<StackItemView> stack = MatchController.instance.getGameView().getStack();
if(stack!=null)
if(isVisible() && stack.isEmpty()) { //visible stack but empty already
hide();
getMenuTab().setText(Localizer.getInstance().getMessage("lblStack") + " (" + 0 + ")");
}
}
@Override
public void update() {
activeItem = null;

View File

@@ -239,17 +239,20 @@ public class FControlGameEventHandler extends IGameEventVisitor.Base<Void> {
@Override
public Void visit(final GameEventSpellAbilityCast event) {
needStackUpdate = true;
processEvent();
final Runnable notifyStackAddition = new Runnable() {
@Override
public void run() {
matchController.notifyStackAddition(event);
}
};
GuiBase.getInterface().invokeInEdtLater(notifyStackAddition);
needStackUpdate = true;
if(GuiBase.getInterface().isLibgdxPort()) {
return processEvent(); //mobile port don't have notify stack addition like the desktop
} else {
processEvent();
final Runnable notifyStackAddition = new Runnable() {
@Override
public void run() {
matchController.notifyStackAddition(event);
}
};
GuiBase.getInterface().invokeInEdtLater(notifyStackAddition);
}
return null;
}
@@ -262,16 +265,19 @@ public class FControlGameEventHandler extends IGameEventVisitor.Base<Void> {
@Override
public Void visit(final GameEventSpellRemovedFromStack event) {
needStackUpdate = true;
processEvent();
final Runnable notifyStackAddition = new Runnable() {
@Override
public void run() {
matchController.notifyStackRemoval(event);
}
};
GuiBase.getInterface().invokeInEdtLater(notifyStackAddition);
if(GuiBase.getInterface().isLibgdxPort()) {
return processEvent(); //mobile port don't have notify stack addition like the desktop
} else {
processEvent();
final Runnable notifyStackAddition = new Runnable() {
@Override
public void run() {
matchController.notifyStackRemoval(event);
}
};
GuiBase.getInterface().invokeInEdtLater(notifyStackAddition);
}
return null;
}
@@ -357,14 +363,12 @@ public class FControlGameEventHandler extends IGameEventVisitor.Base<Void> {
@Override
public Void visit(final GameEventCardChangeZone event) {
if(event.to.getZoneType() == ZoneType.Battlefield)
refreshFieldUpdate = true;
//pfps the change to the zones have already been performed with add and remove calls
// this is only for playing a sound
// updateZone(event.from);
//return updateZone(event.to);
return processEvent();
if(GuiBase.getInterface().isLibgdxPort()) {
updateZone(event.from);
return updateZone(event.to);
} else {
return processEvent();
}
}
@Override
@@ -399,10 +403,11 @@ public class FControlGameEventHandler extends IGameEventVisitor.Base<Void> {
@Override
public Void visit(final GameEventShuffle event) {
//pfps the change to the library has already been performed by a setCards call
// this is only for playing a sound
// return updateZone(event.player.getZone(ZoneType.Library));
return processEvent();
if (GuiBase.getInterface().isLibgdxPort()) {
return updateZone(event.player.getZone(ZoneType.Library));
} else {
return processEvent();
}
}
@Override

View File

@@ -22,6 +22,10 @@ public final class LobbySlot implements Serializable {
private boolean isDevMode;
private Deck deck;
private ImmutableSet<AIOption> aiOptions;
private String AvatarVanguard;
private String SchemeDeckName;
private String PlanarDeckName;
private String DeckName;
public LobbySlot(final LobbySlotType type, final String name, final int avatarIndex, final int sleeveIndex, final int team, final boolean isArchenemy, final boolean isReady, final Set<AIOption> aiOptions) {
this.type = type;
@@ -79,6 +83,22 @@ public final class LobbySlot implements Serializable {
} else if (oldDeck != null && data.getSection() != null && data.getCards() != null) {
oldDeck.putSection(data.getSection(), data.getCards());
}
if (data.getSchemeDeckName() != null) {
setSchemeDeckName(data.getSchemeDeckName());
changed = true;
}
if (data.getAvatarVanguard() != null) {
setAvatarVanguard(data.getAvatarVanguard());
changed = true;
}
if (data.getPlanarDeckName() != null) {
setPlanarDeckName(data.getPlanarDeckName());
changed = true;
}
if (data.getDeckName() != null) {
setDeckName(data.getDeckName());
changed = true;
}
return changed;
}
@@ -116,6 +136,16 @@ public final class LobbySlot implements Serializable {
this.team = team;
}
public String getSchemeDeckName() { return SchemeDeckName; }
public String getAvatarVanguard() { return AvatarVanguard; }
public String getPlanarDeckName() { return PlanarDeckName; }
public String getDeckName() { return DeckName; }
public void setSchemeDeckName(String schemeDeckName) { this.SchemeDeckName = schemeDeckName; }
public void setAvatarVanguard(String avatarVanguard) { this.AvatarVanguard = avatarVanguard; }
public void setPlanarDeckName(String planarDeckName) { this.PlanarDeckName = planarDeckName; }
public void setDeckName(String DeckName) { this.DeckName = DeckName; }
public boolean isArchenemy() {
return isArchenemy;
}

View File

@@ -25,6 +25,10 @@ public final class UpdateLobbyPlayerEvent implements NetEvent {
private DeckSection section = null;
private CardPool cards = null;
private Set<AIOption> aiOptions = null;
private String AvatarVanguard = null;
private String SchemeDeckName = null;
private String PlanarDeckName = null;
private String DeckName = null;
public static UpdateLobbyPlayerEvent create(final LobbySlotType type, final String name, final int avatarIndex, final int sleeveIndex, final int team, final boolean isArchenemy, final boolean isReady, final Set<AIOption> aiOptions) {
@@ -53,17 +57,39 @@ public final class UpdateLobbyPlayerEvent implements NetEvent {
public static UpdateLobbyPlayerEvent sleeveUpdate(final int index) {
return new UpdateLobbyPlayerEvent(index, false);
}
private UpdateLobbyPlayerEvent(int index, boolean avatar) {
public static UpdateLobbyPlayerEvent isReadyUpdate(final boolean isReady) {
return new UpdateLobbyPlayerEvent(isReady);
}
public static UpdateLobbyPlayerEvent teamUpdate(int team) {
return new UpdateLobbyPlayerEvent(team);
}
public static UpdateLobbyPlayerEvent setDeckSchemePlaneVanguard(final String DeckName, final String Scheme, final String Plane, final String Vanguard) {
return new UpdateLobbyPlayerEvent(DeckName, Scheme, Plane, Vanguard);
}
private UpdateLobbyPlayerEvent(final int index, final boolean avatar) {
if (avatar)
this.avatarIndex = index;
else
this.sleeveIndex = index;
}
private UpdateLobbyPlayerEvent(final int team) {
this.team = team;
}
private UpdateLobbyPlayerEvent(final String DeckName, final String Scheme, final String Plane, final String Vanguard) {
this.SchemeDeckName = Scheme;
this.PlanarDeckName = Plane;
this.AvatarVanguard = Vanguard;
this.DeckName = DeckName;
}
private UpdateLobbyPlayerEvent(final Deck deck) {
this.deck = deck;
}
private UpdateLobbyPlayerEvent(final boolean isReady) {
this.isReady = isReady;
}
private UpdateLobbyPlayerEvent(final DeckSection section, final CardPool cards) {
this.section = section;
this.cards = cards;
@@ -149,4 +175,8 @@ public final class UpdateLobbyPlayerEvent implements NetEvent {
public Set<AIOption> getAiOptions() {
return aiOptions == null ? null : Collections.unmodifiableSet(aiOptions);
}
public String getAvatarVanguard() { return AvatarVanguard; }
public String getSchemeDeckName() { return SchemeDeckName; }
public String getPlanarDeckName() { return PlanarDeckName; }
public String getDeckName() { return DeckName; }
}