mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-20 04:38:00 +00:00
Merge branch 'master' of git.cardforge.org:core-developers/forge into remove_some_build_warnings
# Conflicts: # forge-gui-mobile/src/forge/assets/FSkin.java
This commit is contained in:
@@ -13,6 +13,8 @@ public class FThreads {
|
||||
* @param mustBeEDT   boolean: true = exception if not EDT, false = exception if EDT
|
||||
*/
|
||||
public static void assertExecutedByEdt(final boolean mustBeEDT) {
|
||||
if (GuiBase.isNetworkplay())
|
||||
return; //don't check for networkplay
|
||||
if (isGuiThread() != mustBeEDT) {
|
||||
final StackTraceElement[] trace = Thread.currentThread().getStackTrace();
|
||||
final String methodName = trace[2].getClassName() + "." + trace[2].getMethodName();
|
||||
|
||||
@@ -4,6 +4,8 @@ import forge.interfaces.IGuiBase;
|
||||
|
||||
public class GuiBase {
|
||||
private static IGuiBase guiInterface;
|
||||
private static boolean propertyConfig = true;
|
||||
private static boolean networkplay = false;
|
||||
|
||||
public static IGuiBase getInterface() {
|
||||
return guiInterface;
|
||||
@@ -11,4 +13,16 @@ public class GuiBase {
|
||||
public static void setInterface(IGuiBase i0) {
|
||||
guiInterface = i0;
|
||||
}
|
||||
public static void enablePropertyConfig(boolean value) {
|
||||
propertyConfig = value;
|
||||
}
|
||||
public static boolean isNetworkplay() {
|
||||
return networkplay;
|
||||
}
|
||||
public static void setNetworkplay(boolean value) {
|
||||
networkplay = value;
|
||||
}
|
||||
public static boolean hasPropertyConfig() {
|
||||
return propertyConfig;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -322,6 +322,9 @@ public enum FSkinProp {
|
||||
IMG_ABILITY_HEXPROOF_UB (new int[] {166, 494, 80, 80}, PropType.ABILITY),
|
||||
//token icon
|
||||
IMG_ABILITY_TOKEN (new int[] {330, 494, 80, 80}, PropType.ABILITY),
|
||||
//border
|
||||
IMG_BORDER_BLACK (new int[] {2, 2, 672, 936}, PropType.BORDERS),
|
||||
IMG_BORDER_WHITE (new int[] {676, 2, 672, 936}, PropType.BORDERS),
|
||||
//Protection From
|
||||
IMG_ABILITY_PROTECT_ALL (new int[] {248, 84, 80, 80}, PropType.ABILITY),
|
||||
IMG_ABILITY_PROTECT_B (new int[] {330, 84, 80, 80}, PropType.ABILITY),
|
||||
@@ -374,6 +377,7 @@ public enum FSkinProp {
|
||||
OLD_FOIL,
|
||||
TROPHY,
|
||||
ABILITY,
|
||||
BORDERS,
|
||||
MANAICONS,
|
||||
PLANAR_CONQUEST,
|
||||
FAVICON
|
||||
|
||||
@@ -14,6 +14,7 @@ import forge.item.SealedProduct;
|
||||
import forge.model.FModel;
|
||||
import forge.properties.ForgeConstants;
|
||||
import forge.properties.ForgePreferences;
|
||||
import forge.util.CardTranslation;
|
||||
import forge.util.Lang;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
|
||||
@@ -1,91 +0,0 @@
|
||||
package forge.card;
|
||||
|
||||
import com.esotericsoftware.minlog.Log;
|
||||
import com.google.common.base.Charsets;
|
||||
import forge.properties.ForgeConstants;
|
||||
import forge.util.LineReader;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class CardTranslation {
|
||||
|
||||
private static Map <String, String> translatednames;
|
||||
private static Map <String, String> translatedtypes;
|
||||
private static Map <String, String> translatedoracles;
|
||||
private static String languageSelected;
|
||||
|
||||
private static void readTranslationFile(String language) {
|
||||
String filename = "cardnames-" + language + ".txt";
|
||||
|
||||
try (LineReader translationFile = new LineReader(new FileInputStream(ForgeConstants.LANG_DIR + filename), Charsets.UTF_8)) {
|
||||
for (String line : translationFile.readLines()) {
|
||||
String[] matches = line.split("\\|");
|
||||
if (matches.length >= 2) {
|
||||
translatednames.put(matches[0], matches[1]);
|
||||
}
|
||||
if (matches.length >= 3) {
|
||||
translatedtypes.put(matches[0], matches[2]);
|
||||
}
|
||||
if (matches.length >= 4) {
|
||||
translatedoracles.put(matches[0], matches[3].replace("\\n", "\n\n"));
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
Log.error("Error reading translation file: cardnames-" + language + ".txt");
|
||||
}
|
||||
}
|
||||
|
||||
public static String getTranslatedName(String name) {
|
||||
if (needsTranslation()) {
|
||||
String tname = translatednames.get(name);
|
||||
return tname == null ? name : tname;
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
public static String getTranslatedType(String name, String originaltype) {
|
||||
if (needsTranslation()) {
|
||||
String ttype = translatedtypes.get(name);
|
||||
return ttype == null ? originaltype : ttype;
|
||||
}
|
||||
|
||||
return originaltype;
|
||||
}
|
||||
|
||||
public static String getTranslatedOracle(String name) {
|
||||
if (needsTranslation()) {
|
||||
String toracle = translatedoracles.get(name);
|
||||
return toracle == null ? "" : toracle;
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
public static HashMap<String, String> getTranslationTexts(String cardname, String altcardname) {
|
||||
HashMap<String, String> translations = new HashMap<String, String>();
|
||||
translations.put("name", getTranslatedName(cardname));
|
||||
translations.put("oracle", getTranslatedOracle(cardname));
|
||||
translations.put("altname", getTranslatedName(altcardname));
|
||||
translations.put("altoracle", getTranslatedOracle(altcardname));
|
||||
return translations;
|
||||
}
|
||||
|
||||
private static boolean needsTranslation() {
|
||||
return !languageSelected.equals("en-US");
|
||||
}
|
||||
|
||||
public static void preloadTranslation(String language) {
|
||||
languageSelected = language;
|
||||
|
||||
if (needsTranslation()) {
|
||||
translatednames = new HashMap<>();
|
||||
translatedtypes = new HashMap<>();
|
||||
translatedoracles = new HashMap<>();
|
||||
readTranslationFile(languageSelected);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -38,7 +38,7 @@ public class FControlGameEventHandler extends IGameEventVisitor.Base<Void> {
|
||||
private final Set<PlayerView> manaPoolUpdate = new HashSet<>();
|
||||
private final PlayerZoneUpdates zonesUpdate = new PlayerZoneUpdates();
|
||||
|
||||
private boolean processEventsQueued, needPhaseUpdate, needCombatUpdate, needStackUpdate, needPlayerControlUpdate;
|
||||
private boolean processEventsQueued, needPhaseUpdate, needCombatUpdate, needStackUpdate, needPlayerControlUpdate, refreshFieldUpdate;
|
||||
private boolean gameOver, gameFinished;
|
||||
private PlayerView turnUpdate;
|
||||
|
||||
@@ -103,6 +103,10 @@ public class FControlGameEventHandler extends IGameEventVisitor.Base<Void> {
|
||||
zonesUpdate.clear();
|
||||
}
|
||||
}
|
||||
if (refreshFieldUpdate) {
|
||||
refreshFieldUpdate = false;
|
||||
matchController.refreshField();
|
||||
}
|
||||
if (gameOver) {
|
||||
gameOver = false;
|
||||
humanController.getInputQueue().onGameOver(true); // this will unlock any game threads waiting for inputs to complete
|
||||
@@ -277,6 +281,7 @@ public class FControlGameEventHandler extends IGameEventVisitor.Base<Void> {
|
||||
|
||||
@Override
|
||||
public Void visit(final GameEventCardTapped event) {
|
||||
refreshFieldUpdate = true; //update all players field when event un/tapped
|
||||
processCard(event.card, cardsUpdate);
|
||||
return processEvent();
|
||||
}
|
||||
@@ -332,6 +337,8 @@ 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);
|
||||
|
||||
@@ -20,6 +20,7 @@ public final class CardArchetypeLDAGenerator {
|
||||
public static boolean initialize(){
|
||||
List<String> formatStrings = new ArrayList<>();
|
||||
formatStrings.add(FModel.getFormats().getStandard().getName());
|
||||
formatStrings.add(FModel.getFormats().getPioneer().getName());
|
||||
formatStrings.add(FModel.getFormats().getModern().getName());
|
||||
formatStrings.add("Legacy");
|
||||
formatStrings.add("Vintage");
|
||||
|
||||
@@ -20,6 +20,7 @@ public enum DeckType {
|
||||
QUEST_OPPONENT_DECK("lblQuestOpponentDecks"),
|
||||
COLOR_DECK("lblRandomColorDecks"),
|
||||
STANDARD_CARDGEN_DECK("lblRandomStandardArchetypeDecks"),
|
||||
PIONEER_CARDGEN_DECK("lblRandomPioneerArchetypeDecks"),
|
||||
MODERN_CARDGEN_DECK("lblRandomModernArchetypeDecks"),
|
||||
LEGACY_CARDGEN_DECK("lblRandomLegacyArchetypeDecks"),
|
||||
VINTAGE_CARDGEN_DECK("lblRandomVintageArchetypeDecks"),
|
||||
@@ -41,6 +42,7 @@ public enum DeckType {
|
||||
DeckType.QUEST_OPPONENT_DECK,
|
||||
DeckType.COLOR_DECK,
|
||||
DeckType.STANDARD_CARDGEN_DECK,
|
||||
DeckType.PIONEER_CARDGEN_DECK,
|
||||
DeckType.MODERN_CARDGEN_DECK,
|
||||
DeckType.LEGACY_CARDGEN_DECK,
|
||||
DeckType.VINTAGE_CARDGEN_DECK,
|
||||
|
||||
@@ -104,6 +104,8 @@ public class RandomDeckGenerator extends DeckProxy implements Comparable<RandomD
|
||||
return DeckgenUtil.buildColorDeck(colors, null, isAi);
|
||||
case STANDARD_CARDGEN_DECK:
|
||||
return DeckgenUtil.buildLDACArchetypeDeck(FModel.getFormats().getStandard(),isAi);
|
||||
case PIONEER_CARDGEN_DECK:
|
||||
return DeckgenUtil.buildLDACArchetypeDeck(FModel.getFormats().getPioneer(),isAi);
|
||||
case MODERN_CARDGEN_DECK:
|
||||
return DeckgenUtil.buildLDACArchetypeDeck(FModel.getFormats().getModern(),isAi);
|
||||
case LEGACY_CARDGEN_DECK:
|
||||
|
||||
@@ -36,6 +36,9 @@ public class GauntletUtil {
|
||||
case STANDARD_CARDGEN_DECK:
|
||||
deck = DeckgenUtil.buildLDACArchetypeDeck(FModel.getFormats().getStandard(),true);
|
||||
break;
|
||||
case PIONEER_CARDGEN_DECK:
|
||||
deck = DeckgenUtil.buildLDACArchetypeDeck(FModel.getFormats().getPioneer(),true);
|
||||
break;
|
||||
case MODERN_CARDGEN_DECK:
|
||||
deck = DeckgenUtil.buildLDACArchetypeDeck(FModel.getFormats().getModern(),true);
|
||||
break;
|
||||
|
||||
@@ -46,6 +46,7 @@ public interface IGuiBase {
|
||||
boolean showBoxedProduct(String title, String message, List<PaperCard> list);
|
||||
PaperCard chooseCard(String title, String message, List<PaperCard> list);
|
||||
int getAvatarCount();
|
||||
int getSleevesCount();
|
||||
void copyToClipboard(String text);
|
||||
void browseToUrl(String url) throws IOException, URISyntaxException;
|
||||
IAudioClip createAudioClip(String filename);
|
||||
|
||||
@@ -53,6 +53,7 @@ public interface IGuiGame {
|
||||
void updateSingleCard(CardView card);
|
||||
void updateCards(Iterable<CardView> cards);
|
||||
void refreshCardDetails(Iterable<CardView> cards);
|
||||
void refreshField();
|
||||
void updateManaPool(Iterable<PlayerView> manaPoolUpdate);
|
||||
void updateLives(Iterable<PlayerView> livesUpdate);
|
||||
void setPanelSelection(CardView hostCard);
|
||||
@@ -160,6 +161,8 @@ public interface IGuiGame {
|
||||
void setSelectables(final Iterable<CardView> cards);
|
||||
void clearSelectables();
|
||||
boolean isSelecting();
|
||||
boolean isGamePaused();
|
||||
public void setgamePause(boolean pause);
|
||||
|
||||
void awaitNextInput();
|
||||
void cancelAwaitNextInput();
|
||||
|
||||
@@ -9,6 +9,7 @@ import java.util.Set;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
|
||||
import forge.GuiBase;
|
||||
import forge.util.Localizer;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
@@ -37,6 +38,7 @@ public abstract class AbstractGuiGame implements IGuiGame, IMayViewCards {
|
||||
private IGameController spectator = null;
|
||||
private final Map<PlayerView, IGameController> gameControllers = Maps.newHashMap();
|
||||
private final Map<PlayerView, IGameController> originalGameControllers = Maps.newHashMap();
|
||||
private boolean gamePause = false;
|
||||
|
||||
public final boolean hasLocalPlayers() {
|
||||
return !gameControllers.isEmpty();
|
||||
@@ -58,7 +60,16 @@ public abstract class AbstractGuiGame implements IGuiGame, IMayViewCards {
|
||||
public final void setCurrentPlayer(PlayerView player) {
|
||||
player = TrackableTypes.PlayerViewType.lookup(player); //ensure we use the correct player
|
||||
|
||||
if (!gameControllers.containsKey(player)) {
|
||||
if (hasLocalPlayers() && !isLocalPlayer(player)) { //add check if gameControllers is not empty
|
||||
if(GuiBase.getInterface().isLibgdxPort()){//spectator is registered as localplayer bug on ai vs ai (after .
|
||||
if (spectator != null){ //human vs ai game), then it loses "control" when you watch ai vs ai,
|
||||
currentPlayer = null; //again, and vice versa, This is to prevent throwing error, lose control,
|
||||
updateCurrentPlayer(null); //workaround fix on mayviewcards below is needed or it will bug the UI..
|
||||
gameControllers.clear();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
|
||||
@@ -158,13 +169,32 @@ public abstract class AbstractGuiGame implements IGuiGame, IMayViewCards {
|
||||
//not needed for base game implementation
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refreshField() {
|
||||
//not needed for base game implementation
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mayView(final CardView c) {
|
||||
if (!hasLocalPlayers()) {
|
||||
return true; //if not in game, card can be shown
|
||||
}
|
||||
if (getGameController().mayLookAtAllCards()) {
|
||||
return true;
|
||||
if(GuiBase.getInterface().isLibgdxPort()){
|
||||
if(spectator!=null) { //workaround fix!! this is needed on above code or it will
|
||||
gameControllers.remove(spectator); //bug the UI! remove spectator here since its must not be here...
|
||||
return true;
|
||||
}
|
||||
try{
|
||||
if (getGameController().mayLookAtAllCards()) { // when it bugged here, the game thinks the spectator (null)
|
||||
return true; // is the humancontroller here (maybe because there is an existing game thread???)
|
||||
}
|
||||
} catch (NullPointerException e){
|
||||
return true; // return true so it will work as normal
|
||||
}
|
||||
} else {
|
||||
if (getGameController().mayLookAtAllCards()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return c.canBeShownToAny(getLocalPlayers());
|
||||
}
|
||||
@@ -232,6 +262,8 @@ public abstract class AbstractGuiGame implements IGuiGame, IMayViewCards {
|
||||
public boolean isSelecting() {
|
||||
return !selectableCards.isEmpty();
|
||||
}
|
||||
public boolean isGamePaused() { return gamePause; }
|
||||
public void setgamePause(boolean pause) { gamePause = pause; }
|
||||
|
||||
/** Concede game, bring up WinLose UI. */
|
||||
public boolean concede() {
|
||||
@@ -266,6 +298,8 @@ public abstract class AbstractGuiGame implements IGuiGame, IMayViewCards {
|
||||
if (showConfirmDialog(Localizer.getInstance().getMessage("lblCloseGameSpectator"), Localizer.getInstance().getMessage("lblCloseGame"), Localizer.getInstance().getMessage("lblClose"), Localizer.getInstance().getMessage("lblCancel"))) {
|
||||
IGameController controller = spectator;
|
||||
spectator = null; //ensure we don't prompt again, including when calling nextGameDecision below
|
||||
if (!isGamePaused())
|
||||
controller.selectButtonOk(); //pause
|
||||
controller.nextGameDecision(NextGameDecision.QUIT);
|
||||
}
|
||||
return false; //let logic above handle closing current screen
|
||||
|
||||
@@ -158,7 +158,7 @@ public abstract class GameLobby implements IHasGameType {
|
||||
public void addSlot() {
|
||||
final int newIndex = getNumberOfSlots();
|
||||
final LobbySlotType type = allowNetworking ? LobbySlotType.OPEN : LobbySlotType.AI;
|
||||
addSlot(new LobbySlot(type, null, newIndex, newIndex, false, !allowNetworking, Collections.emptySet()));
|
||||
addSlot(new LobbySlot(type, null, newIndex, newIndex, newIndex, false, !allowNetworking, Collections.emptySet()));
|
||||
}
|
||||
protected final void addSlot(final LobbySlot slot) {
|
||||
if (slot == null) {
|
||||
@@ -198,6 +198,15 @@ public abstract class GameLobby implements IHasGameType {
|
||||
}
|
||||
return result;
|
||||
}
|
||||
protected final static int[] localSleeveIndices() {
|
||||
final String[] sSleeves = FModel.getPreferences().getPref(FPref.UI_SLEEVES).split(",");
|
||||
final int[] result = new int[sSleeves.length];
|
||||
for (int i = 0; i < sSleeves.length; i++) {
|
||||
final Integer val = Ints.tryParse(sSleeves[i]);
|
||||
result[i] = val == null ? -1 : val.intValue();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public void removeSlot(final int index) {
|
||||
if (index < 0 || index >= data.slots.size()) {
|
||||
@@ -415,6 +424,7 @@ public abstract class GameLobby implements IHasGameType {
|
||||
final IGuiGame gui = getGui(data.slots.indexOf(slot));
|
||||
final String name = slot.getName();
|
||||
final int avatar = slot.getAvatarIndex();
|
||||
final int sleeve = slot.getSleeveIndex();
|
||||
final boolean isArchenemy = slot.isArchenemy();
|
||||
final int team = GameType.Archenemy.equals(currentGameType) && !isArchenemy ? 1 : slot.getTeam();
|
||||
final Set<AIOption> aiOptions = slot.getAiOptions();
|
||||
@@ -422,7 +432,7 @@ public abstract class GameLobby implements IHasGameType {
|
||||
final boolean isAI = slot.getType() == LobbySlotType.AI;
|
||||
final LobbyPlayer lobbyPlayer;
|
||||
if (isAI) {
|
||||
lobbyPlayer = GamePlayerUtil.createAiPlayer(name, avatar, aiOptions);
|
||||
lobbyPlayer = GamePlayerUtil.createAiPlayer(name, avatar, sleeve, aiOptions);
|
||||
}
|
||||
else {
|
||||
boolean setNameNow = false;
|
||||
@@ -430,7 +440,7 @@ public abstract class GameLobby implements IHasGameType {
|
||||
setNameNow = true;
|
||||
hasNameBeenSet = true;
|
||||
}
|
||||
lobbyPlayer = GamePlayerUtil.getGuiPlayer(name, avatar, setNameNow);
|
||||
lobbyPlayer = GamePlayerUtil.getGuiPlayer(name, avatar, sleeve, setNameNow);
|
||||
}
|
||||
|
||||
Deck deck = slot.getDeck();
|
||||
|
||||
@@ -158,6 +158,7 @@ public class HostedMatch {
|
||||
|
||||
final FCollectionView<Player> players = game.getPlayers();
|
||||
final String[] avatarIndices = FModel.getPreferences().getPref(FPref.UI_AVATARS).split(",");
|
||||
final String[] sleeveIndices = FModel.getPreferences().getPref(FPref.UI_SLEEVES).split(",");
|
||||
final GameView gameView = getGameView();
|
||||
|
||||
humanCount = 0;
|
||||
@@ -175,6 +176,16 @@ public class HostedMatch {
|
||||
}
|
||||
}
|
||||
p.updateAvatar();
|
||||
//sleeve
|
||||
p.getLobbyPlayer().setSleeveIndex(rp.getPlayer().getSleeveIndex());
|
||||
if (p.getLobbyPlayer().getSleeveIndex() == -1) {
|
||||
if (iPlayer < sleeveIndices.length) {
|
||||
p.getLobbyPlayer().setSleeveIndex(Integer.parseInt(sleeveIndices[iPlayer]));
|
||||
} else {
|
||||
p.getLobbyPlayer().setSleeveIndex(0);
|
||||
}
|
||||
}
|
||||
p.updateSleeve();
|
||||
|
||||
if (p.getController() instanceof PlayerControllerHuman) {
|
||||
final PlayerControllerHuman humanController = (PlayerControllerHuman) p.getController();
|
||||
@@ -205,13 +216,7 @@ public class HostedMatch {
|
||||
final IGuiGame gui = GuiBase.getInterface().getNewGuiGame();
|
||||
gui.setGameView(null); //clear the view so when the game restarts again, it updates correctly
|
||||
gui.setGameView(gameView);
|
||||
|
||||
final PlayerControllerHuman humanController = new WatchLocalGame(game, new LobbyPlayerHuman("Spectator"), gui);
|
||||
game.subscribeToEvents(new FControlGameEventHandler(humanController));
|
||||
humanControllers.add(humanController);
|
||||
gui.setSpectator(humanController);
|
||||
|
||||
gui.openView(null);
|
||||
registerSpectator(gui, new WatchLocalGame(game, new LobbyPlayerHuman("Spectator"), gui));
|
||||
}
|
||||
|
||||
//prompt user for player one name if needed
|
||||
@@ -265,9 +270,12 @@ public class HostedMatch {
|
||||
|
||||
public void registerSpectator(final IGuiGame gui) {
|
||||
final PlayerControllerHuman humanController = new WatchLocalGame(game, null, gui);
|
||||
registerSpectator(gui, humanController);
|
||||
}
|
||||
|
||||
public void registerSpectator(final IGuiGame gui, final PlayerControllerHuman humanController) {
|
||||
gui.setSpectator(humanController);
|
||||
gui.openView(null);
|
||||
|
||||
game.subscribeToEvents(new FControlGameEventHandler(humanController));
|
||||
humanControllers.add(humanController);
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ public final class LobbySlot implements Serializable {
|
||||
private LobbySlotType type;
|
||||
private String name;
|
||||
private int avatarIndex;
|
||||
private int sleeveIndex;
|
||||
private int team;
|
||||
private boolean isArchenemy;
|
||||
private boolean isReady;
|
||||
@@ -22,10 +23,11 @@ public final class LobbySlot implements Serializable {
|
||||
private Deck deck;
|
||||
private ImmutableSet<AIOption> aiOptions;
|
||||
|
||||
public LobbySlot(final LobbySlotType type, final String name, final int avatarIndex, final int team, final boolean isArchenemy, final boolean isReady, final Set<AIOption> aiOptions) {
|
||||
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;
|
||||
this.name = name;
|
||||
this.avatarIndex = avatarIndex;
|
||||
this.sleeveIndex = sleeveIndex;
|
||||
this.team = team;
|
||||
this.isArchenemy = isArchenemy;
|
||||
this.isReady = isReady;
|
||||
@@ -47,6 +49,10 @@ public final class LobbySlot implements Serializable {
|
||||
setAvatarIndex(data.getAvatarIndex());
|
||||
changed = true;
|
||||
}
|
||||
if (data.getSleeveIndex() != -1) {
|
||||
setSleeveIndex(data.getSleeveIndex());
|
||||
changed = true;
|
||||
}
|
||||
if (data.getTeam() != -1) {
|
||||
setTeam(data.getTeam());
|
||||
changed = true;
|
||||
@@ -93,9 +99,15 @@ public final class LobbySlot implements Serializable {
|
||||
public int getAvatarIndex() {
|
||||
return avatarIndex;
|
||||
}
|
||||
public int getSleeveIndex() {
|
||||
return sleeveIndex;
|
||||
}
|
||||
public void setAvatarIndex(final int avatarIndex) {
|
||||
this.avatarIndex = avatarIndex;
|
||||
}
|
||||
public void setSleeveIndex(final int sleeveIndex) {
|
||||
this.sleeveIndex = sleeveIndex;
|
||||
}
|
||||
|
||||
public int getTeam() {
|
||||
return team;
|
||||
|
||||
@@ -13,11 +13,12 @@ public final class LocalLobby extends GameLobby {
|
||||
|
||||
final String humanName = localName();
|
||||
final int[] avatarIndices = localAvatarIndices();
|
||||
final int[] sleeveIndices = localSleeveIndices();
|
||||
|
||||
final LobbySlot slot0 = new LobbySlot(LobbySlotType.LOCAL, humanName, avatarIndices[0], 0, true, true, Collections.emptySet());
|
||||
final LobbySlot slot0 = new LobbySlot(LobbySlotType.LOCAL, humanName, avatarIndices[0], sleeveIndices[0],0, true, true, Collections.emptySet());
|
||||
addSlot(slot0);
|
||||
|
||||
final LobbySlot slot1 = new LobbySlot(LobbySlotType.AI, null, avatarIndices[1], 1, false, true, Collections.emptySet());
|
||||
final LobbySlot slot1 = new LobbySlot(LobbySlotType.AI, null, avatarIndices[1], sleeveIndices[1],1, false, true, Collections.emptySet());
|
||||
addSlot(slot1);
|
||||
}
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@ import forge.player.GamePlayerUtil;
|
||||
import forge.player.PlayerControllerHuman;
|
||||
import forge.properties.ForgePreferences.FPref;
|
||||
import forge.util.ITriggerEvent;
|
||||
import forge.util.Localizer;
|
||||
import forge.util.ThreadUtil;
|
||||
|
||||
/**
|
||||
@@ -55,11 +56,12 @@ public class InputPassPriority extends InputSyncronizedBase {
|
||||
public final void showMessage() {
|
||||
showMessage(getTurnPhasePriorityMessage(getController().getGame()));
|
||||
chosenSa = null;
|
||||
Localizer localizer = Localizer.getInstance();
|
||||
if (getController().canUndoLastAction()) { //allow undoing with cancel button if can undo last action
|
||||
getController().getGui().updateButtons(getOwner(), "OK", "Undo", true, true, true);
|
||||
getController().getGui().updateButtons(getOwner(), localizer.getMessage("lblOK"), localizer.getMessage("lblUndo"), true, true, true);
|
||||
}
|
||||
else { //otherwise allow ending turn with cancel button
|
||||
getController().getGui().updateButtons(getOwner(), "OK", "End Turn", true, true, true);
|
||||
getController().getGui().updateButtons(getOwner(), localizer.getMessage("lblOK"), localizer.getMessage("lblEndTurn"), true, true, true);
|
||||
}
|
||||
|
||||
getController().getGui().alertUser();
|
||||
@@ -106,11 +108,12 @@ public class InputPassPriority extends InputSyncronizedBase {
|
||||
ThreadUtil.invokeInGameThread(new Runnable() { //must invoke in game thread so dialog can be shown on mobile game
|
||||
@Override
|
||||
public void run() {
|
||||
String message = "You have mana floating in your mana pool that could be lost if you pass priority now.";
|
||||
Localizer localizer = Localizer.getInstance();
|
||||
String message = localizer.getMessage("lblYouHaveManaFloatingInYourManaPoolCouldBeLostIfPassPriority");
|
||||
if (FModel.getPreferences().getPrefBoolean(FPref.UI_MANABURN)) {
|
||||
message += " You will take mana burn damage equal to the amount of floating mana lost this way.";
|
||||
message += " " + localizer.getMessage("lblYouWillTakeManaBurnDamageEqualAmountFloatingManaLostThisWay");
|
||||
}
|
||||
if (getController().getGui().showConfirmDialog(message, "Mana Floating", "Ok", "Cancel")) {
|
||||
if (getController().getGui().showConfirmDialog(message, localizer.getMessage("lblManaFloating"), localizer.getMessage("lblOk"), localizer.getMessage("lblCancel"))) {
|
||||
runnable.run();
|
||||
}
|
||||
}
|
||||
@@ -161,12 +164,12 @@ public class InputPassPriority extends InputSyncronizedBase {
|
||||
}
|
||||
final SpellAbility sa = abilities.get(0);
|
||||
if (sa.isSpell()) {
|
||||
return "cast spell";
|
||||
return Localizer.getInstance().getMessage("lblCastSpell");
|
||||
}
|
||||
if (sa instanceof LandAbility) {
|
||||
return "play land";
|
||||
return Localizer.getInstance().getMessage("lblPlayLand");
|
||||
}
|
||||
return "activate ability";
|
||||
return Localizer.getInstance().getMessage("lblActivateAbility");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,13 +1,10 @@
|
||||
package forge.match.input;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Queue;
|
||||
import java.util.*;
|
||||
|
||||
import forge.GuiBase;
|
||||
import forge.game.GameActionUtil;
|
||||
import forge.game.ability.AbilityKey;
|
||||
import forge.game.spellability.SpellAbilityView;
|
||||
import forge.util.TextUtil;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
@@ -363,11 +360,11 @@ public abstract class InputPayMana extends InputSyncronizedBase {
|
||||
final Card source = am.getHostCard();
|
||||
final Player activator = am.getActivatingPlayer();
|
||||
final Game g = source.getGame();
|
||||
final HashMap<String, Object> repParams = new HashMap<>();
|
||||
repParams.put("Mana", m.getOrigProduced());
|
||||
repParams.put("Affected", source);
|
||||
repParams.put("Player", activator);
|
||||
repParams.put("AbilityMana", am);
|
||||
final Map<AbilityKey, Object> repParams = AbilityKey.newMap();
|
||||
repParams.put(AbilityKey.Mana, m.getOrigProduced());
|
||||
repParams.put(AbilityKey.Affected, source);
|
||||
repParams.put(AbilityKey.Player, activator);
|
||||
repParams.put(AbilityKey.AbilityMana, am);
|
||||
|
||||
for (final Player p : g.getPlayers()) {
|
||||
for (final Card crd : p.getAllCards()) {
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
package forge.match.input;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import forge.card.mana.ManaAtom;
|
||||
import forge.card.mana.ManaCostShard;
|
||||
import forge.game.card.Card;
|
||||
@@ -15,7 +11,7 @@ import forge.model.FModel;
|
||||
import forge.player.PlayerControllerHuman;
|
||||
import forge.properties.ForgePreferences;
|
||||
import forge.util.ITriggerEvent;
|
||||
import forge.util.Lang;
|
||||
import forge.util.Localizer;
|
||||
|
||||
public class InputPayManaOfCostPayment extends InputPayMana {
|
||||
public InputPayManaOfCostPayment(final PlayerControllerHuman controller, ManaCostBeingPaid cost, SpellAbility spellAbility, Player payer, ManaConversionMatrix matrix) {
|
||||
@@ -64,6 +60,7 @@ public class InputPayManaOfCostPayment extends InputPayMana {
|
||||
protected String getMessage() {
|
||||
final String displayMana = manaCost.toString(false, player.getManaPool());
|
||||
final StringBuilder msg = new StringBuilder();
|
||||
final Localizer localizer = Localizer.getInstance();
|
||||
|
||||
applyMatrix();
|
||||
|
||||
@@ -78,26 +75,22 @@ public class InputPayManaOfCostPayment extends InputPayMana {
|
||||
msg.append(saPaidFor.getHostCard()).append(" - ").append(saPaidFor.toString()).append("\n\n");
|
||||
}
|
||||
}
|
||||
msg.append("Pay Mana Cost: ").append(displayMana);
|
||||
msg.append(localizer.getMessage("lblPayManaCost")).append(" ").append(displayMana);
|
||||
if (this.phyLifeToLose > 0) {
|
||||
msg.append(" (");
|
||||
msg.append(this.phyLifeToLose);
|
||||
msg.append(" life paid for phyrexian mana)");
|
||||
msg.append(" ").append(String.format(localizer.getMessage("lblLifePaidForPhyrexianMana"), this.phyLifeToLose));
|
||||
}
|
||||
|
||||
boolean isLifeInsteadBlack = player.hasKeyword("PayLifeInsteadOf:B") && manaCost.hasAnyKind(ManaAtom.BLACK);
|
||||
|
||||
if (manaCost.containsPhyrexianMana() || isLifeInsteadBlack) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("Click on your life total to pay life for ");
|
||||
List<String> list = Lists.newArrayList();
|
||||
if (manaCost.containsPhyrexianMana()) {
|
||||
list.add("phyrexian mana");
|
||||
if (manaCost.containsPhyrexianMana() && !isLifeInsteadBlack) {
|
||||
sb.append(localizer.getMessage("lblClickOnYourLifeTotalToPayLifeForPhyrexianMana"));
|
||||
} else if (!manaCost.containsPhyrexianMana() && isLifeInsteadBlack) {
|
||||
sb.append(localizer.getMessage("lblClickOnYourLifeTotalToPayLifeForBlackMana"));
|
||||
} else if (manaCost.containsPhyrexianMana() && isLifeInsteadBlack) {
|
||||
sb.append(localizer.getMessage("lblClickOnYourLifeTotalToPayLifeForPhyrexianOrBlackMana"));
|
||||
}
|
||||
if (isLifeInsteadBlack) {
|
||||
list.add("black mana");
|
||||
}
|
||||
sb.append(Lang.joinHomogenous(list, null, "or")).append(".");
|
||||
msg.append("\n(").append(sb).append(")");
|
||||
}
|
||||
|
||||
|
||||
@@ -17,10 +17,6 @@
|
||||
*/
|
||||
package forge.match.input;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import forge.card.mana.ManaAtom;
|
||||
import forge.card.mana.ManaCost;
|
||||
import forge.card.mana.ManaCostShard;
|
||||
@@ -33,7 +29,7 @@ import forge.model.FModel;
|
||||
import forge.player.PlayerControllerHuman;
|
||||
import forge.properties.ForgePreferences;
|
||||
import forge.util.ITriggerEvent;
|
||||
import forge.util.Lang;
|
||||
import forge.util.Localizer;
|
||||
|
||||
//pays the cost of a card played from the player's hand
|
||||
//the card is removed from the players hand if the cost is paid
|
||||
@@ -136,29 +132,26 @@ public class InputPayManaSimple extends InputPayMana {
|
||||
@Override
|
||||
protected String getMessage() {
|
||||
final StringBuilder msg = new StringBuilder();
|
||||
final Localizer localizer = Localizer.getInstance();
|
||||
if (FModel.getPreferences().getPrefBoolean(ForgePreferences.FPref.UI_DETAILED_SPELLDESC_IN_PROMPT)) {
|
||||
msg.append(saPaidFor.getStackDescription().replace("(Targeting ERROR)", "")).append("\n\n");
|
||||
}
|
||||
msg.append("Pay Mana Cost: ").append(this.manaCost.toString(false, player.getManaPool()));
|
||||
msg.append(localizer.getMessage("lblPayManaCost")).append(" ").append(this.manaCost.toString(false, player.getManaPool()));
|
||||
if (this.phyLifeToLose > 0) {
|
||||
msg.append(" (");
|
||||
msg.append(this.phyLifeToLose);
|
||||
msg.append(" life paid for phyrexian mana)");
|
||||
msg.append(" ").append(String.format(localizer.getMessage("lblLifePaidForPhyrexianMana"), this.phyLifeToLose));
|
||||
}
|
||||
|
||||
boolean isLifeInsteadBlack = player.hasKeyword("PayLifeInsteadOf:B") && manaCost.hasAnyKind(ManaAtom.BLACK);
|
||||
|
||||
if (manaCost.containsPhyrexianMana() || isLifeInsteadBlack) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("Click on your life total to pay life for ");
|
||||
List<String> list = Lists.newArrayList();
|
||||
if (manaCost.containsPhyrexianMana()) {
|
||||
list.add("phyrexian mana");
|
||||
if (manaCost.containsPhyrexianMana() && !isLifeInsteadBlack) {
|
||||
sb.append(localizer.getMessage("lblClickOnYourLifeTotalToPayLifeForPhyrexianMana"));
|
||||
} else if (!manaCost.containsPhyrexianMana() && isLifeInsteadBlack) {
|
||||
sb.append(localizer.getMessage("lblClickOnYourLifeTotalToPayLifeForBlackMana"));
|
||||
} else if (manaCost.containsPhyrexianMana() && isLifeInsteadBlack) {
|
||||
sb.append(localizer.getMessage("lblClickOnYourLifeTotalToPayLifeForPhyrexianOrBlackMana"));
|
||||
}
|
||||
if (isLifeInsteadBlack) {
|
||||
list.add("black mana");
|
||||
}
|
||||
sb.append(Lang.joinHomogenous(list, null, "or")).append(".");
|
||||
msg.append("\n(").append(sb).append(")");
|
||||
}
|
||||
|
||||
|
||||
@@ -48,6 +48,7 @@ public class InputPlaybackControl extends InputSyncronizedBase {
|
||||
} else {
|
||||
getController().getGui().updateButtons(null, "Pause", isFast ? "1x Speed" : "10x Faster", true, true, true);
|
||||
}
|
||||
getController().getGui().setgamePause(isPaused);
|
||||
}
|
||||
|
||||
public void pause() {
|
||||
|
||||
@@ -24,7 +24,6 @@ import forge.CardStorageReader.ProgressObserver;
|
||||
import forge.achievement.*;
|
||||
import forge.ai.AiProfileUtil;
|
||||
import forge.card.CardPreferences;
|
||||
import forge.card.CardTranslation;
|
||||
import forge.card.CardType;
|
||||
import forge.deck.CardArchetypeLDAGenerator;
|
||||
import forge.deck.CardRelationMatrixGenerator;
|
||||
@@ -49,6 +48,7 @@ import forge.quest.QuestController;
|
||||
import forge.quest.QuestWorld;
|
||||
import forge.quest.data.QuestPreferences;
|
||||
import forge.tournament.TournamentData;
|
||||
import forge.util.CardTranslation;
|
||||
import forge.util.FileUtil;
|
||||
import forge.util.Localizer;
|
||||
import forge.util.storage.IStorage;
|
||||
@@ -147,7 +147,7 @@ public final class FModel {
|
||||
final CardStorageReader tokenReader = new CardStorageReader(ForgeConstants.TOKEN_DATA_DIR, progressBarBridge,
|
||||
FModel.getPreferences().getPrefBoolean(FPref.LOAD_CARD_SCRIPTS_LAZILY));
|
||||
magicDb = new StaticData(reader, tokenReader, ForgeConstants.EDITIONS_DIR, ForgeConstants.BLOCK_DATA_DIR);
|
||||
CardTranslation.preloadTranslation(preferences.getPref(FPref.UI_LANGUAGE));
|
||||
CardTranslation.preloadTranslation(preferences.getPref(FPref.UI_LANGUAGE), ForgeConstants.LANG_DIR);
|
||||
|
||||
//create profile dirs if they don't already exist
|
||||
for (final String dname : ForgeConstants.PROFILE_DIRS) {
|
||||
@@ -168,6 +168,7 @@ public final class FModel {
|
||||
new File(ForgeConstants.USER_FORMATS_DIR), preferences.getPrefBoolean(FPref.LOAD_HISTORIC_FORMATS)));
|
||||
|
||||
magicDb.setStandardPredicate(formats.getStandard().getFilterRules());
|
||||
magicDb.setPioneerPredicate(formats.getPioneer().getFilterRules());
|
||||
magicDb.setModernPredicate(formats.getModern().getFilterRules());
|
||||
magicDb.setCommanderPredicate(formats.get("Commander").getFilterRules());
|
||||
magicDb.setOathbreakerPredicate(formats.get("Oathbreaker").getFilterRules());
|
||||
|
||||
58
forge-gui/src/main/java/forge/net/CustomObjectDecoder.java
Normal file
58
forge-gui/src/main/java/forge/net/CustomObjectDecoder.java
Normal file
@@ -0,0 +1,58 @@
|
||||
package forge.net;
|
||||
|
||||
import forge.GuiBase;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.ByteBufInputStream;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
|
||||
import io.netty.handler.codec.serialization.ClassResolver;
|
||||
import org.mapdb.elsa.ElsaObjectInputStream;
|
||||
|
||||
import java.io.ObjectInputStream;
|
||||
|
||||
public class CustomObjectDecoder extends LengthFieldBasedFrameDecoder {
|
||||
private final ClassResolver classResolver;
|
||||
|
||||
public CustomObjectDecoder(ClassResolver classResolver) {
|
||||
this(1048576, classResolver);
|
||||
}
|
||||
|
||||
public CustomObjectDecoder(int maxObjectSize, ClassResolver classResolver) {
|
||||
super(maxObjectSize, 0, 4, 0, 4);
|
||||
this.classResolver = classResolver;
|
||||
}
|
||||
|
||||
protected Object decode(ChannelHandlerContext ctx, ByteBuf in) throws Exception {
|
||||
ByteBuf frame = (ByteBuf) super.decode(ctx, in);
|
||||
if (frame == null) {
|
||||
return null;
|
||||
} else {
|
||||
if (GuiBase.hasPropertyConfig()){
|
||||
ElsaObjectInputStream ois = new ElsaObjectInputStream(new ByteBufInputStream(frame, true));
|
||||
|
||||
Object var5;
|
||||
try {
|
||||
var5 = ois.readObject();
|
||||
} finally {
|
||||
ois.close();
|
||||
}
|
||||
|
||||
return var5;
|
||||
}
|
||||
else {
|
||||
ObjectInputStream ois = new ObjectInputStream(new ByteBufInputStream(frame, true));
|
||||
|
||||
Object var5;
|
||||
try {
|
||||
var5 = ois.readObject();
|
||||
} finally {
|
||||
ois.close();
|
||||
}
|
||||
|
||||
return var5;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static int maxObjectsize = 10000000; //10megabyte???
|
||||
}
|
||||
56
forge-gui/src/main/java/forge/net/CustomObjectEncoder.java
Normal file
56
forge-gui/src/main/java/forge/net/CustomObjectEncoder.java
Normal file
@@ -0,0 +1,56 @@
|
||||
package forge.net;
|
||||
|
||||
import forge.GuiBase;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.ByteBufOutputStream;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.handler.codec.MessageToByteEncoder;
|
||||
import org.mapdb.elsa.ElsaObjectOutputStream;
|
||||
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.Serializable;
|
||||
|
||||
public class CustomObjectEncoder extends MessageToByteEncoder<Serializable> {
|
||||
private static final byte[] LENGTH_PLACEHOLDER = new byte[4];
|
||||
|
||||
public CustomObjectEncoder() {
|
||||
}
|
||||
|
||||
protected void encode(ChannelHandlerContext ctx, Serializable msg, ByteBuf out) throws Exception {
|
||||
int startIdx = out.writerIndex();
|
||||
ByteBufOutputStream bout = new ByteBufOutputStream(out);
|
||||
|
||||
if (GuiBase.hasPropertyConfig()){
|
||||
ElsaObjectOutputStream oout = null;
|
||||
try {
|
||||
bout.write(LENGTH_PLACEHOLDER);
|
||||
oout = new ElsaObjectOutputStream(bout);
|
||||
oout.writeObject(msg);
|
||||
oout.flush();
|
||||
} finally {
|
||||
if (oout != null) {
|
||||
oout.close();
|
||||
} else {
|
||||
bout.close();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ObjectOutputStream oout = null;
|
||||
try {
|
||||
bout.write(LENGTH_PLACEHOLDER);
|
||||
oout = new ObjectOutputStream(bout);
|
||||
oout.writeObject(msg);
|
||||
oout.flush();
|
||||
} finally {
|
||||
if (oout != null) {
|
||||
oout.close();
|
||||
} else {
|
||||
bout.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int endIdx = out.writerIndex();
|
||||
out.setInt(startIdx, endIdx - startIdx - 4);
|
||||
}
|
||||
}
|
||||
@@ -14,11 +14,12 @@ public final class OfflineLobby extends GameLobby {
|
||||
|
||||
final String humanName = localName();
|
||||
final int[] avatarIndices = localAvatarIndices();
|
||||
final int[] sleeveIndices = localSleeveIndices();
|
||||
|
||||
final LobbySlot slot0 = new LobbySlot(LobbySlotType.LOCAL, humanName, avatarIndices[0], 0, true, false, Collections.emptySet());
|
||||
final LobbySlot slot0 = new LobbySlot(LobbySlotType.LOCAL, humanName, avatarIndices[0], sleeveIndices[0], 0, true, false, Collections.emptySet());
|
||||
addSlot(slot0);
|
||||
|
||||
final LobbySlot slot1 = new LobbySlot(LobbySlotType.OPEN, null, -1, -1, false, false, Collections.emptySet());
|
||||
final LobbySlot slot1 = new LobbySlot(LobbySlotType.OPEN, null, -1, -1,-1, false, false, Collections.emptySet());
|
||||
addSlot(slot1);
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ import java.util.Map;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
|
||||
import forge.GuiBase;
|
||||
import forge.assets.FSkinProp;
|
||||
import forge.deck.CardPool;
|
||||
import forge.game.GameEntityView;
|
||||
@@ -65,11 +66,14 @@ public enum ProtocolMethod {
|
||||
confirm (Mode.SERVER, Boolean.TYPE, CardView.class, String.class, Boolean.TYPE, List/*String*/.class),
|
||||
getChoices (Mode.SERVER, List.class, String.class, Integer.TYPE, Integer.TYPE, List.class, Object.class, Function.class),
|
||||
order (Mode.SERVER, List.class, String.class, String.class, Integer.TYPE, Integer.TYPE, List.class, List.class, CardView.class, Boolean.TYPE),
|
||||
sideboard (Mode.SERVER, List.class, CardPool.class, CardPool.class),
|
||||
sideboard (Mode.SERVER, List.class, CardPool.class, CardPool.class, String.class),
|
||||
chooseSingleEntityForEffect(Mode.SERVER, GameEntityView.class, String.class, List.class, DelayedReveal.class, Boolean.TYPE),
|
||||
chooseEntitiesForEffect(Mode.SERVER, GameEntityView.class, String.class, List.class, Integer.TYPE, Integer.TYPE, DelayedReveal.class),
|
||||
manipulateCardList (Mode.SERVER, List.class, String.class, Iterable.class, Iterable.class, Boolean.TYPE, Boolean.TYPE, Boolean.TYPE),
|
||||
setCard (Mode.SERVER, Void.TYPE, CardView.class),
|
||||
setSelectables (Mode.SERVER, Void.TYPE, Iterable/*CardView*/.class),
|
||||
clearSelectables (Mode.SERVER),
|
||||
refreshField (Mode.SERVER),
|
||||
// TODO case "setPlayerAvatar":
|
||||
openZones (Mode.SERVER, Boolean.TYPE, Collection/*ZoneType*/.class, Map/*PlayerView,Object*/.class),
|
||||
restoreOldZones (Mode.SERVER, Void.TYPE, Map/*PlayerView,Object*/.class),
|
||||
@@ -155,11 +159,22 @@ public enum ProtocolMethod {
|
||||
}
|
||||
|
||||
public void checkArgs(final Object[] args) {
|
||||
if (GuiBase.hasPropertyConfig())
|
||||
return; //uses custom serializer for Android 8+..
|
||||
for (int iArg = 0; iArg < args.length; iArg++) {
|
||||
final Object arg = args[iArg];
|
||||
final Class<?> type = this.args[iArg];
|
||||
if (!ReflectionUtil.isInstance(arg, type)) {
|
||||
throw new InternalError(String.format("Protocol method %s: illegal argument (%d) of type %s, %s expected", name(), iArg, arg.getClass().getName(), type.getName()));
|
||||
Object arg = null;
|
||||
Class<?> type = null;
|
||||
try {
|
||||
arg = args[iArg];
|
||||
if (this.args.length > iArg)
|
||||
type = this.args[iArg];
|
||||
}
|
||||
catch (ArrayIndexOutOfBoundsException ex){ ex.printStackTrace(); }
|
||||
catch(ConcurrentModificationException ex) { ex.printStackTrace(); }
|
||||
if (arg != null)
|
||||
if (type != null)
|
||||
if (!ReflectionUtil.isInstance(arg, type)) {
|
||||
throw new InternalError(String.format("Protocol method %s: illegal argument (%d) of type %s, %s expected", name(), iArg, arg.getClass().getName(), type.getName()));
|
||||
}
|
||||
if (arg != null) {
|
||||
// attempt to Serialize each argument, this will throw an exception if it can't.
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package forge.net.client;
|
||||
|
||||
import forge.net.CustomObjectDecoder;
|
||||
import forge.net.CustomObjectEncoder;
|
||||
import io.netty.bootstrap.Bootstrap;
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.channel.ChannelFuture;
|
||||
@@ -12,8 +14,6 @@ import io.netty.channel.nio.NioEventLoopGroup;
|
||||
import io.netty.channel.socket.SocketChannel;
|
||||
import io.netty.channel.socket.nio.NioSocketChannel;
|
||||
import io.netty.handler.codec.serialization.ClassResolvers;
|
||||
import io.netty.handler.codec.serialization.ObjectDecoder;
|
||||
import io.netty.handler.codec.serialization.ObjectEncoder;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
@@ -58,8 +58,8 @@ public class FGameClient implements IToServer {
|
||||
public void initChannel(final SocketChannel ch) throws Exception {
|
||||
final ChannelPipeline pipeline = ch.pipeline();
|
||||
pipeline.addLast(
|
||||
new ObjectEncoder(),
|
||||
new ObjectDecoder(ClassResolvers.cacheDisabled(null)),
|
||||
new CustomObjectEncoder(),
|
||||
new CustomObjectDecoder(CustomObjectDecoder.maxObjectsize, ClassResolvers.cacheDisabled(null)),
|
||||
new MessageHandler(),
|
||||
new LobbyUpdateHandler(),
|
||||
new GameClientHandler(FGameClient.this));
|
||||
|
||||
@@ -198,7 +198,8 @@ final class GameClientHandler extends GameProtocolHandler<IGuiGame> {
|
||||
);
|
||||
LobbyPlayer lobbyPlayer = new LobbyPlayerHuman(
|
||||
playerSlot.getName(),
|
||||
playerSlot.getAvatarIndex()
|
||||
playerSlot.getAvatarIndex(),
|
||||
playerSlot.getSleeveIndex()
|
||||
);
|
||||
player.setPlayer(lobbyPlayer);
|
||||
player.setTeamNumber(playerSlot.getTeam());
|
||||
@@ -287,7 +288,7 @@ final class GameClientHandler extends GameProtocolHandler<IGuiGame> {
|
||||
@Override
|
||||
public void channelActive(final ChannelHandlerContext ctx) {
|
||||
// Don't use send() here, as this.channel is not yet set!
|
||||
ctx.channel().writeAndFlush(new LoginEvent(FModel.getPreferences().getPref(FPref.PLAYER_NAME), Integer.parseInt(FModel.getPreferences().getPref(FPref.UI_AVATARS).split(",")[0])));
|
||||
ctx.channel().writeAndFlush(new LoginEvent(FModel.getPreferences().getPref(FPref.PLAYER_NAME), Integer.parseInt(FModel.getPreferences().getPref(FPref.UI_AVATARS).split(",")[0]), Integer.parseInt(FModel.getPreferences().getPref(FPref.UI_SLEEVES).split(",")[0])));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -6,10 +6,11 @@ public class LoginEvent implements NetEvent {
|
||||
private static final long serialVersionUID = -8865183377417377938L;
|
||||
|
||||
private final String username;
|
||||
private final int avatarIndex;
|
||||
public LoginEvent(final String username, final int avatarIndex) {
|
||||
private final int avatarIndex, sleeveIndex;
|
||||
public LoginEvent(final String username, final int avatarIndex, final int sleeveIndex) {
|
||||
this.username = username;
|
||||
this.avatarIndex = avatarIndex;
|
||||
this.sleeveIndex = sleeveIndex;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -23,4 +24,8 @@ public class LoginEvent implements NetEvent {
|
||||
public int getAvatarIndex() {
|
||||
return avatarIndex;
|
||||
}
|
||||
|
||||
public int getSleeveIndex() {
|
||||
return sleeveIndex;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ public final class UpdateLobbyPlayerEvent implements NetEvent {
|
||||
private LobbySlotType type = null;
|
||||
private String name = null;
|
||||
private int avatarIndex = -1;
|
||||
private int sleeveIndex = -1;
|
||||
private int team = -1;
|
||||
private Boolean isArchenemy = null;
|
||||
private Boolean isReady = null;
|
||||
@@ -26,11 +27,11 @@ public final class UpdateLobbyPlayerEvent implements NetEvent {
|
||||
private Set<AIOption> aiOptions = null;
|
||||
|
||||
|
||||
public static UpdateLobbyPlayerEvent create(final LobbySlotType type, final String name, final int avatarIndex, final int team, final boolean isArchenemy, final boolean isReady, final Set<AIOption> aiOptions) {
|
||||
return new UpdateLobbyPlayerEvent(type, name, avatarIndex, team, isArchenemy, isReady, aiOptions);
|
||||
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) {
|
||||
return new UpdateLobbyPlayerEvent(type, name, avatarIndex, sleeveIndex, team, isArchenemy, isReady, aiOptions);
|
||||
}
|
||||
public static UpdateLobbyPlayerEvent create(final LobbySlotType type, final String name, final int avatarIndex, final int team, final boolean isArchenemy, final boolean isReady, final boolean isDevMode, final Set<AIOption> aiOptions) {
|
||||
return new UpdateLobbyPlayerEvent(type, name, avatarIndex, team, isArchenemy, isReady, isDevMode, aiOptions);
|
||||
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 boolean isDevMode, final Set<AIOption> aiOptions) {
|
||||
return new UpdateLobbyPlayerEvent(type, name, avatarIndex, sleeveIndex, team, isArchenemy, isReady, isDevMode, aiOptions);
|
||||
}
|
||||
public static UpdateLobbyPlayerEvent deckUpdate(final Deck deck) {
|
||||
return new UpdateLobbyPlayerEvent(deck);
|
||||
@@ -46,6 +47,19 @@ public final class UpdateLobbyPlayerEvent implements NetEvent {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public static UpdateLobbyPlayerEvent avatarUpdate(final int index) {
|
||||
return new UpdateLobbyPlayerEvent(index, true);
|
||||
}
|
||||
public static UpdateLobbyPlayerEvent sleeveUpdate(final int index) {
|
||||
return new UpdateLobbyPlayerEvent(index, false);
|
||||
}
|
||||
private UpdateLobbyPlayerEvent(int index, boolean avatar) {
|
||||
if (avatar)
|
||||
this.avatarIndex = index;
|
||||
else
|
||||
this.sleeveIndex = index;
|
||||
}
|
||||
|
||||
private UpdateLobbyPlayerEvent(final Deck deck) {
|
||||
this.deck = deck;
|
||||
}
|
||||
@@ -59,6 +73,7 @@ public final class UpdateLobbyPlayerEvent implements NetEvent {
|
||||
final LobbySlotType type,
|
||||
final String name,
|
||||
final int avatarIndex,
|
||||
final int sleeveIndex,
|
||||
final int team,
|
||||
final boolean isArchenemy,
|
||||
final boolean isReady,
|
||||
@@ -66,6 +81,7 @@ public final class UpdateLobbyPlayerEvent implements NetEvent {
|
||||
this.type = type;
|
||||
this.name = name;
|
||||
this.avatarIndex = avatarIndex;
|
||||
this.sleeveIndex = sleeveIndex;
|
||||
this.team = team;
|
||||
this.isArchenemy = isArchenemy;
|
||||
this.isReady = isReady;
|
||||
@@ -76,6 +92,7 @@ public final class UpdateLobbyPlayerEvent implements NetEvent {
|
||||
final LobbySlotType type,
|
||||
final String name,
|
||||
final int avatarIndex,
|
||||
final int sleeveIndex,
|
||||
final int team,
|
||||
final boolean isArchenemy,
|
||||
final boolean isReady,
|
||||
@@ -84,6 +101,7 @@ public final class UpdateLobbyPlayerEvent implements NetEvent {
|
||||
this.type = type;
|
||||
this.name = name;
|
||||
this.avatarIndex = avatarIndex;
|
||||
this.sleeveIndex = sleeveIndex;
|
||||
this.team = team;
|
||||
this.isArchenemy = isArchenemy;
|
||||
this.isReady = isReady;
|
||||
@@ -104,6 +122,9 @@ public final class UpdateLobbyPlayerEvent implements NetEvent {
|
||||
public int getAvatarIndex() {
|
||||
return avatarIndex;
|
||||
}
|
||||
public int getSleeveIndex() {
|
||||
return sleeveIndex;
|
||||
}
|
||||
public int getTeam() {
|
||||
return team;
|
||||
}
|
||||
|
||||
@@ -6,13 +6,14 @@ import forge.interfaces.IGuiGame;
|
||||
import forge.interfaces.ILobbyListener;
|
||||
import forge.match.LobbySlot;
|
||||
import forge.match.LobbySlotType;
|
||||
import forge.net.CustomObjectDecoder;
|
||||
import forge.net.CustomObjectEncoder;
|
||||
import forge.net.event.LobbyUpdateEvent;
|
||||
import forge.net.event.LoginEvent;
|
||||
import forge.net.event.LogoutEvent;
|
||||
import forge.net.event.MessageEvent;
|
||||
import forge.net.event.NetEvent;
|
||||
import forge.net.event.UpdateLobbyPlayerEvent;
|
||||
import forge.properties.ForgeConstants;
|
||||
import io.netty.bootstrap.ServerBootstrap;
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.channel.ChannelFuture;
|
||||
@@ -25,8 +26,6 @@ import io.netty.channel.nio.NioEventLoopGroup;
|
||||
import io.netty.channel.socket.SocketChannel;
|
||||
import io.netty.channel.socket.nio.NioServerSocketChannel;
|
||||
import io.netty.handler.codec.serialization.ClassResolvers;
|
||||
import io.netty.handler.codec.serialization.ObjectDecoder;
|
||||
import io.netty.handler.codec.serialization.ObjectEncoder;
|
||||
import io.netty.handler.logging.LogLevel;
|
||||
import io.netty.handler.logging.LoggingHandler;
|
||||
|
||||
@@ -39,7 +38,6 @@ import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.log4j.PropertyConfigurator;
|
||||
import org.fourthline.cling.UpnpService;
|
||||
import org.fourthline.cling.UpnpServiceImpl;
|
||||
import org.fourthline.cling.support.igd.PortMappingListener;
|
||||
@@ -85,7 +83,6 @@ public final class FServerManager {
|
||||
*/
|
||||
public static FServerManager getInstance() {
|
||||
if (instance == null) {
|
||||
PropertyConfigurator.configure(ForgeConstants.ASSETS_DIR + "/src/main/resources/log4jConfig.config");
|
||||
instance = new FServerManager();
|
||||
}
|
||||
return instance;
|
||||
@@ -98,11 +95,12 @@ public final class FServerManager {
|
||||
.channel(NioServerSocketChannel.class)
|
||||
.handler(new LoggingHandler(LogLevel.INFO))
|
||||
.childHandler(new ChannelInitializer<SocketChannel>() {
|
||||
@Override public final void initChannel(final SocketChannel ch) {
|
||||
@Override
|
||||
public final void initChannel(final SocketChannel ch) throws Exception {
|
||||
final ChannelPipeline p = ch.pipeline();
|
||||
p.addLast(
|
||||
new ObjectEncoder(),
|
||||
new ObjectDecoder(ClassResolvers.cacheDisabled(null)),
|
||||
new CustomObjectEncoder(),
|
||||
new CustomObjectDecoder(CustomObjectDecoder.maxObjectsize, ClassResolvers.cacheDisabled(null)),
|
||||
new MessageHandler(),
|
||||
new RegisterClientHandler(),
|
||||
new LobbyInputHandler(),
|
||||
@@ -329,7 +327,7 @@ public final class FServerManager {
|
||||
final RemoteClient client = clients.get(ctx.channel());
|
||||
if (msg instanceof LoginEvent) {
|
||||
final LoginEvent event = (LoginEvent) msg;
|
||||
final int index = localLobby.connectPlayer(event.getUsername(), event.getAvatarIndex());
|
||||
final int index = localLobby.connectPlayer(event.getUsername(), event.getAvatarIndex(), event.getSleeveIndex());
|
||||
if (index == -1) {
|
||||
ctx.close();
|
||||
} else {
|
||||
|
||||
@@ -183,6 +183,12 @@ public class NetGuiGame extends AbstractGuiGame {
|
||||
send(ProtocolMethod.setPanelSelection, hostCard);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refreshField() {
|
||||
updateGameView();
|
||||
send(ProtocolMethod.refreshField);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpellAbilityView getAbilityToPlay(final CardView hostCard, final List<SpellAbilityView> abilities, final ITriggerEvent triggerEvent) {
|
||||
return sendAndWait(ProtocolMethod.getAbilityToPlay, hostCard, abilities, triggerEvent);
|
||||
@@ -259,6 +265,18 @@ public class NetGuiGame extends AbstractGuiGame {
|
||||
send(ProtocolMethod.setCard, card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSelectables(final Iterable<CardView> cards) {
|
||||
updateGameView();
|
||||
send(ProtocolMethod.setSelectables, cards);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearSelectables() {
|
||||
updateGameView();
|
||||
send(ProtocolMethod.clearSelectables);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPlayerAvatar(final LobbyPlayer player, final IHasIcon ihi) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
@@ -13,25 +13,26 @@ public final class ServerGameLobby extends GameLobby {
|
||||
|
||||
public ServerGameLobby() {
|
||||
super(true);
|
||||
addSlot(new LobbySlot(LobbySlotType.LOCAL, localName(), localAvatarIndices()[0], 0, true, false, Collections.emptySet()));
|
||||
addSlot(new LobbySlot(LobbySlotType.OPEN, null, -1, 1, false, false, Collections.emptySet()));
|
||||
addSlot(new LobbySlot(LobbySlotType.LOCAL, localName(), localAvatarIndices()[0], localSleeveIndices()[0],0, true, false, Collections.emptySet()));
|
||||
addSlot(new LobbySlot(LobbySlotType.OPEN, null, -1, -1, 1, false, false, Collections.emptySet()));
|
||||
}
|
||||
|
||||
public int connectPlayer(final String name, final int avatarIndex) {
|
||||
public int connectPlayer(final String name, final int avatarIndex, final int sleeveIndex) {
|
||||
final int nSlots = getNumberOfSlots();
|
||||
for (int index = 0; index < nSlots; index++) {
|
||||
final LobbySlot slot = getSlot(index);
|
||||
if (slot.getType() == LobbySlotType.OPEN) {
|
||||
connectPlayer(name, avatarIndex, slot);
|
||||
connectPlayer(name, avatarIndex, sleeveIndex, slot);
|
||||
return index;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
private void connectPlayer(final String name, final int avatarIndex, final LobbySlot slot) {
|
||||
private void connectPlayer(final String name, final int avatarIndex, final int sleeveIndex, final LobbySlot slot) {
|
||||
slot.setType(LobbySlotType.REMOTE);
|
||||
slot.setName(name);
|
||||
slot.setAvatarIndex(avatarIndex);
|
||||
slot.setSleeveIndex(sleeveIndex);
|
||||
updateView(false);
|
||||
}
|
||||
public void disconnectPlayer(final int index) {
|
||||
|
||||
@@ -127,7 +127,7 @@ public class ConquestController {
|
||||
starter.add(humanStart.setPlayer(humanPlayer));
|
||||
|
||||
final IGuiGame gui = GuiBase.getInterface().getNewGuiGame();
|
||||
final LobbyPlayer aiPlayer = GamePlayerUtil.createAiPlayer(aiPlayerName, -1);
|
||||
final LobbyPlayer aiPlayer = GamePlayerUtil.createAiPlayer(aiPlayerName, -1, -1);
|
||||
battle.setOpponentAvatar(aiPlayer, gui);
|
||||
starter.add(aiStart.setPlayer(aiPlayer));
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ public final class GamePlayerUtil {
|
||||
public static final LobbyPlayer getGuiPlayer() {
|
||||
return guiPlayer;
|
||||
}
|
||||
public static final LobbyPlayer getGuiPlayer(final String name, final int avatarIndex, final boolean writePref) {
|
||||
public static final LobbyPlayer getGuiPlayer(final String name, final int avatarIndex, final int sleeveIndex, final boolean writePref) {
|
||||
if (writePref) {
|
||||
if (!name.equals(guiPlayer.getName())) {
|
||||
guiPlayer.setName(name);
|
||||
@@ -33,7 +33,7 @@ public final class GamePlayerUtil {
|
||||
return guiPlayer;
|
||||
}
|
||||
//use separate LobbyPlayerHuman instance for human players beyond first
|
||||
return new LobbyPlayerHuman(name, avatarIndex);
|
||||
return new LobbyPlayerHuman(name, avatarIndex, sleeveIndex);
|
||||
}
|
||||
|
||||
public static final LobbyPlayer getQuestPlayer() {
|
||||
@@ -45,19 +45,25 @@ public final class GamePlayerUtil {
|
||||
}
|
||||
public final static LobbyPlayer createAiPlayer(final String name) {
|
||||
final int avatarCount = GuiBase.getInterface().getAvatarCount();
|
||||
return createAiPlayer(name, avatarCount == 0 ? 0 : MyRandom.getRandom().nextInt(avatarCount));
|
||||
final int sleeveCount = GuiBase.getInterface().getSleevesCount();
|
||||
return createAiPlayer(name, avatarCount == 0 ? 0 : MyRandom.getRandom().nextInt(avatarCount), sleeveCount == 0 ? 0 : MyRandom.getRandom().nextInt(sleeveCount));
|
||||
}
|
||||
public final static LobbyPlayer createAiPlayer(final String name, final String profileOverride) {
|
||||
final int avatarCount = GuiBase.getInterface().getAvatarCount();
|
||||
return createAiPlayer(name, avatarCount == 0 ? 0 : MyRandom.getRandom().nextInt(avatarCount), null, profileOverride);
|
||||
final int sleeveCount = GuiBase.getInterface().getSleevesCount();
|
||||
return createAiPlayer(name, avatarCount == 0 ? 0 : MyRandom.getRandom().nextInt(avatarCount), sleeveCount == 0 ? 0 : MyRandom.getRandom().nextInt(sleeveCount), null, profileOverride);
|
||||
}
|
||||
public final static LobbyPlayer createAiPlayer(final String name, final int avatarIndex) {
|
||||
return createAiPlayer(name, avatarIndex, null, "");
|
||||
final int sleeveCount = GuiBase.getInterface().getSleevesCount();
|
||||
return createAiPlayer(name, avatarIndex, sleeveCount == 0 ? 0 : MyRandom.getRandom().nextInt(sleeveCount), null, "");
|
||||
}
|
||||
public final static LobbyPlayer createAiPlayer(final String name, final int avatarIndex, final Set<AIOption> options) {
|
||||
return createAiPlayer(name, avatarIndex, options, "");
|
||||
public final static LobbyPlayer createAiPlayer(final String name, final int avatarIndex, final int sleeveIndex) {
|
||||
return createAiPlayer(name, avatarIndex, sleeveIndex, null, "");
|
||||
}
|
||||
public final static LobbyPlayer createAiPlayer(final String name, final int avatarIndex, final Set<AIOption> options, final String profileOverride) {
|
||||
public final static LobbyPlayer createAiPlayer(final String name, final int avatarIndex, final int sleeveIndex, final Set<AIOption> options) {
|
||||
return createAiPlayer(name, avatarIndex, sleeveIndex, options, "");
|
||||
}
|
||||
public final static LobbyPlayer createAiPlayer(final String name, final int avatarIndex, final int sleeveIndex, final Set<AIOption> options, final String profileOverride) {
|
||||
final LobbyPlayerAi player = new LobbyPlayerAi(name, options);
|
||||
|
||||
// TODO: implement specific AI profiles for quest mode.
|
||||
@@ -87,6 +93,7 @@ public final class GamePlayerUtil {
|
||||
|
||||
player.setAiProfile(profile);
|
||||
player.setAvatarIndex(avatarIndex);
|
||||
player.setSleeveIndex(sleeveIndex);
|
||||
return player;
|
||||
}
|
||||
|
||||
|
||||
@@ -9,11 +9,12 @@ import forge.util.GuiDisplayUtil;
|
||||
|
||||
public class LobbyPlayerHuman extends LobbyPlayer implements IGameEntitiesFactory {
|
||||
public LobbyPlayerHuman(final String name) {
|
||||
this(name, -1);
|
||||
this(name, -1, -1);
|
||||
}
|
||||
public LobbyPlayerHuman(final String name, final int avatarIndex) {
|
||||
public LobbyPlayerHuman(final String name, final int avatarIndex, final int sleeveIndex) {
|
||||
super(name);
|
||||
setAvatarIndex(avatarIndex);
|
||||
setSleeveIndex(sleeveIndex);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -678,7 +678,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
|
||||
public CardCollection orderBlockers(final Card attacker, final CardCollection blockers) {
|
||||
final CardView vAttacker = CardView.get(attacker);
|
||||
getGui().setPanelSelection(vAttacker);
|
||||
return game.getCardList(getGui().order("Choose Damage Order for " + vAttacker, "Damaged First",
|
||||
return game.getCardList(getGui().order(localizer.getMessage("lblChooseDamageOrderFor").replace("%s", vAttacker.toString()), localizer.getMessage("lblDamagedFirst"),
|
||||
CardView.getCollection(blockers), vAttacker));
|
||||
}
|
||||
|
||||
@@ -703,7 +703,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
|
||||
final CardView vAttacker = CardView.get(attacker);
|
||||
getGui().setPanelSelection(vAttacker);
|
||||
return game.getCardList(getGui().insertInList(
|
||||
"Choose blocker after which to place " + vAttacker + " in damage order; cancel to place it first",
|
||||
localizer.getMessage("lblChooseBlockerAfterWhichToPlaceAttackert").replace("%s", vAttacker.toString()),
|
||||
CardView.get(blocker), CardView.getCollection(oldBlockers)));
|
||||
}
|
||||
|
||||
@@ -711,7 +711,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
|
||||
public CardCollection orderAttackers(final Card blocker, final CardCollection attackers) {
|
||||
final CardView vBlocker = CardView.get(blocker);
|
||||
getGui().setPanelSelection(vBlocker);
|
||||
return game.getCardList(getGui().order("Choose Damage Order for " + vBlocker, "Damaged First",
|
||||
return game.getCardList(getGui().order(localizer.getMessage("lblChooseDamageOrderFor").replace("%s", vBlocker.toString()), localizer.getMessage("lblDamagedFirst"),
|
||||
CardView.getCollection(attackers), vBlocker));
|
||||
}
|
||||
|
||||
@@ -841,7 +841,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
|
||||
getGui().setCard(c.getView());
|
||||
|
||||
boolean result = false;
|
||||
result = InputConfirm.confirm(this, view, TextUtil.concatNoSpace("Put ", view.toString(), " on the top or bottom of your library?"),
|
||||
result = InputConfirm.confirm(this, view, localizer.getMessage("lblPutCardOnTopOrBottomLibrary").replace("%s", view.toString()),
|
||||
true, ImmutableList.of("Top", "Bottom"));
|
||||
|
||||
endTempShowCards();
|
||||
@@ -876,27 +876,27 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
|
||||
tempShowCards(cards);
|
||||
switch (destinationZone) {
|
||||
case Library:
|
||||
choices = getGui().order("Choose order of cards to put into the library", "Closest to top",
|
||||
choices = getGui().order(localizer.getMessage("lblChooseOrderCardsPutIntoLibrary"), localizer.getMessage("lblClosestToTop"),
|
||||
CardView.getCollection(cards), null);
|
||||
break;
|
||||
case Battlefield:
|
||||
choices = getGui().order("Choose order of cards to put onto the battlefield", "Put first",
|
||||
choices = getGui().order(localizer.getMessage("lblChooseOrderCardsPutOntoBattlefield"), localizer.getMessage("lblPutFirst"),
|
||||
CardView.getCollection(cards), null);
|
||||
break;
|
||||
case Graveyard:
|
||||
choices = getGui().order("Choose order of cards to put into the graveyard", "Closest to bottom",
|
||||
choices = getGui().order(localizer.getMessage("lblChooseOrderCardsPutIntoGraveyard"), localizer.getMessage("lblClosestToBottom"),
|
||||
CardView.getCollection(cards), null);
|
||||
break;
|
||||
case PlanarDeck:
|
||||
choices = getGui().order("Choose order of cards to put into the planar deck", "Closest to top",
|
||||
choices = getGui().order(localizer.getMessage("lblChooseOrderCardsPutIntoPlanarDeck"), localizer.getMessage("lblClosestToTop"),
|
||||
CardView.getCollection(cards), null);
|
||||
break;
|
||||
case SchemeDeck:
|
||||
choices = getGui().order("Choose order of cards to put into the scheme deck", "Closest to top",
|
||||
choices = getGui().order(localizer.getMessage("lblChooseOrderCardsPutIntoSchemeDeck"), localizer.getMessage("lblClosestToTop"),
|
||||
CardView.getCollection(cards), null);
|
||||
break;
|
||||
case Stack:
|
||||
choices = getGui().order("Choose order of copies to cast", "Put first", CardView.getCollection(cards),
|
||||
choices = getGui().order(localizer.getMessage("lblChooseOrderCopiesCast"), localizer.getMessage("lblPutFirst"), CardView.getCollection(cards),
|
||||
null);
|
||||
break;
|
||||
default:
|
||||
@@ -914,14 +914,14 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
|
||||
if (p != player) {
|
||||
tempShowCards(valid);
|
||||
final CardCollection choices = game
|
||||
.getCardList(getGui().many("Choose " + min + " card" + (min != 1 ? "s" : "") + " to discard",
|
||||
"Discarded", min, min, CardView.getCollection(valid), null));
|
||||
.getCardList(getGui().many(String.format(localizer.getMessage("lblChooseMinCardToDiscard"), min),
|
||||
localizer.getMessage("lblDiscarded"), min, min, CardView.getCollection(valid), null));
|
||||
endTempShowCards();
|
||||
return choices;
|
||||
}
|
||||
|
||||
final InputSelectCardsFromList inp = new InputSelectCardsFromList(this, min, max, valid, sa);
|
||||
inp.setMessage(sa.hasParam("AnyNumber") ? "Discard up to %d card(s)" : "Discard %d card(s)");
|
||||
inp.setMessage(sa.hasParam("AnyNumber") ? localizer.getMessage("lblDiscardUpToNCards") : localizer.getMessage("lblDiscardNCards"));
|
||||
inp.showAndWait();
|
||||
return new CardCollection(inp.getSelected());
|
||||
}
|
||||
@@ -938,9 +938,9 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
|
||||
for (int i = 0; i <= cardsInGrave; i++) {
|
||||
cntChoice.add(Integer.valueOf(i));
|
||||
}
|
||||
final int chosenAmount = getGui().one("Delve how many cards?", cntChoice.build()).intValue();
|
||||
final int chosenAmount = getGui().one(localizer.getMessage("lblDelveHowManyCards"), cntChoice.build()).intValue();
|
||||
for (int i = 0; i < chosenAmount; i++) {
|
||||
final CardView nowChosen = getGui().oneOrNone("Exile which card?", CardView.getCollection(grave));
|
||||
final CardView nowChosen = getGui().oneOrNone(localizer.getMessage("lblExileWhichCard"), CardView.getCollection(grave));
|
||||
|
||||
if (nowChosen == null) {
|
||||
// User canceled,abort delving.
|
||||
@@ -1003,7 +1003,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
|
||||
return super.hasAllTargets();
|
||||
}
|
||||
};
|
||||
target.setMessage("Select %d card(s) to discard, unless you discard a " + uType + ".");
|
||||
target.setMessage(localizer.getMessage("lblSelectNCardsToDiscardUnlessDiscarduType").replace("%s", uType));
|
||||
target.showAndWait();
|
||||
return new CardCollection(target.getSelected());
|
||||
}
|
||||
@@ -1316,8 +1316,8 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
|
||||
// opponent's next turn
|
||||
}
|
||||
};
|
||||
final String message = "Cleanup Phase\nSelect " + nDiscard + " card" + (nDiscard > 1 ? "s" : "")
|
||||
+ " to discard to bring your hand down to the maximum of " + max + " cards.";
|
||||
final String message = localizer.getMessage("lblCleanupPhase") + "\n"
|
||||
+ localizer.getMessage("lblSelectCardsToDiscardHandDownMaximum").replace("%d", String.valueOf(nDiscard)).replace("%max", String.valueOf(max));
|
||||
inp.setMessage(message);
|
||||
inp.setCancelAllowed(false);
|
||||
inp.showAndWait();
|
||||
@@ -1587,7 +1587,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
|
||||
|
||||
@Override
|
||||
public ReplacementEffect chooseSingleReplacementEffect(final String prompt,
|
||||
final List<ReplacementEffect> possibleReplacers, final Map<String, Object> runParams) {
|
||||
final List<ReplacementEffect> possibleReplacers) {
|
||||
final ReplacementEffect first = possibleReplacers.get(0);
|
||||
if (possibleReplacers.size() == 1) {
|
||||
return first;
|
||||
|
||||
@@ -94,8 +94,11 @@ public final class ForgeConstants {
|
||||
public static final String SPRITE_OLD_FOILS_FILE = "sprite_old_foils.png";
|
||||
public static final String SPRITE_TROPHIES_FILE = "sprite_trophies.png";
|
||||
public static final String SPRITE_ABILITY_FILE = "sprite_ability.png";
|
||||
public static final String SPRITE_BORDER_FILE = "sprite_border.png";
|
||||
public static final String SPRITE_MANAICONS_FILE = "sprite_manaicons.png";
|
||||
public static final String SPRITE_AVATARS_FILE = "sprite_avatars.png";
|
||||
public static final String SPRITE_SLEEVES_FILE = "sprite_sleeves.png";
|
||||
public static final String SPRITE_SLEEVES2_FILE = "sprite_sleeves2.png";
|
||||
public static final String SPRITE_FAVICONS_FILE = "sprite_favicons.png";
|
||||
public static final String SPRITE_PLANAR_CONQUEST_FILE = "sprite_planar_conquest.png";
|
||||
public static final String FONT_FILE = "font1.ttf";
|
||||
|
||||
@@ -73,6 +73,7 @@ public class ForgePreferences extends PreferencesStore<ForgePreferences.FPref> {
|
||||
UI_RANDOM_FOIL ("false"),
|
||||
UI_ENABLE_AI_CHEATS ("false"),
|
||||
UI_AVATARS ("0,1"),
|
||||
UI_SLEEVES ("0,1"),
|
||||
UI_SHOW_CARD_OVERLAYS ("true"),
|
||||
UI_OVERLAY_CARD_NAME ("true"),
|
||||
UI_OVERLAY_CARD_POWER ("true"),
|
||||
@@ -134,6 +135,9 @@ public class ForgePreferences extends PreferencesStore<ForgePreferences.FPref> {
|
||||
UI_ROTATE_SPLIT_CARDS("true"),
|
||||
UI_DYNAMIC_PLANECHASE_BG("false"),
|
||||
UI_DISABLE_IMAGES_EFFECT_CARDS("false"),
|
||||
UI_ENABLE_PRELOAD_EXTENDED_ART("false"),
|
||||
UI_ENABLE_BORDER_MASKING("false"),
|
||||
UI_SHOW_FPS("false"),
|
||||
UI_ALLOW_ORDER_GRAVEYARD_WHEN_NEEDED ("Never"),
|
||||
UI_DEFAULT_FONT_SIZE("12"),
|
||||
UI_SELECT_FROM_CARD_DISPLAYS("true"),
|
||||
|
||||
@@ -448,7 +448,10 @@ public class QuestController {
|
||||
if (world.getName().equals(QuestWorld.STANDARDWORLDNAME)) {
|
||||
this.duelManager = new QuestEventLDADuelManager(FModel.getFormats().getStandard());
|
||||
return;
|
||||
} else if (world.getName().equals(QuestWorld.MODERNWORLDNAME)) {
|
||||
} else if (world.getName().equals(QuestWorld.PIONEERWORLDNAME)) {
|
||||
this.duelManager = new QuestEventLDADuelManager(FModel.getFormats().getPioneer());
|
||||
return;
|
||||
}else if (world.getName().equals(QuestWorld.MODERNWORLDNAME)) {
|
||||
this.duelManager = new QuestEventLDADuelManager(FModel.getFormats().getModern());
|
||||
return;
|
||||
}else if (world.isCustom()) {
|
||||
|
||||
@@ -360,6 +360,11 @@ public class QuestSpellShop {
|
||||
//If this card has an exception to the card limit, e.g.: Relentless Rats, get the quest preference
|
||||
if (DeckFormat.canHaveAnyNumberOf(card)) {
|
||||
numToKeep = FModel.getQuestPreferences().getPrefInt(QPref.PLAYSET_ANY_NUMBER_SIZE);
|
||||
} else {
|
||||
Integer cardCopies = DeckFormat.canHaveSpecificNumberInDeck(card);
|
||||
if (cardCopies != null) {
|
||||
numToKeep = cardCopies;
|
||||
}
|
||||
}
|
||||
|
||||
if (numToKeep < item.getValue()) {
|
||||
|
||||
@@ -40,6 +40,7 @@ public class QuestWorld implements Comparable<QuestWorld>{
|
||||
private final String dir;
|
||||
private final GameFormatQuest format;
|
||||
public static final String STANDARDWORLDNAME = "Random Standard";
|
||||
public static final String PIONEERWORLDNAME = "Random Pioneer";
|
||||
public static final String MODERNWORLDNAME = "Random Modern";
|
||||
public static final String RANDOMCOMMANDERWORLDNAME = "Random Commander";
|
||||
|
||||
@@ -195,6 +196,12 @@ public class QuestWorld implements Comparable<QuestWorld>{
|
||||
FModel.getFormats().getStandard().getBannedCardNames(),false);
|
||||
}
|
||||
|
||||
if (useName.equalsIgnoreCase(QuestWorld.PIONEERWORLDNAME)){
|
||||
useFormat = new GameFormatQuest(QuestWorld.PIONEERWORLDNAME,
|
||||
FModel.getFormats().getPioneer().getAllowedSetCodes(),
|
||||
FModel.getFormats().getPioneer().getBannedCardNames(),false);
|
||||
}
|
||||
|
||||
if (useName.equalsIgnoreCase(QuestWorld.MODERNWORLDNAME)){
|
||||
useFormat = new GameFormatQuest(QuestWorld.MODERNWORLDNAME,
|
||||
FModel.getFormats().getModern().getAllowedSetCodes(),
|
||||
|
||||
@@ -36,6 +36,9 @@ public class TournamentUtil {
|
||||
case STANDARD_CARDGEN_DECK:
|
||||
deck = DeckgenUtil.buildCardGenDeck(FModel.getFormats().getStandard(),true);
|
||||
break;
|
||||
case PIONEER_CARDGEN_DECK:
|
||||
deck = DeckgenUtil.buildCardGenDeck(FModel.getFormats().getPioneer(),true);
|
||||
break;
|
||||
case MODERN_CARDGEN_DECK:
|
||||
deck = DeckgenUtil.buildCardGenDeck(FModel.getFormats().getModern(),true);
|
||||
break;
|
||||
|
||||
@@ -1,170 +0,0 @@
|
||||
/*
|
||||
* Forge: Play Magic: the Gathering.
|
||||
* Copyright (C) 2011 Forge Team
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package forge.util;
|
||||
|
||||
/**
|
||||
* TODO: Write javadoc for this type.
|
||||
*
|
||||
*/
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
/**
|
||||
* Represents the lines found in an {@link InputStream}. The lines are read one
|
||||
* at a time using {@link BufferedReader#readLine()} and may be streamed through
|
||||
* an iterator or returned all at once.
|
||||
*
|
||||
* <p>
|
||||
* This class does not handle any concurrency issues.
|
||||
*
|
||||
* <p>
|
||||
* The stream is closed automatically when the for loop is done :)
|
||||
*
|
||||
* <pre>
|
||||
* {@code
|
||||
* for(String line : new LineReader(stream))
|
||||
* // ...
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* <p>
|
||||
* An {@link IllegalStateException} will be thrown if any {@link IOException}s
|
||||
* occur when reading or closing the stream.
|
||||
*
|
||||
* @author Torleif Berger
|
||||
* http://creativecommons.org/licenses/by/3.0/
|
||||
* @see http://www.geekality.net/?p=1614
|
||||
*/
|
||||
public class LineReader implements Iterable<String>, Closeable {
|
||||
private final BufferedReader reader;
|
||||
|
||||
/**
|
||||
* Instantiates a new line reader.
|
||||
*
|
||||
* @param stream the stream
|
||||
*/
|
||||
public LineReader(final InputStream stream) {
|
||||
this(stream, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a new line reader.
|
||||
*
|
||||
* @param stream the stream
|
||||
* @param charset the charset
|
||||
*/
|
||||
public LineReader(final InputStream stream, final Charset charset) {
|
||||
this.reader = new BufferedReader(new InputStreamReader(stream, charset));
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes the underlying stream.
|
||||
*
|
||||
* @throws IOException Signals that an I/O exception has occurred.
|
||||
*/
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
this.reader.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes sure the underlying stream is closed.
|
||||
*
|
||||
* @throws Throwable the throwable
|
||||
*/
|
||||
@Override
|
||||
protected void finalize() throws Throwable {
|
||||
this.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an iterator over the lines remaining to be read.
|
||||
*
|
||||
* <p>
|
||||
* The underlying stream is closed automatically once
|
||||
*
|
||||
* @return This iterator.
|
||||
* {@link Iterator#hasNext()} returns false. This means that the stream
|
||||
* should be closed after using a for loop.
|
||||
*/
|
||||
@Override
|
||||
public Iterator<String> iterator() {
|
||||
return new LineIterator();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all lines remaining to be read and closes the stream.
|
||||
*
|
||||
* @return The lines read from the stream.
|
||||
*/
|
||||
public Collection<String> readLines() {
|
||||
final Collection<String> lines = new ArrayList<>();
|
||||
for (final String line : this) {
|
||||
lines.add(line);
|
||||
}
|
||||
return lines;
|
||||
}
|
||||
|
||||
private class LineIterator implements Iterator<String> {
|
||||
private String nextLine;
|
||||
|
||||
public String bufferNext() {
|
||||
try {
|
||||
return this.nextLine = LineReader.this.reader.readLine();
|
||||
} catch (final IOException e) {
|
||||
throw new IllegalStateException("I/O error while reading stream.", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
final boolean hasNext = (this.nextLine != null) || (this.bufferNext() != null);
|
||||
|
||||
if (!hasNext) {
|
||||
try {
|
||||
LineReader.this.reader.close();
|
||||
} catch (final IOException e) {
|
||||
throw new IllegalStateException("I/O error when closing stream.", e);
|
||||
}
|
||||
}
|
||||
|
||||
return hasNext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String next() {
|
||||
if (!this.hasNext()) {
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
|
||||
final String result = this.nextLine;
|
||||
this.nextLine = null;
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
}
|
||||
18
forge-gui/src/main/resources/log4j2.xml
Normal file
18
forge-gui/src/main/resources/log4j2.xml
Normal file
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Configuration status="ALL">
|
||||
<Appenders>
|
||||
<Console name="A1">
|
||||
<PatternLayout pattern="%-4r [%t] %-5p %c %x - %m%n" />
|
||||
</Console>
|
||||
|
||||
<!--Sentry name="Sentry" /-->
|
||||
</Appenders>
|
||||
|
||||
<Loggers>
|
||||
<Root level="ALL">
|
||||
<AppenderRef ref="A1" />
|
||||
<!-- Note that the Sentry logging threshold is overridden to the WARN level -->
|
||||
<!--AppenderRef ref="Sentry" level="WARN" /-->
|
||||
</Root>
|
||||
</Loggers>
|
||||
</Configuration>
|
||||
Reference in New Issue
Block a user