diff --git a/forge-adventure/src/main/java/forge/adventure/Main.java b/forge-adventure/src/main/java/forge/adventure/Main.java index f1bc3f0a02c..dcac01e5c85 100644 --- a/forge-adventure/src/main/java/forge/adventure/Main.java +++ b/forge-adventure/src/main/java/forge/adventure/Main.java @@ -16,7 +16,6 @@ import forge.util.FileUtil; import forge.util.OperatingSystem; import forge.util.RestartUtil; import io.sentry.Sentry; -import io.sentry.SentryClient; import javax.imageio.ImageIO; import java.awt.*; @@ -35,11 +34,12 @@ public class Main { public static void main(String[] args) { - Sentry.init(); - SentryClient sentryClient = Sentry.getStoredClient(); - sentryClient.setRelease(BuildInfo.getVersionString()); - sentryClient.setEnvironment(System.getProperty("os.name")); - sentryClient.addTag("Java Version", System.getProperty("java.version")); + Sentry.init(options -> { + options.setEnableExternalConfiguration(true); + options.setRelease(BuildInfo.getVersionString()); + options.setEnvironment(System.getProperty("os.name")); + options.setTag("Java Version", System.getProperty("java.version")); + }, true); // HACK - temporary solution to "Comparison method violates it's general contract!" crash System.setProperty("java.util.Arrays.useLegacyMergeSort", "true"); diff --git a/forge-ai/src/main/java/forge/ai/AiController.java b/forge-ai/src/main/java/forge/ai/AiController.java index a44490dc4b9..07f5d0badd8 100644 --- a/forge-ai/src/main/java/forge/ai/AiController.java +++ b/forge-ai/src/main/java/forge/ai/AiController.java @@ -64,8 +64,8 @@ import forge.util.ComparatorUtil; import forge.util.Expressions; import forge.util.MyRandom; import forge.util.collect.FCollectionView; +import io.sentry.Breadcrumb; import io.sentry.Sentry; -import io.sentry.event.BreadcrumbBuilder; import java.util.*; @@ -625,7 +625,7 @@ public class AiController { catch (IllegalArgumentException ex) { System.err.println(ex.getMessage()); String assertex = ComparatorUtil.verifyTransitivity(saComparator, all); - Sentry.capture(ex.getMessage() + "\nAssertionError [verifyTransitivity]: " + assertex); + Sentry.captureMessage(ex.getMessage() + "\nAssertionError [verifyTransitivity]: " + assertex); } for (final SpellAbility sa : ComputerUtilAbility.getOriginalAndAltCostAbilities(all, player)) { @@ -836,21 +836,21 @@ public class AiController { if (sa.getApi() != null) { String msg = "AiController:canPlaySa: AI checks for if can PlaySa"; - Sentry.getContext().recordBreadcrumb( - new BreadcrumbBuilder().setMessage(msg) - .withData("Api", sa.getApi().toString()) - .withData("Card", card.getName()).withData("SA", sa.toString()).build() - ); + Breadcrumb bread = new Breadcrumb(msg); + bread.setData("Api", sa.getApi().toString()); + bread.setData("Card", card.getName()); + bread.setData("SA", sa.toString()); + Sentry.addBreadcrumb(bread); // add Extra for debugging - Sentry.getContext().addExtra("Card", card); - Sentry.getContext().addExtra("SA", sa.toString()); + Sentry.setExtra("Card", card.getName()); + Sentry.setExtra("SA", sa.toString()); boolean canPlay = SpellApiToAi.Converter.get(sa.getApi()).canPlayAIWithSubs(player, sa); // remove added extra - Sentry.getContext().removeExtra("Card"); - Sentry.getContext().removeExtra("SA"); + Sentry.removeExtra("Card"); + Sentry.removeExtra("SA"); if (!canPlay) { return AiPlayDecision.CantPlayAi; @@ -1696,7 +1696,7 @@ public class AiController { catch (IllegalArgumentException ex) { System.err.println(ex.getMessage()); String assertex = ComparatorUtil.verifyTransitivity(saComparator, all); - Sentry.capture(ex.getMessage() + "\nAssertionError [verifyTransitivity]: " + assertex); + Sentry.captureMessage(ex.getMessage() + "\nAssertionError [verifyTransitivity]: " + assertex); } for (final SpellAbility sa : ComputerUtilAbility.getOriginalAndAltCostAbilities(all, player)) { diff --git a/forge-core/pom.xml b/forge-core/pom.xml index aa0d904c3e1..25483a89b66 100644 --- a/forge-core/pom.xml +++ b/forge-core/pom.xml @@ -16,12 +16,12 @@ com.google.guava guava - 31.0.1-android + 31.1-android org.apache.commons commons-lang3 - 3.8.1 + 3.12.0 diff --git a/forge-core/src/main/java/forge/item/InventoryItem.java b/forge-core/src/main/java/forge/item/InventoryItem.java index 6f019c53c9d..df8e20a1818 100644 --- a/forge-core/src/main/java/forge/item/InventoryItem.java +++ b/forge-core/src/main/java/forge/item/InventoryItem.java @@ -26,51 +26,4 @@ import forge.util.IHasName; public interface InventoryItem extends IHasName { String getItemType(); String getImageKey(boolean altState); - - /** - * Converts a card name to a sortable name. - * Trim leading quotes, then move article last, then replace characters. - * Because An-Havva Constable. - * Capitals and lowercase sorted as one: "my deck" before "Myr Retribution" - * Apostrophes matter, though: "D'Avenant" before "Danitha" - * TO DO: Commas before apostrophes: "Rakdos, Lord of Riots" before "Rakdos's Return" - * - * @param printedName The name of the card. - * @return A sortable name. - */ - public static String toSortableName(String printedName) { - if (printedName.startsWith("\"")) printedName = printedName.substring(1); - return moveArticleToEnd(printedName).toLowerCase().replaceAll("[^\\s'0-9a-z]", ""); - } - - - /** - * Article words. These words get kicked to the end of a sortable name. - * For localization, simply overwrite this array with appropriate words. - * Words in this list are used by the method String moveArticleToEnd(String), useful - * for alphabetizing phrases, in particular card or other inventory object names. - */ - public static final String[] ARTICLE_WORDS = { - "A", - "An", - "The" - }; - - /** - * Detects whether a string begins with an article word - * - * @param str The name of the card. - * @return The sort-friendly name of the card. Example: "The Hive" becomes "Hive The". - */ - public static String moveArticleToEnd(String str) { - String articleWord; - for (int i = 0; i < ARTICLE_WORDS.length; i++) { - articleWord = ARTICLE_WORDS[i]; - if (str.startsWith(articleWord + " ")) { - str = str.substring(articleWord.length() + 1) + " " + articleWord; - return str; - } - } - return str; - } } diff --git a/forge-core/src/main/java/forge/item/PaperCard.java b/forge-core/src/main/java/forge/item/PaperCard.java index df10046f9b1..9fe5b2039f7 100644 --- a/forge-core/src/main/java/forge/item/PaperCard.java +++ b/forge-core/src/main/java/forge/item/PaperCard.java @@ -190,7 +190,7 @@ public final class PaperCard implements Comparable, InventoryItemFro collectorNumber = (collectorNumber0 != null) && (collectorNumber0.length() > 0) ? collectorNumber0 : IPaperCard.NO_COLLECTOR_NUMBER; // If the user changes the language this will make cards sort by the old language until they restart the game. // This is a good tradeoff - sortableName = InventoryItem.toSortableName(CardTranslation.getTranslatedName(rules0.getName())); + sortableName = TextUtil.toSortableName(CardTranslation.getTranslatedName(rules0.getName())); } // Want this class to be a key for HashTable diff --git a/forge-core/src/main/java/forge/util/TextUtil.java b/forge-core/src/main/java/forge/util/TextUtil.java index 3ae45c32e70..9496391736a 100644 --- a/forge-core/src/main/java/forge/util/TextUtil.java +++ b/forge-core/src/main/java/forge/util/TextUtil.java @@ -313,4 +313,51 @@ public class TextUtil { return "mana";//fix manamorphose stack description and probably others.. return "{"+TextUtil.fastReplace(ManaProduced," ","}{")+"}"; } + + /** + * Converts a card name to a sortable name. + * Trim leading quotes, then move article last, then replace characters. + * Because An-Havva Constable. + * Capitals and lowercase sorted as one: "my deck" before "Myr Retribution" + * Apostrophes matter, though: "D'Avenant" before "Danitha" + * TO DO: Commas before apostrophes: "Rakdos, Lord of Riots" before "Rakdos's Return" + * + * @param printedName The name of the card. + * @return A sortable name. + */ + public static String toSortableName(String printedName) { + if (printedName.startsWith("\"")) printedName = printedName.substring(1); + return moveArticleToEnd(printedName).toLowerCase().replaceAll("[^\\s'0-9a-z]", ""); + } + + + /** + * Article words. These words get kicked to the end of a sortable name. + * For localization, simply overwrite this array with appropriate words. + * Words in this list are used by the method String moveArticleToEnd(String), useful + * for alphabetizing phrases, in particular card or other inventory object names. + */ + public static final String[] ARTICLE_WORDS = { + "A", + "An", + "The" + }; + + /** + * Detects whether a string begins with an article word + * + * @param str The name of the card. + * @return The sort-friendly name of the card. Example: "The Hive" becomes "Hive The". + */ + public static String moveArticleToEnd(String str) { + String articleWord; + for (int i = 0; i < ARTICLE_WORDS.length; i++) { + articleWord = ARTICLE_WORDS[i]; + if (str.startsWith(articleWord + " ")) { + str = str.substring(articleWord.length() + 1) + " " + articleWord; + return str; + } + } + return str; + } } diff --git a/forge-game/pom.xml b/forge-game/pom.xml index 002607cd494..fd7c0627952 100644 --- a/forge-game/pom.xml +++ b/forge-game/pom.xml @@ -26,14 +26,14 @@ junit junit - 4.10 + 4.13.2 test jar io.sentry sentry-logback - 1.7.30 + 5.7.0 diff --git a/forge-game/src/main/java/forge/game/ability/AbilityFactory.java b/forge-game/src/main/java/forge/game/ability/AbilityFactory.java index b2359829155..837963f5f7f 100644 --- a/forge-game/src/main/java/forge/game/ability/AbilityFactory.java +++ b/forge-game/src/main/java/forge/game/ability/AbilityFactory.java @@ -35,8 +35,8 @@ import forge.game.cost.Cost; import forge.game.spellability.*; import forge.game.zone.ZoneType; import forge.util.FileSection; +import io.sentry.Breadcrumb; import io.sentry.Sentry; -import io.sentry.event.BreadcrumbBuilder; /** *

@@ -145,10 +145,12 @@ public final class AbilityFactory { return getAbility(mapParams, type, state, sVarHolder); } catch (Error | Exception ex) { String msg = "AbilityFactory:getAbility: crash when trying to create ability "; - Sentry.getContext().recordBreadcrumb( - new BreadcrumbBuilder().setMessage(msg) - .withData("Card", state.getName()).withData("Ability", abString).build() - ); + + Breadcrumb bread = new Breadcrumb(msg); + bread.setData("Card", state.getName()); + bread.setData("Ability", abString); + + Sentry.addBreadcrumb(bread); throw new RuntimeException(msg + " of card: " + state.getName(), ex); } } diff --git a/forge-game/src/main/java/forge/game/ability/AbilityUtils.java b/forge-game/src/main/java/forge/game/ability/AbilityUtils.java index 6a8bf99c4de..1ba0172c7a3 100644 --- a/forge-game/src/main/java/forge/game/ability/AbilityUtils.java +++ b/forge-game/src/main/java/forge/game/ability/AbilityUtils.java @@ -73,8 +73,8 @@ import forge.util.MyRandom; import forge.util.TextUtil; import forge.util.collect.FCollection; import forge.util.collect.FCollectionView; +import io.sentry.Breadcrumb; import io.sentry.Sentry; -import io.sentry.event.BreadcrumbBuilder; public class AbilityUtils { @@ -1428,11 +1428,11 @@ public class AbilityUtils { final Card card = sa.getHostCard(); String msg = "AbilityUtils:resolveApiAbility: try to resolve API ability"; - Sentry.getContext().recordBreadcrumb( - new BreadcrumbBuilder().setMessage(msg) - .withData("Api", sa.getApi().toString()) - .withData("Card", card.getName()).withData("SA", sa.toString()).build() - ); + Breadcrumb bread = new Breadcrumb(msg); + bread.setData("Api", sa.getApi().toString()); + bread.setData("Card", card.getName()); + bread.setData("SA", sa.toString()); + Sentry.addBreadcrumb(bread); // check conditions if (sa.metConditions()) { diff --git a/forge-game/src/main/java/forge/game/ability/effects/ManaEffect.java b/forge-game/src/main/java/forge/game/ability/effects/ManaEffect.java index 9c74ce0685b..59ff6322391 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/ManaEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/ManaEffect.java @@ -23,8 +23,8 @@ import forge.game.spellability.AbilityManaPart; import forge.game.spellability.SpellAbility; import forge.game.zone.ZoneType; import forge.util.Localizer; +import io.sentry.Breadcrumb; import io.sentry.Sentry; -import io.sentry.event.BreadcrumbBuilder; public class ManaEffect extends SpellAbilityEffect { @@ -231,10 +231,12 @@ public class ManaEffect extends SpellAbilityEffect { // this can happen when mana is based on criteria that didn't match if (mana.isEmpty()) { String msg = "AbilityFactoryMana::manaResolve() - special mana effect is empty for"; - Sentry.getContext().recordBreadcrumb( - new BreadcrumbBuilder().setMessage(msg) - .withData("Card", card.getName()).withData("SA", sa.toString()).build() - ); + + Breadcrumb bread = new Breadcrumb(msg); + bread.setData("Card", card.getName()); + bread.setData("SA", sa.toString()); + Sentry.addBreadcrumb(bread, sa); + continue; } diff --git a/forge-game/src/main/java/forge/game/card/Card.java b/forge-game/src/main/java/forge/game/card/Card.java index 8e30e5b32c5..af11ed05d38 100644 --- a/forge-game/src/main/java/forge/game/card/Card.java +++ b/forge-game/src/main/java/forge/game/card/Card.java @@ -70,8 +70,8 @@ import forge.trackable.Tracker; import forge.util.*; import forge.util.collect.FCollection; import forge.util.collect.FCollectionView; +import io.sentry.Breadcrumb; import io.sentry.Sentry; -import io.sentry.event.BreadcrumbBuilder; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.mutable.MutableBoolean; import org.apache.commons.lang3.tuple.Pair; @@ -2183,10 +2183,11 @@ public class Card extends GameEntity implements Comparable, IHasSVars { } } catch (Exception e) { String msg = "Card:keywordToText: crash in Keyword parsing"; - Sentry.getContext().recordBreadcrumb( - new BreadcrumbBuilder().setMessage(msg) - .withData("Card", this.getName()).withData("Keyword", keyword).build() - ); + + Breadcrumb bread = new Breadcrumb(msg); + bread.setData("Card", this.getName()); + bread.setData("Keyword", keyword); + Sentry.addBreadcrumb(bread, this); throw new RuntimeException("Error in Card " + this.getName() + " with Keyword " + keyword, e); } @@ -2672,10 +2673,11 @@ public class Card extends GameEntity implements Comparable, IHasSVars { } } catch (Exception e) { String msg = "Card:abilityTextInstantSorcery: crash in Keyword parsing"; - Sentry.getContext().recordBreadcrumb( - new BreadcrumbBuilder().setMessage(msg) - .withData("Card", this.getName()).withData("Keyword", keyword).build() - ); + + Breadcrumb bread = new Breadcrumb(msg); + bread.setData("Card", this.getName()); + bread.setData("Keyword", keyword); + Sentry.addBreadcrumb(bread, this); throw new RuntimeException("Error in Card " + this.getName() + " with Keyword " + keyword, e); } diff --git a/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java b/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java index feb2f18455b..e3bc93829a9 100644 --- a/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java +++ b/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java @@ -74,8 +74,8 @@ import forge.game.trigger.TriggerHandler; import forge.game.zone.ZoneType; import forge.util.Lang; import forge.util.TextUtil; +import io.sentry.Breadcrumb; import io.sentry.Sentry; -import io.sentry.event.BreadcrumbBuilder; /** *

@@ -599,10 +599,11 @@ public class CardFactoryUtil { intrinsicAbility.setCardState(card.getCurrentState()); } catch (Exception e) { String msg = "CardFactoryUtil:addAbilityFactoryAbilities: crash in raw Ability"; - Sentry.getContext().recordBreadcrumb( - new BreadcrumbBuilder().setMessage(msg) - .withData("Card", card.getName()).withData("Ability", rawAbility).build() - ); + + Breadcrumb bread = new Breadcrumb(msg); + bread.setData("Card", card.getName()); + bread.setData("Ability", rawAbility); + Sentry.addBreadcrumb(bread, card); // rethrow the exception with card Name for the user throw new RuntimeException("crash in raw Ability, check card script of " + card.getName(), e); diff --git a/forge-game/src/main/java/forge/game/card/CardState.java b/forge-game/src/main/java/forge/game/card/CardState.java index 6d267fca627..e52678f1c93 100644 --- a/forge-game/src/main/java/forge/game/card/CardState.java +++ b/forge-game/src/main/java/forge/game/card/CardState.java @@ -50,8 +50,8 @@ import forge.game.staticability.StaticAbility; import forge.game.trigger.Trigger; import forge.util.collect.FCollection; import forge.util.collect.FCollectionView; +import io.sentry.Breadcrumb; import io.sentry.Sentry; -import io.sentry.event.BreadcrumbBuilder; public class CardState extends GameObject implements IHasSVars { private String name = ""; @@ -270,10 +270,11 @@ public class CardState extends GameObject implements IHasSVars { inst = intrinsicKeywords.add(s); } catch (Exception e) { String msg = "CardState:addIntrinsicKeyword: failed to parse Keyword"; - Sentry.getContext().recordBreadcrumb( - new BreadcrumbBuilder().setMessage(msg) - .withData("Card", card.getName()).withData("Keyword", s).build() - ); + + Breadcrumb bread = new Breadcrumb(msg); + bread.setData("Card", card.getName()); + bread.setData("Keyword", s); + Sentry.addBreadcrumb(bread, this); //rethrow throw new RuntimeException("Error in Keyword " + s + " for card " + card.getName(), e); diff --git a/forge-game/src/main/java/forge/game/card/CardUtil.java b/forge-game/src/main/java/forge/game/card/CardUtil.java index f4187a6a66a..50641285999 100644 --- a/forge-game/src/main/java/forge/game/card/CardUtil.java +++ b/forge-game/src/main/java/forge/game/card/CardUtil.java @@ -46,8 +46,8 @@ import forge.game.spellability.TargetRestrictions; import forge.game.zone.ZoneType; import forge.util.TextUtil; import forge.util.collect.FCollection; +import io.sentry.Breadcrumb; import io.sentry.Sentry; -import io.sentry.event.BreadcrumbBuilder; public final class CardUtil { // disable instantiation @@ -190,13 +190,12 @@ public final class CardUtil { return cachedCard; } String msg = "CardUtil:getLKICopy copy object"; - Sentry.getContext().recordBreadcrumb( - new BreadcrumbBuilder().setMessage(msg) - .withData("Card", in.getName()) - .withData("CardState", in.getCurrentStateName().toString()) - .withData("Player", in.getController().getName()) - .build() - ); + + Breadcrumb bread = new Breadcrumb(msg); + bread.setData("Card", in.getName()); + bread.setData("CardState", in.getCurrentStateName().toString()); + bread.setData("Player", in.getController().getName()); + Sentry.addBreadcrumb(bread, in); final Card newCopy = new Card(in.getId(), in.getPaperCard(), in.getGame(), null); cachedMap.put(in.getId(), newCopy); diff --git a/forge-game/src/main/java/forge/game/keyword/KeywordInstance.java b/forge-game/src/main/java/forge/game/keyword/KeywordInstance.java index b3b20f2740d..1696cb7b20b 100644 --- a/forge-game/src/main/java/forge/game/keyword/KeywordInstance.java +++ b/forge-game/src/main/java/forge/game/keyword/KeywordInstance.java @@ -16,8 +16,8 @@ import forge.game.spellability.SpellAbility; import forge.game.staticability.StaticAbility; import forge.game.trigger.Trigger; import forge.util.Lang; +import io.sentry.Breadcrumb; import io.sentry.Sentry; -import io.sentry.event.BreadcrumbBuilder; public abstract class KeywordInstance> implements KeywordInterface { private Keyword keyword; @@ -95,14 +95,15 @@ public abstract class KeywordInstance> implements K try { String msg = "KeywordInstance:createTraits: make Traits for Keyword"; - Sentry.getContext().recordBreadcrumb( - new BreadcrumbBuilder().setMessage(msg) - .withData("Card", host.getName()).withData("Keyword", this.original).build() - ); + + Breadcrumb bread = new Breadcrumb(msg); + bread.setData("Card", host.getName()); + bread.setData("Keyword", this.original); + Sentry.addBreadcrumb(bread, this); // add Extra for debugging - Sentry.getContext().addExtra("Card", host); - Sentry.getContext().addExtra("Keyword", this.original); + Sentry.setExtra("Card", host.getName()); + Sentry.setExtra("Keyword", this.original); CardFactoryUtil.addTriggerAbility(this, host, intrinsic); CardFactoryUtil.addReplacementEffect(this, host.getCurrentState(), intrinsic); @@ -110,16 +111,18 @@ public abstract class KeywordInstance> implements K CardFactoryUtil.addStaticAbility(this, host.getCurrentState(), intrinsic); } catch (Exception e) { String msg = "KeywordInstance:createTraits: failed Traits for Keyword"; - Sentry.getContext().recordBreadcrumb( - new BreadcrumbBuilder().setMessage(msg) - .withData("Card", host.getName()).withData("Keyword", this.original).build() - ); + + Breadcrumb bread = new Breadcrumb(msg); + bread.setData("Card", host.getName()); + bread.setData("Keyword", this.original); + Sentry.addBreadcrumb(bread, this); + //rethrow throw new RuntimeException("Error in Keyword " + this.original + " for card " + host.getName(), e); } finally { // remove added extra - Sentry.getContext().removeExtra("Card"); - Sentry.getContext().removeExtra("Keyword"); + Sentry.removeExtra("Card"); + Sentry.removeExtra("Keyword"); } } @@ -143,14 +146,15 @@ public abstract class KeywordInstance> implements K } try { String msg = "KeywordInstance:createTraits: make Traits for Keyword"; - Sentry.getContext().recordBreadcrumb( - new BreadcrumbBuilder().setMessage(msg) - .withData("Player", player.getName()).withData("Keyword", this.original).build() - ); + + Breadcrumb bread = new Breadcrumb(msg); + bread.setData("Player", player.getName()); + bread.setData("Keyword", this.original); + Sentry.addBreadcrumb(bread, this); // add Extra for debugging - Sentry.getContext().addExtra("Player", player); - Sentry.getContext().addExtra("Keyword", this.original); + Sentry.setExtra("Player", player.getName()); + Sentry.setExtra("Keyword", this.original); PlayerFactoryUtil.addTriggerAbility(this, player); PlayerFactoryUtil.addReplacementEffect(this, player); @@ -158,16 +162,18 @@ public abstract class KeywordInstance> implements K PlayerFactoryUtil.addStaticAbility(this, player); } catch (Exception e) { String msg = "KeywordInstance:createTraits: failed Traits for Keyword"; - Sentry.getContext().recordBreadcrumb( - new BreadcrumbBuilder().setMessage(msg) - .withData("Player", player.getName()).withData("Keyword", this.original).build() - ); + + Breadcrumb bread = new Breadcrumb(msg); + bread.setData("Player", player.getName()); + bread.setData("Keyword", this.original); + Sentry.addBreadcrumb(bread, this); + //rethrow throw new RuntimeException("Error in Keyword " + this.original + " for player " + player.getName(), e); } finally { // remove added extra - Sentry.getContext().removeExtra("Player"); - Sentry.getContext().removeExtra("Keyword"); + Sentry.removeExtra("Player"); + Sentry.removeExtra("Keyword"); } } /* diff --git a/forge-game/src/main/java/forge/game/trigger/TriggerHandler.java b/forge-game/src/main/java/forge/game/trigger/TriggerHandler.java index 3187ab21a96..bc1c8c3acd6 100644 --- a/forge-game/src/main/java/forge/game/trigger/TriggerHandler.java +++ b/forge-game/src/main/java/forge/game/trigger/TriggerHandler.java @@ -40,8 +40,8 @@ import forge.game.zone.Zone; import forge.game.zone.ZoneType; import forge.util.FileSection; import forge.util.Visitor; +import io.sentry.Breadcrumb; import io.sentry.Sentry; -import io.sentry.event.BreadcrumbBuilder; public class TriggerHandler { private final Set suppressedModes = Collections.synchronizedSet(EnumSet.noneOf(TriggerType.class)); @@ -127,10 +127,12 @@ public class TriggerHandler { return TriggerHandler.parseTrigger(mapParams, host, intrinsic, sVarHolder); } catch (Exception e) { String msg = "TriggerHandler:parseTrigger failed to parse"; - Sentry.getContext().recordBreadcrumb( - new BreadcrumbBuilder().setMessage(msg) - .withData("Card", host.getName()).withData("Trigger", trigParse).build() - ); + + Breadcrumb bread = new Breadcrumb(msg); + bread.setData("Card", host.getName()); + bread.setData("Trigger", trigParse); + Sentry.addBreadcrumb(bread, host); + //rethrow throw new RuntimeException("Error in Trigger for Card: " + host.getName(), e); } @@ -153,10 +155,12 @@ public class TriggerHandler { } } catch (Exception e) { String msg = "TriggerHandler:parseTrigger failed to parse"; - Sentry.getContext().recordBreadcrumb( - new BreadcrumbBuilder().setMessage(msg) - .withData("Card", host.getName()).withData("Params", mapParams.toString()).build() - ); + + Breadcrumb bread = new Breadcrumb(msg); + bread.setData("Card", host.getName()); + bread.setData("Params", mapParams.toString()); + Sentry.addBreadcrumb(bread, host); + //rethrow throw new RuntimeException("Error in Trigger for Card: " + host.getName(), e); } diff --git a/forge-gui-android/AndroidManifest.xml b/forge-gui-android/AndroidManifest.xml index 92fc4afcdcb..8237552827d 100644 --- a/forge-gui-android/AndroidManifest.xml +++ b/forge-gui-android/AndroidManifest.xml @@ -2,7 +2,7 @@ + android:versionName="1.6.49" > + + + + + diff --git a/forge-gui-android/pom.xml b/forge-gui-android/pom.xml index 695751741a4..c3a8a838850 100644 --- a/forge-gui-android/pom.xml +++ b/forge-gui-android/pom.xml @@ -6,7 +6,7 @@ jar -Xms1024m -Xmx1536m - 1.6.47.001 + 1.6.49.001 keystore alias storepass @@ -45,7 +45,6 @@ forge-android-${alpha-version} - com.google.android @@ -104,7 +103,69 @@ io.sentry sentry-android - 1.7.30 + 5.7.0 + aar + + + io.sentry + sentry-android-core + + + io.sentry + sentry-android-ndk + + + + + + io.sentry + sentry-android-core + 5.7.0 + aar + + + androidx.lifecycle + lifecycle-process + + + androidx.lifecycle + lifecycle-common-java8 + + + androidx.core + core + + + + + io.sentry + sentry-android-ndk + 5.7.0 + aar + + + io.sentry + sentry-android-core + + + androidx.lifecycle + lifecycle-process + + + androidx.lifecycle + lifecycle-common-java8 + + + androidx.core + core + + + + + + com.google.code.gson + gson + 2.8.5 @@ -119,7 +180,19 @@ com.simpligility.maven.plugins android-maven-plugin - 4.2.1 + + + javax.xml.bind + jaxb-api + 2.3.1 + + + net.sf.proguard + proguard-base + 6.2.2 + + + 4.6.0 true @@ -139,11 +212,21 @@ ${project.basedir}/proguard.cfg true - + d8 + + 26 ${build.min.memory} ${build.max.memory} + + + true + + ${build.min.memory} + ${build.max.memory} + + --min-sdk-version=26 @@ -160,7 +243,19 @@ com.simpligility.maven.plugins android-maven-plugin - 4.2.1 + + + javax.xml.bind + jaxb-api + 2.3.1 + + + net.sf.proguard + proguard-base + 6.2.2 + + + 4.6.0 true @@ -183,11 +278,21 @@ ${project.basedir}/proguard.cfg true - + d8 + + 26 ${build.min.memory} ${build.max.memory} + + + true + + ${build.min.memory} + ${build.max.memory} + + --min-sdk-version=26 @@ -238,7 +343,19 @@ com.simpligility.maven.plugins android-maven-plugin - 4.2.1 + + + javax.xml.bind + jaxb-api + 2.3.1 + + + net.sf.proguard + proguard-base + 6.2.2 + + + 4.6.0 true diff --git a/forge-gui-android/proguard.cfg b/forge-gui-android/proguard.cfg index b5365a37c33..5b4a814d1f6 100644 --- a/forge-gui-android/proguard.cfg +++ b/forge-gui-android/proguard.cfg @@ -6,9 +6,13 @@ -verbose -optimizations !code/simplification/arithmetic,!field/*,!class/merging/*,!code/allocation/variable +-android + ## Uncomment the line below and set it to the location of rt.jar in JDK if the Proguard step fails to find the libraries ## and spits out a thousand-something Class Not Found errors ##-libraryjars /usr/lib/jvm/java-8-openjdk-amd64/jre/lib/rt.jar +##-libraryjars /jmods/java.base.jmod(!**.jar;!module-info.class) +##-libraryjars /jmods/jdk.xml.dom.jmod(!**.jar;!module-info.class) -dontwarn afu.org.checkerframework.** -dontwarn io.netty.** @@ -16,32 +20,55 @@ -dontwarn com.thoughtworks.xstream.** -dontwarn com.badlogic.gdx.** -dontwarn org.apache.commons.** +-dontwarn org.apache.http.** -dontwarn com.google.guava.** -dontwarn com.google.common.** +-dontwarn com.google.gson.** -dontwarn org.checkerframework.** -dontwarn org.xmlpull.** -dontwarn org.apache.log4j.** -dontwarn org.fourthline.cling.** -dontwarn org.seamless.http.** +-dontwarn org.seamless.xhtml.** +-dontwarn org.seamless.xml.** -dontwarn org.seamless.util.** -dontwarn org.seamless.swing.** -dontwarn java.lang.management.** -dontwarn java.awt.** -dontwarn java.util.** -dontwarn java.lang.** +-dontwarn java.net.** +-dontwarn java.nio.** +-dontwarn java.io.** -dontwarn org.slf4j.** +-dontwarn ch.qos.logback.** -dontwarn javax.** -dontwarn org.apache.logging.log4j.** -dontwarn module-info +-dontwarn io.sentry.logback.* +-dontwarn io.sentry.** +-dontwarn net.jpountz.** ## Support library --dontwarn android.support.** +-dontwarn android.** +-dontwarn androidx.** + +-dontwarn forge.** -keep class forge.** { *; } -keep class com.thoughtworks.xstream.** { *; } -keep class org.apache.commons.lang3.** { *; } -keep class com.google.guava.** { *; } -keep class com.google.common.** { *; } +-keep class com.google.gson.GsonBuilder -keep class io.sentry.event.Event { *; } +-keep class io.sentry.android.core.SentryAndroidOptions +-keep class io.sentry.android.core.SentryAndroid + +-keep class io.sentry.android.core.SentryInitProvider +-keep class io.sentry.android.core.SentryPerformanceProvider + +-keep class io.sentry.android.ndk.SentryNdk +-keep class io.sentry.Sentry -keep class io.netty.util.internal.logging.** { *; } -keep class net.jpountz.** { *; } -keep class com.ray3k.** { *; } diff --git a/forge-gui-android/src/forge/app/Main.java b/forge-gui-android/src/forge/app/Main.java index 7a47506f544..d21b6f3d725 100644 --- a/forge-gui-android/src/forge/app/Main.java +++ b/forge-gui-android/src/forge/app/Main.java @@ -53,9 +53,9 @@ import forge.localinstance.properties.ForgePreferences; import forge.model.FModel; import forge.util.FileUtil; import forge.util.ThreadUtil; +import io.sentry.Breadcrumb; import io.sentry.Sentry; -import io.sentry.android.AndroidSentryClientFactory; -import io.sentry.event.BreadcrumbBuilder; +//import io.sentry.android.core.SentryAndroid; public class Main extends AndroidApplication { AndroidAdapter Gadapter; @@ -63,10 +63,10 @@ public class Main extends AndroidApplication { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - Context ctx = this.getApplicationContext(); - String sentryDsn = "https://a0b8dbad9b8a49cfa51bf65d462e8dae:b3f27d7461224cb8836eb5c6050c666c@sentry.cardforge.org/2?buffer.enabled=false"; + //init Sentry - Sentry.init(sentryDsn, new AndroidSentryClientFactory(ctx)); + //SentryAndroid.init(this); + //get total device RAM in mb ActivityManager actManager = (ActivityManager) getSystemService(ACTIVITY_SERVICE); ActivityManager.MemoryInfo memInfo = new ActivityManager.MemoryInfo(); @@ -217,9 +217,7 @@ public class Main extends AndroidApplication { //fake init for error message //set current orientation String message = getDeviceName()+"\n"+"Android "+AndroidRelease+"\n"+"RAM "+ totalRAM+"MB" +"\n"+"LibGDX "+ Version.VERSION+"\n"+"Can't access external storage"; - Sentry.getContext().recordBreadcrumb( - new BreadcrumbBuilder().setMessage(message).build() - ); + Sentry.addBreadcrumb(new Breadcrumb(message)); Main.this.setRequestedOrientation(Main.this.getResources().getConfiguration().orientation); initialize(Forge.getApp(new AndroidClipboard(), adapter, "", false, true, totalRAM, isTabletDevice, AndroidAPI, AndroidRelease, getDeviceName())); displayMessage(adapter, true, message); @@ -232,9 +230,7 @@ public class Main extends AndroidApplication { //fake init for error message //set current orientation String message = getDeviceName()+"\n"+"Android "+AndroidRelease+"\n"+"RAM "+ totalRAM+"MB" +"\n"+"LibGDX "+ Version.VERSION+"\n"+"Can't access external storage\nPath: " + assetsDir; - Sentry.getContext().recordBreadcrumb( - new BreadcrumbBuilder().setMessage(message).build() - ); + Sentry.addBreadcrumb(new Breadcrumb(message)); Main.this.setRequestedOrientation(Main.this.getResources().getConfiguration().orientation); initialize(Forge.getApp(new AndroidClipboard(), adapter, "", false, true, totalRAM, isTabletDevice, AndroidAPI, AndroidRelease, getDeviceName())); displayMessage(adapter, true, message); diff --git a/forge-gui-desktop/pom.xml b/forge-gui-desktop/pom.xml index 8ba58c34c3a..2bce22e23c4 100644 --- a/forge-gui-desktop/pom.xml +++ b/forge-gui-desktop/pom.xml @@ -139,12 +139,6 @@ java-image-scaling 0.8.5 - - org.testng - testng - 6.9.10 - test - org.powermock powermock-module-testng-common @@ -184,30 +178,30 @@ org.mockito mockito-core - 3.3.3 + 3.12.4 test net.bytebuddy byte-buddy - 1.10.5 + 1.12.3 net.bytebuddy byte-buddy-agent - 1.10.5 + 1.12.3 test org.objenesis objenesis - 2.6 + 3.2 test org.freemarker freemarker - 2.3.20 + 2.3.31 com.googlecode.soundlibs @@ -240,7 +234,7 @@ com.akathist.maven.plugins.launch4j launch4j-maven-plugin - 1.7.25 + 2.1.2 l4j-gui @@ -405,7 +399,7 @@ com.akathist.maven.plugins.launch4j launch4j-maven-plugin - 1.7.25 + 2.1.2 l4j-gui diff --git a/forge-gui-desktop/src/main/java/forge/view/Main.java b/forge-gui-desktop/src/main/java/forge/view/Main.java index 0a9fb687588..2f6824ff4ea 100644 --- a/forge-gui-desktop/src/main/java/forge/view/Main.java +++ b/forge-gui-desktop/src/main/java/forge/view/Main.java @@ -24,7 +24,6 @@ import forge.gui.GuiBase; import forge.gui.card.CardReaderExperiments; import forge.util.BuildInfo; import io.sentry.Sentry; -import io.sentry.SentryClient; /** * Main class for Forge's swing application view. @@ -34,11 +33,13 @@ public final class Main { * Main entry point for Forge */ public static void main(final String[] args) { - Sentry.init(); - SentryClient sentryClient = Sentry.getStoredClient(); - sentryClient.setRelease(BuildInfo.getVersionString()); - sentryClient.setEnvironment(System.getProperty("os.name")); - sentryClient.addTag("Java Version", System.getProperty("java.version")); + + Sentry.init(options -> { + options.setEnableExternalConfiguration(true); + options.setRelease(BuildInfo.getVersionString()); + options.setEnvironment(System.getProperty("os.name")); + options.setTag("Java Version", System.getProperty("java.version")); + }, true); // HACK - temporary solution to "Comparison method violates it's general contract!" crash System.setProperty("java.util.Arrays.useLegacyMergeSort", "true"); diff --git a/forge-gui-desktop/src/test/java/forge/card/ForgeCardMockTestCase.java b/forge-gui-desktop/src/test/java/forge/card/ForgeCardMockTestCase.java index 14fb057c191..c73da4db0a0 100644 --- a/forge-gui-desktop/src/test/java/forge/card/ForgeCardMockTestCase.java +++ b/forge-gui-desktop/src/test/java/forge/card/ForgeCardMockTestCase.java @@ -14,6 +14,7 @@ import forge.util.TextUtil; import org.apache.commons.lang3.StringUtils; import org.mockito.Mockito; import org.powermock.api.mockito.PowerMockito; +import org.powermock.core.classloader.annotations.PowerMockIgnore; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.core.classloader.annotations.SuppressStaticInitializationFor; import org.powermock.modules.testng.PowerMockTestCase; @@ -33,6 +34,7 @@ import java.util.ResourceBundle; ImageCache.class, ImageIO.class, ImageKeys.class, ForgeConstants.class, Localizer.class}) @SuppressStaticInitializationFor({"forge.ImageCache", "forge.localinstance.properties.ForgeConstants"}) +@PowerMockIgnore({"javax.xml.*", "org.xml.sax.*", "com.sun.org.apache.xerces.*", "org.w3c.dom.*", "org.springframework.context.*", "org.apache.log4j.*"}) public class ForgeCardMockTestCase extends PowerMockTestCase { public static final String MOCKED_LOCALISED_STRING = "any localised string"; diff --git a/forge-gui-desktop/src/test/java/forge/gamesimulationtests/BaseGameSimulationTest.java b/forge-gui-desktop/src/test/java/forge/gamesimulationtests/BaseGameSimulationTest.java index eb4e64ccf23..50c85a362ea 100644 --- a/forge-gui-desktop/src/test/java/forge/gamesimulationtests/BaseGameSimulationTest.java +++ b/forge-gui-desktop/src/test/java/forge/gamesimulationtests/BaseGameSimulationTest.java @@ -14,8 +14,8 @@ import forge.model.FModel; import forge.util.Lang; import forge.util.Localizer; import io.sentry.Sentry; -import io.sentry.context.Context; import org.powermock.api.mockito.PowerMockito; +import org.powermock.core.classloader.annotations.PowerMockIgnore; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.core.classloader.annotations.SuppressStaticInitializationFor; import org.testng.Assert; @@ -28,6 +28,7 @@ import java.util.ResourceBundle; ImageCache.class, ImageIO.class, ImageKeys.class, ForgeConstants.class, Localizer.class, Sentry.class, GameLogFormatter.class}) @SuppressStaticInitializationFor({"forge.ImageCache", "forge.localinstance.properties.ForgeConstants"}) +@PowerMockIgnore({"javax.xml.*", "org.xml.sax.*", "com.sun.org.apache.xerces.*", "org.w3c.dom.*", "org.springframework.context.*", "org.apache.log4j.*"}) public class BaseGameSimulationTest extends ForgeCardMockTestCase { @BeforeMethod @@ -36,7 +37,7 @@ public class BaseGameSimulationTest extends ForgeCardMockTestCase { super.initMocks(); PowerMockito.mockStatic(Sentry.class); PowerMockito.mockStatic(GameLogFormatter.class); - PowerMockito.when(Sentry.getContext()).thenReturn(new Context()); + //PowerMockito.when(Sentry.getContext()).thenReturn(new Context()); Lang.createInstance("en-US"); } diff --git a/forge-gui-mobile/src/forge/Forge.java b/forge-gui-mobile/src/forge/Forge.java index 1d77a76c637..8b758a854e3 100644 --- a/forge-gui-mobile/src/forge/Forge.java +++ b/forge-gui-mobile/src/forge/Forge.java @@ -59,7 +59,7 @@ import java.util.List; import java.util.Map; public class Forge implements ApplicationListener { - public static final String CURRENT_VERSION = "1.6.47.001"; + public static final String CURRENT_VERSION = "1.6.49.001"; private static ApplicationListener app = null; static Scene currentScene = null; diff --git a/forge-gui/pom.xml b/forge-gui/pom.xml index 1c7f5297ba9..148b265e81c 100644 --- a/forge-gui/pom.xml +++ b/forge-gui/pom.xml @@ -43,23 +43,23 @@ com.thoughtworks.xstream xstream - 1.4.18 + 1.4.19 io.netty netty-all - 4.1.48.Final + 4.1.71.Final compile org.fourthline.cling cling-support - 2.0.1 + 2.1.2 org.lz4 lz4-java - 1.7.1 + 1.8.0 com.github.raeleus.TenPatch diff --git a/forge-gui/src/main/java/forge/gui/error/BugReporter.java b/forge-gui/src/main/java/forge/gui/error/BugReporter.java index b3965239ad9..7d751505529 100644 --- a/forge-gui/src/main/java/forge/gui/error/BugReporter.java +++ b/forge-gui/src/main/java/forge/gui/error/BugReporter.java @@ -31,7 +31,6 @@ import forge.localinstance.properties.ForgePreferences; import forge.model.FModel; import forge.util.Localizer; import io.sentry.Sentry; -import io.sentry.event.BreadcrumbBuilder; /** * The class ErrorViewer. Enables showing and saving error messages that @@ -71,9 +70,7 @@ public class BugReporter { final StringBuilder sb = new StringBuilder(); if (null != message && !message.isEmpty()) { - Sentry.getContext().recordBreadcrumb( - new BreadcrumbBuilder().setMessage(message).build() - ); + Sentry.addBreadcrumb(message); sb.append(FThreads.debugGetCurrThreadId()).append(" > ").append(message).append("\n"); } @@ -156,9 +153,9 @@ public class BugReporter { public static void sendSentry() { if (exception != null) { - Sentry.capture(exception); + Sentry.captureException(exception); } else if (message !=null) { - Sentry.capture(message); + Sentry.captureMessage(message); } } diff --git a/forge-gui/src/main/java/forge/itemmanager/ColumnDef.java b/forge-gui/src/main/java/forge/itemmanager/ColumnDef.java index 41a5287fa78..e21669c0ea4 100644 --- a/forge-gui/src/main/java/forge/itemmanager/ColumnDef.java +++ b/forge-gui/src/main/java/forge/itemmanager/ColumnDef.java @@ -34,6 +34,8 @@ import forge.itemmanager.ItemColumnConfig.SortState; import forge.model.FModel; import forge.util.CardTranslation; import forge.util.Localizer; +import forge.util.TextUtil; + import org.apache.commons.lang3.StringUtils; import java.math.BigDecimal; @@ -68,9 +70,9 @@ public enum ColumnDef { public Comparable apply(final Entry from) { if (from.getKey() instanceof PaperCard) { String sortableName = ((PaperCard)from.getKey()).getSortableName(); - return sortableName == null ? InventoryItem.toSortableName(from.getKey().getName()) : sortableName; + return sortableName == null ? TextUtil.toSortableName(from.getKey().getName()) : sortableName; } - return InventoryItem.toSortableName(from.getKey().getName()); + return TextUtil.toSortableName(from.getKey().getName()); } }, new Function, Object>() { diff --git a/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java b/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java index 5223ec868f1..ff106a7f5aa 100644 --- a/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java +++ b/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java @@ -638,8 +638,8 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont public List chooseEntitiesForEffect(final FCollectionView optionList, final int min, final int max, final DelayedReveal delayedReveal, final SpellAbility sa, final String title, final Player targetedPlayer, Map params) { // useful details for debugging problems with the mass select logic - Sentry.getContext().addExtra("Card", sa.getCardView().toString()); - Sentry.getContext().addExtra("SpellAbility", sa.toString()); + Sentry.setExtra("Card", sa.getCardView().toString()); + Sentry.setExtra("SpellAbility", sa.toString()); // Human is supposed to read the message and understand from it what to choose if (optionList.isEmpty()) { diff --git a/pom.xml b/pom.xml index 5b4c4d59d39..c67adff9217 100644 --- a/pom.xml +++ b/pom.xml @@ -317,12 +317,12 @@ ch.qos.logback logback-classic - 1.2.9 + 1.2.11 ch.qos.logback logback-core - 1.2.9 + 1.2.11