diff --git a/gemp-lotr/gemp-lotr-async/src/main/java/com/gempukku/lotro/async/ResponseWriter.java b/gemp-lotr/gemp-lotr-async/src/main/java/com/gempukku/lotro/async/ResponseWriter.java index ad0f1c366..dca192beb 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/java/com/gempukku/lotro/async/ResponseWriter.java +++ b/gemp-lotr/gemp-lotr-async/src/main/java/com/gempukku/lotro/async/ResponseWriter.java @@ -12,7 +12,7 @@ public interface ResponseWriter { public void writeFile(File file, Map headers); public void writeHtmlResponse(String html); - public void writeJsonResponse(String html); + public void writeJsonResponse(String json); public void writeByteResponse(byte[] bytes, Map headers); diff --git a/gemp-lotr/gemp-lotr-async/src/main/java/com/gempukku/lotro/async/handler/HallRequestHandler.java b/gemp-lotr/gemp-lotr-async/src/main/java/com/gempukku/lotro/async/handler/HallRequestHandler.java index 298718ebe..4356d0424 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/java/com/gempukku/lotro/async/handler/HallRequestHandler.java +++ b/gemp-lotr/gemp-lotr-async/src/main/java/com/gempukku/lotro/async/handler/HallRequestHandler.java @@ -1,5 +1,6 @@ package com.gempukku.lotro.async.handler; +import com.alibaba.fastjson.JSON; import com.gempukku.lotro.SubscriptionConflictException; import com.gempukku.lotro.SubscriptionExpiredException; import com.gempukku.lotro.async.HttpProcessingException; @@ -65,6 +66,8 @@ public class HallRequestHandler extends LotroServerRequestHandler implements Uri updateHall(request, responseWriter); } else if (uri.equals("/formats/html") && request.method() == HttpMethod.GET) { getFormats(request, responseWriter); + } else if (uri.equals("/errata/json") && request.method() == HttpMethod.GET) { + getErrataInfo(request, responseWriter); } else if (uri.startsWith("/format/") && request.method() == HttpMethod.GET) { getFormat(request, uri.substring(8), responseWriter); } else if (uri.startsWith("/queue/") && request.method() == HttpMethod.POST) { @@ -340,6 +343,14 @@ public class HallRequestHandler extends LotroServerRequestHandler implements Uri } } + private void getErrataInfo(HttpRequest request, ResponseWriter responseWriter) throws CardNotFoundException { + + var errata = _library.getErrata(); + String json = JSON.toJSONString(errata); + + responseWriter.writeJsonResponse(json); + } + private void getHall(HttpRequest request, ResponseWriter responseWriter) { QueryStringDecoder queryDecoder = new QueryStringDecoder(request.uri()); diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/css/gemp-001/deckBuild.css b/gemp-lotr/gemp-lotr-async/src/main/web/css/gemp-001/deckBuild.css index 4af556fb0..afeadbd4d 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/css/gemp-001/deckBuild.css +++ b/gemp-lotr/gemp-lotr-async/src/main/web/css/gemp-001/deckBuild.css @@ -55,6 +55,22 @@ body { font-size: 70%; } +button.navigation-butt { + padding: 0.5em; +} + +.navigation-butt.ui-button-icon-only > .ui-button-text{ + padding: 0; +} + +.navigation-butt.ui-button-icon-only { + width: 25px; +} + +.ui-button-icon-only .ui-button-icon-primary.ui-icon { + margin: auto auto auto -4px; +} + #set { width: 120px; } diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/css/gemp-001/hall.css b/gemp-lotr/gemp-lotr-async/src/main/web/css/gemp-001/hall.css index a111c677a..eb689fc2f 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/css/gemp-001/hall.css +++ b/gemp-lotr/gemp-lotr-async/src/main/web/css/gemp-001/hall.css @@ -172,6 +172,11 @@ button { opacity: 0.3; }*/ +.cultureHint { + position:relative; + top: 4px; +} + #gameHall { overflow-y: scroll; width: calc(100% ); diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/hall.html b/gemp-lotr/gemp-lotr-async/src/main/web/hall.html index 1758aa0a0..867e5535c 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/hall.html +++ b/gemp-lotr/gemp-lotr-async/src/main/web/hall.html @@ -89,7 +89,8 @@ autoOpen:false, closeOnEscape:true, resizable:false, - title:"Card information" + title:"Card information", + closeText: "" }); $("body").click( @@ -97,13 +98,20 @@ var tar = $(event.target); if (tar.hasClass("cardHint")) { - var blueprintId = tar.attr("value"); - var card = new Card(blueprintId, "SPECIAL", "hint", ""); - + var ids = tar.attr("value").split(","); + infoDialog.html(""); infoDialog.html("
"); - var floatCardDiv = $("
"); - floatCardDiv.append(createFullCardDiv(card.imageUrl, card.foil, card.horizontal)); + var floatCardDiv = $("
"); + + var horiz = false; + for(var i = 0; i < ids.length; i++) { + var bpid = ids[i]; + var card = new Card(bpid, "SPECIAL", "hint", ""); + horiz = horiz || card.horizontal; + floatCardDiv.append(createFullCardDiv(card.imageUrl, card.foil, card.horizontal)); + } + infoDialog.append(floatCardDiv); var windowWidth = $(window).width(); @@ -111,14 +119,21 @@ var horSpace = 30; var vertSpace = 45; + var height = 505; + var width = 340; - infoDialog.dialog({title:"Card information"}); - if (card.horizontal) { + infoDialog.dialog({ + title:"Card information", + + }); + if (horiz) { // 500x360 - infoDialog.dialog({width:Math.min(500 + horSpace, windowWidth), height:Math.min(360 + vertSpace, windowHeight)}); + infoDialog.dialog({width:Math.min((height + 10) * ids.length, windowWidth), + height:Math.min((width + 90), windowHeight)}); } else { // 360x500 - infoDialog.dialog({width:Math.min(360 + horSpace, windowWidth), height:Math.min(500 + vertSpace, windowHeight)}); + infoDialog.dialog({width:Math.min((width + 30) * ids.length, windowWidth), + height:Math.min((height + 45), windowHeight)}); } infoDialog.dialog("open"); @@ -325,7 +340,7 @@ -
+
diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/images/cultures/one_ring.png b/gemp-lotr/gemp-lotr-async/src/main/web/images/cultures/one_ring.png new file mode 100644 index 000000000..998998616 Binary files /dev/null and b/gemp-lotr/gemp-lotr-async/src/main/web/images/cultures/one_ring.png differ diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/images/cultures/site.png b/gemp-lotr/gemp-lotr-async/src/main/web/images/cultures/site.png new file mode 100644 index 000000000..de2b656ee Binary files /dev/null and b/gemp-lotr/gemp-lotr-async/src/main/web/images/cultures/site.png differ diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/images/cultures/site.svg b/gemp-lotr/gemp-lotr-async/src/main/web/images/cultures/site.svg new file mode 100644 index 000000000..e5486f188 --- /dev/null +++ b/gemp-lotr/gemp-lotr-async/src/main/web/images/cultures/site.svg @@ -0,0 +1,17 @@ + + + + + + image/svg+xml + + + + + + + + + + + \ No newline at end of file diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/includes/help.html b/gemp-lotr/gemp-lotr-async/src/main/web/includes/help.html index 240d81206..f17c4a036 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/includes/help.html +++ b/gemp-lotr/gemp-lotr-async/src/main/web/includes/help.html @@ -15,6 +15,7 @@
  • Code of Conduct
  • Format Rules
  • League Rules
  • +
  • PC Errata
  • diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/includes/help/pc-errata.html b/gemp-lotr/gemp-lotr-async/src/main/web/includes/help/pc-errata.html new file mode 100644 index 000000000..c406d24a6 --- /dev/null +++ b/gemp-lotr/gemp-lotr-async/src/main/web/includes/help/pc-errata.html @@ -0,0 +1,75 @@ +
    + +
    +

    + All errata are indicated in-game with a red slash in their upper-right-hand corner. Errata that were issued by the Player's Council instead of Decipher also have this slash, but also include the errata date in the lower-left-hand corner of the card. +

    + Each of the released errata have had a full writeup on the PC's thoughts and justifications here on the LOTR-TCG wiki. +

    +

    + Below you can find a quick reference allowing you to quickly compare released errata. +

    +
    +
    +
    \ No newline at end of file diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/communication.js b/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/communication.js index e37fd1664..ee76385ea 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/communication.js +++ b/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/communication.js @@ -684,6 +684,19 @@ var GempLotrCommunication = Class.extend({ }); }, + getErrata:function (callback, errorMap) { + $.ajax({ + type:"GET", + url:this.url + "/hall/errata/json", + cache:false, + data:{ + participantId:getUrlParam("participantId")}, + success:this.deliveryCheck(callback), + error:this.errorCheck(errorMap), + dataType:"json" + }); + }, + addTesterFlag:function (callback, errorMap) { $.ajax({ type:"POST", diff --git a/gemp-lotr/gemp-lotr-common/src/main/java/com/gempukku/lotro/common/JSONDefs.java b/gemp-lotr/gemp-lotr-common/src/main/java/com/gempukku/lotro/common/JSONDefs.java index a5f149818..5d0d5e76b 100644 --- a/gemp-lotr/gemp-lotr-common/src/main/java/com/gempukku/lotro/common/JSONDefs.java +++ b/gemp-lotr/gemp-lotr-common/src/main/java/com/gempukku/lotro/common/JSONDefs.java @@ -64,4 +64,13 @@ public class JSONDefs { public Map SealedTemplates; public Map DraftTemplates; } + + public static class ErrataInfo { + public static String PC_Errata = "PC"; + public String BaseID; + public String Name; + public String LinkText; + public Map ErrataIDs; + } + } diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/game/LotroCardBlueprintLibrary.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/game/LotroCardBlueprintLibrary.java index 6c8a32489..0561f1ea3 100644 --- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/game/LotroCardBlueprintLibrary.java +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/game/LotroCardBlueprintLibrary.java @@ -3,8 +3,10 @@ package com.gempukku.lotro.game; import com.gempukku.lotro.cards.build.InvalidCardDefinitionException; import com.gempukku.lotro.cards.build.LotroCardBlueprintBuilder; import com.gempukku.lotro.common.AppConfig; +import com.gempukku.lotro.common.JSONDefs; import com.gempukku.lotro.game.packs.DefaultSetDefinition; import com.gempukku.lotro.game.packs.SetDefinition; +import com.gempukku.lotro.logic.GameUtils; import com.gempukku.util.JsonUtils; import org.apache.commons.io.IOUtils; import org.apache.log4j.Logger; @@ -91,6 +93,8 @@ public class LotroCardBlueprintLibrary { reloadSets(); reloadMappings(); reloadCards(); + errataMappings = null; + getErrata(); for(var callback : _refreshCallbacks) { callback.Invoke(); @@ -302,6 +306,53 @@ public class LotroCardBlueprintLibrary { } } + private Map errataMappings = null; + public Map getErrata() { + try { + if(errataMappings == null) { + collectionReady.acquire(); + errataMappings = new HashMap<>(); + for (String id : _blueprints.keySet()) { + var parts = id.split("_"); + int setID = Integer.parseInt(parts[0]); + String cardID = parts[1]; + JSONDefs.ErrataInfo card = null; + String base = id; + if(setID >= 50 && setID <= 69) { + base = "" + (setID - 50) + "_" + cardID; + } + else if(setID >= 70 && setID <= 89) { + base = "" + (setID - 70) + "_" + cardID; + } + else if(setID >= 150 && setID <= 199) { + base = "" + (setID - 50) + "_" + cardID; + } + else + continue; + + if(errataMappings.containsKey(base)) { + card = errataMappings.get(base); + } + else { + card = new JSONDefs.ErrataInfo(); + card.BaseID = base; + card.Name = GameUtils.getFullName(_blueprints.get(base)); + card.LinkText = GameUtils.getDeluxeCardLink(id, _blueprints.get(base)); + card.ErrataIDs = new HashMap<>(); + errataMappings.put(base, card); + } + + card.ErrataIDs.put(JSONDefs.ErrataInfo.PC_Errata, id); + } + + collectionReady.release(); + } + return errataMappings; + } catch (InterruptedException exp) { + throw new RuntimeException("LotroCardBlueprintLibrary.getErrata() interrupted: ", exp); + } + } + public boolean hasAlternateInSet(String blueprintId, int setNo) { try { collectionReady.acquire(); diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/GameUtils.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/GameUtils.java index 76ba97ef4..87af021ca 100644 --- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/GameUtils.java +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/GameUtils.java @@ -116,6 +116,24 @@ public class GameUtils { return "
    " + (blueprint.isUnique() ? "·" : "") + GameUtils.getFullName(blueprint) + "
    "; } + public static String getDeluxeCardLink(String blueprintId, LotroCardBlueprint blueprint) { + var culture = blueprint.getCulture(); + var cultureString = ""; + if(culture == null) { + if (blueprint.getTitle().equals("The One Ring")) { + cultureString = getCultureImage(culture, "one_ring"); + } + else { + cultureString = getCultureImage(culture, "site"); + } + } + else { + cultureString = getCultureImage(culture, null); + } + return "
    " + cultureString + + (blueprint.isUnique() ? "·" : "") + " " + GameUtils.getFullName(blueprint) + "
    "; + } + public static String getCultureImage(String cultureName) { Culture culture = Culture.findCulture(cultureName); if(culture == null) @@ -124,6 +142,13 @@ public class GameUtils { return getCultureImage(culture); } + public static String getCultureImage(Culture culture, String override) { + if(override == null || override.isEmpty()) { + override = culture.toString().toLowerCase(); + } + return ""; + } + public static String getCultureImage(Culture culture) { return " " + culture.getHumanReadable() + "";