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:
Ryan1729
2019-11-21 10:24:52 -07:00
348 changed files with 5224 additions and 1701 deletions

View File

@@ -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();

View File

@@ -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;
}
}

View File

@@ -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

View File

@@ -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;

View File

@@ -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);
}
}
}

View File

@@ -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);

View File

@@ -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");

View File

@@ -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,

View File

@@ -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:

View File

@@ -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;

View File

@@ -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);

View File

@@ -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();

View File

@@ -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

View File

@@ -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();

View File

@@ -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);
}

View File

@@ -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;

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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()) {

View File

@@ -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(")");
}

View File

@@ -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(")");
}

View File

@@ -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() {

View File

@@ -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());

View 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???
}

View 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);
}
}

View File

@@ -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);
}

View File

@@ -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.

View File

@@ -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));

View File

@@ -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])));
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}

View File

@@ -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 {

View File

@@ -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

View File

@@ -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) {

View File

@@ -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));

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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;

View File

@@ -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";

View File

@@ -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"),

View File

@@ -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()) {

View File

@@ -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()) {

View File

@@ -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(),

View File

@@ -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;

View File

@@ -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();
}
}
}

View 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>