From 996a93aa1e5097b636b91af92b8c9445bb053cf6 Mon Sep 17 00:00:00 2001 From: Christoph Prenner Date: Thu, 19 Feb 2026 13:53:03 +0100 Subject: [PATCH 1/4] Feature 208: - added drag icon to cards created in Ready and Torpor - added updateRegion Method in DeckserverRemote that swapes places for 2 cards in a region - added jquery drag and drop to li items in Ready/Torpor region in the ds.js - added min touch punch js to main.jsp --- .../net/deckserver/dwr/DeckserverRemote.java | 12 ++++++++ src/main/webapp/WEB-INF/jsps/game/card.jsp | 2 ++ src/main/webapp/WEB-INF/main.jsp | 1 + src/main/webapp/js/ds.js | 28 +++++++++++++++++++ .../webapp/js/jquery.ui.touch-punch.min.js | 11 ++++++++ 5 files changed, 54 insertions(+) create mode 100644 src/main/webapp/js/jquery.ui.touch-punch.min.js diff --git a/src/main/java/net/deckserver/dwr/DeckserverRemote.java b/src/main/java/net/deckserver/dwr/DeckserverRemote.java index 2f4b83c2..f313687b 100644 --- a/src/main/java/net/deckserver/dwr/DeckserverRemote.java +++ b/src/main/java/net/deckserver/dwr/DeckserverRemote.java @@ -6,12 +6,16 @@ import net.deckserver.dwr.creators.UpdateFactory; import net.deckserver.dwr.model.GameModel; import net.deckserver.dwr.model.GameView; +import net.deckserver.dwr.model.JolGame; import net.deckserver.dwr.model.PlayerModel; import net.deckserver.game.enums.GameFormat; +import net.deckserver.game.enums.RegionType; import net.deckserver.services.*; import net.deckserver.storage.json.deck.Deck; import net.deckserver.storage.json.deck.ExtendedDeck; +import net.deckserver.storage.json.game.CardData; import net.deckserver.storage.json.game.ChatData; +import net.deckserver.storage.json.game.RegionData; import net.deckserver.storage.json.system.DeckInfo; import net.deckserver.storage.json.system.GameHistory; import net.deckserver.storage.json.system.PlayerResult; @@ -411,6 +415,14 @@ public String exportPastGamesAsCsv() throws IOException { return writer.toString(); } + public Map updateRegion(String gameName, String player, String region, int oldPos, int newPos) { + JolGame game = GameService.getGameByName(gameName); + RegionData playerRegion = game.data().getPlayerRegion(player, RegionType.valueOf(region)); + LinkedList cards = (LinkedList) playerRegion.getCards(); + Collections.swap(cards, oldPos, newPos); + return UpdateFactory.getUpdate(); + } + private GameView getView(String name) { String player = getPlayer(request); return getModel(name).getView(player); diff --git a/src/main/webapp/WEB-INF/jsps/game/card.jsp b/src/main/webapp/WEB-INF/jsps/game/card.jsp index f9e9380f..79088510 100755 --- a/src/main/webapp/WEB-INF/jsps/game/card.jsp +++ b/src/main/webapp/WEB-INF/jsps/game/card.jsp @@ -46,6 +46,7 @@ // Red: hasBlood || hasCapacity String counterStyle = (cardSummary.hasLife() && RegionType.OTHER_VISIBLE_REGIONS.contains(region)) ? "text-bg-success" : ((cardSummary.hasBlood() || hasCapacity) ? "text-bg-danger" : "text-bg-secondary"); String regionStyle = region == RegionType.TORPOR ? "opacity-75" : ""; + boolean regionDragDrop = region == RegionType.TORPOR || region == RegionType.READY ? true : false; String contestedStyle = contested ? "bg-warning-subtle" : ""; String counterText = counters + (capacity > 0 ? " / " + capacity : ""); String attributes = cardDetail.buildAttributes(region, index, true); @@ -130,4 +131,5 @@ + \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/main.jsp b/src/main/webapp/WEB-INF/main.jsp index 1fbd7d1f..30114b65 100755 --- a/src/main/webapp/WEB-INF/main.jsp +++ b/src/main/webapp/WEB-INF/main.jsp @@ -89,6 +89,7 @@ + diff --git a/src/main/webapp/js/ds.js b/src/main/webapp/js/ds.js index 4fb64f7a..82ac3d85 100644 --- a/src/main/webapp/js/ds.js +++ b/src/main/webapp/js/ds.js @@ -1301,6 +1301,34 @@ function loadGame(data) { addCardTooltips("#hand"); } + // drag and drop + $(".region").each(function (index, region) { + let regionName = region.id.substring(2); + if(region.id.indexOf("READY")>-1 || region.id.indexOf("TORPOR")>-1) { + $(region).sortable({ + handle: ".bi-grip-vertical", + start: function (event, ui) { + ui.item.parent("ol").children("li").each(function (index, li) { + if(li===ui.item[0]) { + ui.item.attr("oldPos", index); + } + }); + }, + stop: function (event, ui) { + let playerName = ui.item.closest(".player").attr("data-player"); + let newPos; + ui.item.parent("ol").children("li").each(function (index, li) { + if(li===ui.item[0]) { + newPos = index; + } + }); + DS.updateRegion(data.name, playerName, regionName, ui.item.attr("oldPos"), newPos, {callback: processData, errorHandler: errorhandler}); + } + }); + $(region).disableSelection(); + } + }); + // Setup polling if (refresher) clearTimeout(refresher); if (data.refresh > 0 || fetchFullLog) { diff --git a/src/main/webapp/js/jquery.ui.touch-punch.min.js b/src/main/webapp/js/jquery.ui.touch-punch.min.js new file mode 100644 index 00000000..31272ce6 --- /dev/null +++ b/src/main/webapp/js/jquery.ui.touch-punch.min.js @@ -0,0 +1,11 @@ +/*! + * jQuery UI Touch Punch 0.2.3 + * + * Copyright 2011–2014, Dave Furfero + * Dual licensed under the MIT or GPL Version 2 licenses. + * + * Depends: + * jquery.ui.widget.js + * jquery.ui.mouse.js + */ +!function(a){function f(a,b){if(!(a.originalEvent.touches.length>1)){a.preventDefault();var c=a.originalEvent.changedTouches[0],d=document.createEvent("MouseEvents");d.initMouseEvent(b,!0,!0,window,1,c.screenX,c.screenY,c.clientX,c.clientY,!1,!1,!1,!1,0,null),a.target.dispatchEvent(d)}}if(a.support.touch="ontouchend"in document,a.support.touch){var e,b=a.ui.mouse.prototype,c=b._mouseInit,d=b._mouseDestroy;b._touchStart=function(a){var b=this;!e&&b._mouseCapture(a.originalEvent.changedTouches[0])&&(e=!0,b._touchMoved=!1,f(a,"mouseover"),f(a,"mousemove"),f(a,"mousedown"))},b._touchMove=function(a){e&&(this._touchMoved=!0,f(a,"mousemove"))},b._touchEnd=function(a){e&&(f(a,"mouseup"),f(a,"mouseout"),this._touchMoved||f(a,"click"),e=!1)},b._mouseInit=function(){var b=this;b.element.bind({touchstart:a.proxy(b,"_touchStart"),touchmove:a.proxy(b,"_touchMove"),touchend:a.proxy(b,"_touchEnd")}),c.call(b)},b._mouseDestroy=function(){var b=this;b.element.unbind({touchstart:a.proxy(b,"_touchStart"),touchmove:a.proxy(b,"_touchMove"),touchend:a.proxy(b,"_touchEnd")}),d.call(b)}}}(jQuery); \ No newline at end of file From ee5143bd594e194f71289f649b2f6b05cc7ede77 Mon Sep 17 00:00:00 2001 From: Christoph Prenner Date: Fri, 20 Feb 2026 12:27:02 +0100 Subject: [PATCH 2/4] Feature 208: - added drop-zone to ol in cards.jsp - rename updateRegion to swapCardsInRegion - added detach card to Region - added attach card to card - added more sortable features to ds.js. Drop Zone allows li's to get dropped on ol - added addCard to RegionData with position --- .../net/deckserver/dwr/DeckserverRemote.java | 54 +++++++++++++++++- .../storage/json/game/RegionData.java | 25 ++++++++ src/main/webapp/WEB-INF/jsps/game/card.jsp | 6 +- src/main/webapp/WEB-INF/jsps/game/region.jsp | 2 +- src/main/webapp/js/ds.js | 57 ++++++++++++++----- 5 files changed, 123 insertions(+), 21 deletions(-) diff --git a/src/main/java/net/deckserver/dwr/DeckserverRemote.java b/src/main/java/net/deckserver/dwr/DeckserverRemote.java index f313687b..1610c227 100644 --- a/src/main/java/net/deckserver/dwr/DeckserverRemote.java +++ b/src/main/java/net/deckserver/dwr/DeckserverRemote.java @@ -415,11 +415,43 @@ public String exportPastGamesAsCsv() throws IOException { return writer.toString(); } - public Map updateRegion(String gameName, String player, String region, int oldPos, int newPos) { + public Map swapCardsInRegion(String gameName, String player, String region, int oldPos, int newPos) { + //get Game & Region & Cards JolGame game = GameService.getGameByName(gameName); RegionData playerRegion = game.data().getPlayerRegion(player, RegionType.valueOf(region)); LinkedList cards = (LinkedList) playerRegion.getCards(); - Collections.swap(cards, oldPos, newPos); + //swap pos in collection + Collections.swap(cards, oldPos-1, newPos); + //reload State + doReload(gameName); + return UpdateFactory.getUpdate(); + } + + public Map detachRegionCard(String gameName, String player, String region, String oldPos, int newPos) { + //get Game & Region & Cards + JolGame game = GameService.getGameByName(gameName); + RegionData playerRegion = game.data().getPlayerRegion(player, RegionType.valueOf(region)); + LinkedList cards = (LinkedList) playerRegion.getCards(); + //get Card + CardData cardData = getCard(cards, oldPos); + //detach Card + playerRegion.addCard(cardData, newPos); + //reload State + doReload(gameName); + return UpdateFactory.getUpdate(); + } + + public Map attachRegionCard(String gameName, String player, String region, String oldPos, String newPos) { + //get Game & Region & Cards + JolGame game = GameService.getGameByName(gameName); + RegionData playerRegion = game.data().getPlayerRegion(player, RegionType.valueOf(region)); + LinkedList cards = (LinkedList) playerRegion.getCards(); + //get card + CardData cardData = getCard(cards, oldPos); + //attach Card + getCard(cards, newPos).add(cardData, true); + //reload State + doReload(gameName); return UpdateFactory.getUpdate(); } @@ -432,4 +464,22 @@ private GameModel getModel(String name) { return JolAdmin.getGameModel(name); } + private void doReload(String name) { + //reload State + getModel(name).doReload(true,false,false); + } + + private CardData getCard(LinkedList cards, String pos) { + LinkedList targetCards = cards; + if(pos.contains(".")){ + String[] split = pos.split("\\."); + int lastCard = Integer.valueOf(split[split.length-1]); + for(int i = 0; i < split.length-1; i++) { + targetCards = targetCards.get(Integer.valueOf(split[i])-1).getCards(); + } + return targetCards.get(lastCard-1); + } else { + return cards.get(Integer.valueOf(pos)-1); + } + } } diff --git a/src/main/java/net/deckserver/storage/json/game/RegionData.java b/src/main/java/net/deckserver/storage/json/game/RegionData.java index 6dc2cb98..39cd7bda 100644 --- a/src/main/java/net/deckserver/storage/json/game/RegionData.java +++ b/src/main/java/net/deckserver/storage/json/game/RegionData.java @@ -72,6 +72,31 @@ public void addCard(CardData card, boolean top) { card.setParent(null); card.setRegion(this); } + public void addCard(CardData card, int pos) { + // Remove from parent first, if it exists + if (card.getParent() != null) { + card.getParent().remove(card); + } + // Remove from region if it exists + if (card.getRegion() != null) { + card.getRegion().removeCard(card); + } + // Add new Card to correct position + LinkedList newCardsOrder = new LinkedList<>(); + for(int i = 0; i 0 ? " / " + capacity : ""); String attributes = cardDetail.buildAttributes(region, index, true); @@ -57,7 +57,7 @@ request.setAttribute("cards", cards); %>
  • onclick="<%= showAction %>" - class="list-group-item d-flex justify-content-between align-items-baseline px-2 pt-2 pb-1 <%= regionStyle%> <%= shadowStyle %> <%= contestedStyle %>"> + class="list-group-item d-flex justify-content-between align-items-baseline px-2 pt-2 pb-1 dropable-item <%= regionStyle%> <%= shadowStyle %> <%= contestedStyle %>">
    @@ -103,7 +103,7 @@
    -
      +
        diff --git a/src/main/webapp/WEB-INF/jsps/game/region.jsp b/src/main/webapp/WEB-INF/jsps/game/region.jsp index ef50b609..02561d30 100755 --- a/src/main/webapp/WEB-INF/jsps/game/region.jsp +++ b/src/main/webapp/WEB-INF/jsps/game/region.jsp @@ -42,7 +42,7 @@
          + class="region sortable1 list-group list-group-flush list-group-numbered drop-zone<%= regionStyle %> collapse <%= show %>"> diff --git a/src/main/webapp/js/ds.js b/src/main/webapp/js/ds.js index 82ac3d85..c8679f11 100644 --- a/src/main/webapp/js/ds.js +++ b/src/main/webapp/js/ds.js @@ -1302,31 +1302,58 @@ function loadGame(data) { } // drag and drop - $(".region").each(function (index, region) { + //add sortable to highest order list and connect to sublists + $(".sortable1").each(function (index, region) { let regionName = region.id.substring(2); - if(region.id.indexOf("READY")>-1 || region.id.indexOf("TORPOR")>-1) { + if(region.id.indexOf("READY")>-1) { $(region).sortable({ + connectWith: ".sortable1, .sortable2, .drop-zone", handle: ".bi-grip-vertical", - start: function (event, ui) { - ui.item.parent("ol").children("li").each(function (index, li) { - if(li===ui.item[0]) { - ui.item.attr("oldPos", index); - } - }); - }, + dropOnEmpty: true, stop: function (event, ui) { let playerName = ui.item.closest(".player").attr("data-player"); let newPos; - ui.item.parent("ol").children("li").each(function (index, li) { - if(li===ui.item[0]) { - newPos = index; - } - }); - DS.updateRegion(data.name, playerName, regionName, ui.item.attr("oldPos"), newPos, {callback: processData, errorHandler: errorhandler}); + if(ui.item.parent("ol").hasClass("region")) { + ui.item.parent("ol").children("li").each(function (index, li) { + if(li===ui.item[0]) { + newPos = index; + } + }); + DS.swapCardsInRegion(data.name, playerName, regionName, ui.item.attr("data-coordinates"), newPos, {callback: processData, errorHandler: errorhandler}); + } else { + DS.attachRegionCard(data.name, playerName, regionName, ui.item.attr("data-coordinates"), ui.item.parents("li").attr("data-coordinates"), {callback: processData, errorHandler: errorhandler}); + } } }); $(region).disableSelection(); } + //add drag and drop to all sub lists and connect to parent list + $(".sortable2").sortable({ + handle: ".bi-grip-vertical", + dropOnEmpty: true, + connectWith: ".sortable1, .drop-zone, .sortable2 ", + stop: function (event, ui) { + let playerName = ui.item.closest(".player").attr("data-player"); + let newPos; + ui.item.parent("ol").children("li").each(function (index, li) { + if(li===ui.item[0]) { + newPos = index; + } + }); + DS.detachRegionCard(data.name, playerName, "READY", ui.item.attr("data-coordinates"), newPos, {callback: processData, errorHandler: errorhandler}); + } + }); + $(".sortable2").disableSelection(); + //create a drop zone + $(".drop-zone").droppable({ + accept: ".dropable-item", + }); + $(".drop-zone").sortable({ + handle: ".bi-grip-vertical", + connectWith: '.drop-zone, .sortable1, .sortable2', + }); + $(".drop-zone").disableSelection(); + }); // Setup polling From 865751f325bb108a12861372acee67926eb43ca8 Mon Sep 17 00:00:00 2001 From: Christoph Prenner Date: Fri, 20 Feb 2026 13:39:02 +0100 Subject: [PATCH 3/4] - added comments - added player restriction to drag and drop --- .../net/deckserver/dwr/DeckserverRemote.java | 48 +++++++++++++----- src/main/webapp/js/ds.js | 49 +++++++++++++------ 2 files changed, 71 insertions(+), 26 deletions(-) diff --git a/src/main/java/net/deckserver/dwr/DeckserverRemote.java b/src/main/java/net/deckserver/dwr/DeckserverRemote.java index 1610c227..12ee2daf 100644 --- a/src/main/java/net/deckserver/dwr/DeckserverRemote.java +++ b/src/main/java/net/deckserver/dwr/DeckserverRemote.java @@ -415,6 +415,15 @@ public String exportPastGamesAsCsv() throws IOException { return writer.toString(); } + /** + * Swap two cards in a given Region + * @param gameName - Name where cards should be swapped + * @param player - Player whom card shall be swapped + * @param region - Region where the cards shall be swapped + * @param oldPos - Old Position of the Card + * @param newPos - New Positon of the Card + * @return Map with View to Update + */ public Map swapCardsInRegion(String gameName, String player, String region, int oldPos, int newPos) { //get Game & Region & Cards JolGame game = GameService.getGameByName(gameName); @@ -423,10 +432,19 @@ public Map swapCardsInRegion(String gameName, String player, Str //swap pos in collection Collections.swap(cards, oldPos-1, newPos); //reload State - doReload(gameName); - return UpdateFactory.getUpdate(); - } - + return doReload(gameName); + } + + /** + * Detach a Card from another card to a Region + * + * @param gameName - Name where cards should be detached + * @param player - Player whom card shall be detached + * @param region - Region where the cards shall be detached + * @param oldPos - Old Position of the Card + * @param newPos - New Positon of the Card + * @return Map with View to Update + */ public Map detachRegionCard(String gameName, String player, String region, String oldPos, int newPos) { //get Game & Region & Cards JolGame game = GameService.getGameByName(gameName); @@ -437,10 +455,18 @@ public Map detachRegionCard(String gameName, String player, Stri //detach Card playerRegion.addCard(cardData, newPos); //reload State - doReload(gameName); - return UpdateFactory.getUpdate(); - } - + return doReload(gameName); + } + + /** + * Attach Card to another Card in a given Region + * @param gameName - Name where cards should be attached + * @param player - Player whom card shall be attached + * @param region - Region where the cards shall be attached + * @param oldPos - Old Position of the Card + * @param newPos - New Positon of the Card + * @return Map with View to Update + */ public Map attachRegionCard(String gameName, String player, String region, String oldPos, String newPos) { //get Game & Region & Cards JolGame game = GameService.getGameByName(gameName); @@ -451,8 +477,7 @@ public Map attachRegionCard(String gameName, String player, Stri //attach Card getCard(cards, newPos).add(cardData, true); //reload State - doReload(gameName); - return UpdateFactory.getUpdate(); + return doReload(gameName); } private GameView getView(String name) { @@ -464,9 +489,10 @@ private GameModel getModel(String name) { return JolAdmin.getGameModel(name); } - private void doReload(String name) { + public Map doReload(String name) { //reload State getModel(name).doReload(true,false,false); + return UpdateFactory.getUpdate(); } private CardData getCard(LinkedList cards, String pos) { diff --git a/src/main/webapp/js/ds.js b/src/main/webapp/js/ds.js index c8679f11..0313e27b 100644 --- a/src/main/webapp/js/ds.js +++ b/src/main/webapp/js/ds.js @@ -1303,6 +1303,7 @@ function loadGame(data) { // drag and drop //add sortable to highest order list and connect to sublists + let startPlayer; $(".sortable1").each(function (index, region) { let regionName = region.id.substring(2); if(region.id.indexOf("READY")>-1) { @@ -1310,18 +1311,25 @@ function loadGame(data) { connectWith: ".sortable1, .sortable2, .drop-zone", handle: ".bi-grip-vertical", dropOnEmpty: true, + start: function (event, ui) { + startPlayer = ui.item.closest(".player").attr("data-player"); + }, stop: function (event, ui) { let playerName = ui.item.closest(".player").attr("data-player"); - let newPos; - if(ui.item.parent("ol").hasClass("region")) { - ui.item.parent("ol").children("li").each(function (index, li) { - if(li===ui.item[0]) { - newPos = index; - } - }); - DS.swapCardsInRegion(data.name, playerName, regionName, ui.item.attr("data-coordinates"), newPos, {callback: processData, errorHandler: errorhandler}); + if(playerName==startPlayer) { + let newPos; + if(ui.item.parent("ol").hasClass("region")) { + ui.item.parent("ol").children("li").each(function (index, li) { + if(li===ui.item[0]) { + newPos = index; + } + }); + DS.swapCardsInRegion(data.name, playerName, regionName, ui.item.attr("data-coordinates"), newPos, {callback: processData, errorHandler: errorhandler}); + } else { + DS.attachRegionCard(data.name, playerName, regionName, ui.item.attr("data-coordinates"), ui.item.parents("li").attr("data-coordinates"), {callback: processData, errorHandler: errorhandler}); + } } else { - DS.attachRegionCard(data.name, playerName, regionName, ui.item.attr("data-coordinates"), ui.item.parents("li").attr("data-coordinates"), {callback: processData, errorHandler: errorhandler}); + DS.doReload(data.name, {callback: processData, errorHandler: errorhandler}); } } }); @@ -1332,15 +1340,26 @@ function loadGame(data) { handle: ".bi-grip-vertical", dropOnEmpty: true, connectWith: ".sortable1, .drop-zone, .sortable2 ", + start: function (event, ui) { + startPlayer = ui.item.closest(".player").attr("data-player"); + }, stop: function (event, ui) { let playerName = ui.item.closest(".player").attr("data-player"); - let newPos; - ui.item.parent("ol").children("li").each(function (index, li) { - if(li===ui.item[0]) { - newPos = index; + if(playerName==startPlayer) { + let newPos; + if(ui.item.parent("ol").hasClass("region")) { + ui.item.parent("ol").children("li").each(function (index, li) { + if(li===ui.item[0]) { + newPos = index; + } + }); + DS.detachRegionCard(data.name, playerName, "READY", ui.item.attr("data-coordinates"), newPos, {callback: processData, errorHandler: errorhandler}); + } else { + DS.attachRegionCard(data.name, playerName, "READY", ui.item.attr("data-coordinates"), ui.item.parents("li").attr("data-coordinates"), {callback: processData, errorHandler: errorhandler}); } - }); - DS.detachRegionCard(data.name, playerName, "READY", ui.item.attr("data-coordinates"), newPos, {callback: processData, errorHandler: errorhandler}); + } else { + DS.doReload(data.name, {callback: processData, errorHandler: errorhandler}); + } } }); $(".sortable2").disableSelection(); From 60b6221315a3b0fb5841d9dcddbdb593ebfb663b Mon Sep 17 00:00:00 2001 From: Christoph Prenner Date: Fri, 20 Feb 2026 17:04:41 +0100 Subject: [PATCH 4/4] - added Chat Msg to drag and drop --- src/main/java/net/deckserver/dwr/DeckserverRemote.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/main/java/net/deckserver/dwr/DeckserverRemote.java b/src/main/java/net/deckserver/dwr/DeckserverRemote.java index 12ee2daf..ed8de068 100644 --- a/src/main/java/net/deckserver/dwr/DeckserverRemote.java +++ b/src/main/java/net/deckserver/dwr/DeckserverRemote.java @@ -429,8 +429,10 @@ public Map swapCardsInRegion(String gameName, String player, Str JolGame game = GameService.getGameByName(gameName); RegionData playerRegion = game.data().getPlayerRegion(player, RegionType.valueOf(region)); LinkedList cards = (LinkedList) playerRegion.getCards(); + CardData cardData = getCard(cards, String.valueOf(oldPos)); //swap pos in collection Collections.swap(cards, oldPos-1, newPos); + sendChatMessage(game.id(), player, cardData.getName(), String.valueOf(oldPos), String.valueOf(newPos+1), region); //reload State return doReload(gameName); } @@ -454,6 +456,7 @@ public Map detachRegionCard(String gameName, String player, Stri CardData cardData = getCard(cards, oldPos); //detach Card playerRegion.addCard(cardData, newPos); + sendChatMessage(game.id(), player, cardData.getName(), oldPos, String.valueOf(newPos+1), region); //reload State return doReload(gameName); } @@ -476,6 +479,7 @@ public Map attachRegionCard(String gameName, String player, Stri CardData cardData = getCard(cards, oldPos); //attach Card getCard(cards, newPos).add(cardData, true); + sendChatMessage(game.id(), player, cardData.getName(), oldPos, newPos, region); //reload State return doReload(gameName); } @@ -508,4 +512,8 @@ private CardData getCard(LinkedList cards, String pos) { return cards.get(Integer.valueOf(pos)-1); } } + + private void sendChatMessage(String id, String playerName, String cardName, String oldPos, String newPos, String region) { + ChatService.sendMessage(id, playerName, playerName + " moves "+cardName+" from "+oldPos+" to "+newPos+" of their "+region+" region."); + } }