diff --git a/pom.xml b/pom.xml index 9f9c4d6..d914c2d 100644 --- a/pom.xml +++ b/pom.xml @@ -68,6 +68,11 @@ jline-builtins 3.26.3 + + org.jline + jline-terminal-jansi + 3.26.3 + diff --git a/src/main/java/it/polimi/ingsw/gc14/ClientLauncherTUI.java b/src/main/java/it/polimi/ingsw/gc14/ClientLauncherTUI.java index 39b7bf3..80656cc 100644 --- a/src/main/java/it/polimi/ingsw/gc14/ClientLauncherTUI.java +++ b/src/main/java/it/polimi/ingsw/gc14/ClientLauncherTUI.java @@ -15,6 +15,8 @@ import org.jline.terminal.Terminal; import org.jline.terminal.TerminalBuilder; import java.io.IOException; +import java.io.PrintStream; +import java.nio.charset.StandardCharsets; import static org.jline.builtins.Completers.TreeCompleter.node; @@ -35,7 +37,12 @@ public class ClientLauncherTUI { */ public void main() throws InterruptedException { try { - terminal = TerminalBuilder.builder().system(true).build(); + System.setOut(new PrintStream(System.out, true, StandardCharsets.UTF_8)); + System.setErr(new PrintStream(System.err, true, StandardCharsets.UTF_8)); + terminal = TerminalBuilder.builder() + .system(true) + .encoding(StandardCharsets.UTF_8) + .build(); } catch (IOException e) { System.err.println("Could not initialise terminal: " + e.getMessage()); return; @@ -149,6 +156,7 @@ public class ClientLauncherTUI { node("totem"), node("skip"), node("render"), + node("help"), node("rematch"), node("quit") ); @@ -180,6 +188,7 @@ public class ClientLauncherTUI { } case "skip" -> controller.skipTurn(); case "render" -> handleRender(parts); + case "help" -> view.renderHelp(); case "rematch" -> { if (controller.miniModel == null || !controller.miniModel.currentState.getGameStage().equals(GameStages.ENDED)) { diff --git a/src/main/java/it/polimi/ingsw/gc14/Model/Cards/BuildingCard.java b/src/main/java/it/polimi/ingsw/gc14/Model/Cards/BuildingCard.java index 220fd5b..9d3b3c9 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Model/Cards/BuildingCard.java +++ b/src/main/java/it/polimi/ingsw/gc14/Model/Cards/BuildingCard.java @@ -274,6 +274,6 @@ public class BuildingCard extends PlayableCard implements Cloneable , BuildingEf */ @Override public String toString() { - return ":" + " ID:" + String.valueOf(getEffectId())+ " 🍗:"+String.valueOf(getPrice())+" \uD83C\uDFC5:"+String.valueOf(getPrestigeValue()); + return ":" + " ID:" + String.valueOf(getEffectId())+ " \uD83C\uDF56:"+String.valueOf(getPrice())+" \uD83C\uDFC5:"+String.valueOf(getPrestigeValue()); } } \ No newline at end of file diff --git a/src/main/java/it/polimi/ingsw/gc14/Model/Cards/TribeCards/Characters/Inventor.java b/src/main/java/it/polimi/ingsw/gc14/Model/Cards/TribeCards/Characters/Inventor.java index 7a5342a..0fa8003 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Model/Cards/TribeCards/Characters/Inventor.java +++ b/src/main/java/it/polimi/ingsw/gc14/Model/Cards/TribeCards/Characters/Inventor.java @@ -93,7 +93,7 @@ public class Inventor extends Character { */ @Override public String toString() { - return super.toString() + " I_ID:" + String.valueOf(icon); + return super.toString() + "ID:" + String.valueOf(icon); } /** diff --git a/src/main/java/it/polimi/ingsw/gc14/Model/Cards/TribeCards/Characters/Shaman.java b/src/main/java/it/polimi/ingsw/gc14/Model/Cards/TribeCards/Characters/Shaman.java index b0c4409..b3778e2 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Model/Cards/TribeCards/Characters/Shaman.java +++ b/src/main/java/it/polimi/ingsw/gc14/Model/Cards/TribeCards/Characters/Shaman.java @@ -86,7 +86,7 @@ public class Shaman extends Character { */ @Override public String toString() { - return super.toString() + " " + "🌟".repeat(icon); + return super.toString() + "🌟:" + icon; } /** @@ -102,7 +102,7 @@ public class Shaman extends Character { */ @Override public String toStringBoard() { - return super.toStringBoard() + " " + "🌟".repeat(icon); + return super.toStringBoard() + "🌟:" + icon; } /** diff --git a/src/main/java/it/polimi/ingsw/gc14/Model/Cards/TribeCards/EventCard.java b/src/main/java/it/polimi/ingsw/gc14/Model/Cards/TribeCards/EventCard.java index 2a3329b..4b2e87d 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Model/Cards/TribeCards/EventCard.java +++ b/src/main/java/it/polimi/ingsw/gc14/Model/Cards/TribeCards/EventCard.java @@ -89,7 +89,7 @@ public abstract class EventCard extends TribeCard { */ @Override public String toStringBoard() { - return super.toString() + " " + type.toString(); + return super.toStringBoard() + " " + type.toString(); } /** diff --git a/src/main/java/it/polimi/ingsw/gc14/Model/Cards/TribeCards/Events/Hunt.java b/src/main/java/it/polimi/ingsw/gc14/Model/Cards/TribeCards/Events/Hunt.java index 2f9be07..67eed2a 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Model/Cards/TribeCards/Events/Hunt.java +++ b/src/main/java/it/polimi/ingsw/gc14/Model/Cards/TribeCards/Events/Hunt.java @@ -96,7 +96,7 @@ public class Hunt extends EventCard { */ @Override public String toStringBoard() { - return super.toStringBoard()+" 1F+"+prestigeMultiplier+"PP"+" X N Hunter"; + return super.toStringBoard()+" 1\uD83C\uDF56+"+prestigeMultiplier+"\uD83C\uDFC5"+" X N Hunter"; } } diff --git a/src/main/java/it/polimi/ingsw/gc14/Model/GamePackage/CurrentState.java b/src/main/java/it/polimi/ingsw/gc14/Model/GamePackage/CurrentState.java index fa369c0..81b68a8 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Model/GamePackage/CurrentState.java +++ b/src/main/java/it/polimi/ingsw/gc14/Model/GamePackage/CurrentState.java @@ -201,11 +201,9 @@ public class CurrentState implements Serializable { } @Override public String toString(){ - var table= new AsciiTable(BorderStyle.ROUNDED,6); + var table= new AsciiTable(BorderStyle.ROUNDED,4); Listheader= new ArrayList<>(); header.add("Player"); - header.add("NUpper"); - header.add("NLower"); header.add("Round"); header.add("Era"); header.add("GameStage"); @@ -213,8 +211,6 @@ public class CurrentState implements Serializable { table.addSeparator(); Listvalues= new ArrayList<>(); values.add(player.getUserName()); - values.add(Integer.toString(NUpper)); - values.add(Integer.toString(NLower)); values.add(Integer.toString(round)); values.add(Integer.toString(Era)); values.add(GameStage.toString()); diff --git a/src/main/java/it/polimi/ingsw/gc14/Model/Orders/Order2.java b/src/main/java/it/polimi/ingsw/gc14/Model/Orders/Order2.java index 7555247..139b299 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Model/Orders/Order2.java +++ b/src/main/java/it/polimi/ingsw/gc14/Model/Orders/Order2.java @@ -72,9 +72,9 @@ public class Order2 extends OrderLogicCard { { try { if(playerList.get(i).played) - stringUp.add(" "); + stringUp.add(""); else - stringUp.add(i+". "+playerList.get(i).player.getUserName()); + stringUp.add(playerList.get(i).player.getUserName()); } catch (IndexOutOfBoundsException e) { stringUp.add(""); @@ -83,9 +83,9 @@ public class Order2 extends OrderLogicCard { table.addRow(stringUp); List stringList=new ArrayList<>(); - stringList.add("+1🍗"); - stringList.add("-1🍗 / -2\uD83C\uDFC5"); + stringList.add("+1\uD83C\uDF56"); + stringList.add("-1\uD83C\uDF56/-2\uD83C\uDFC5"); table.addRow(stringList); - return "TURN ORDER\n" + table.build() + "\n"; + return table.build() + "\n"; } } \ No newline at end of file diff --git a/src/main/java/it/polimi/ingsw/gc14/Model/Orders/Order3.java b/src/main/java/it/polimi/ingsw/gc14/Model/Orders/Order3.java index 0ac675d..cc4cda3 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Model/Orders/Order3.java +++ b/src/main/java/it/polimi/ingsw/gc14/Model/Orders/Order3.java @@ -75,9 +75,9 @@ public class Order3 extends OrderLogicCard { { try { if(playerList.get(i).played) - stringUp.add(" "); + stringUp.add(""); else - stringUp.add(i+". "+playerList.get(i).player.getUserName()); + stringUp.add(playerList.get(i).player.getUserName()); } catch (IndexOutOfBoundsException e) { stringUp.add(""); @@ -87,12 +87,12 @@ public class Order3 extends OrderLogicCard { List stringList=new ArrayList<>(); - stringList.add("+2 🍗"); + stringList.add("+2\uD83C\uDF56"); stringList.add("--"); - stringList.add("-1 🍗 / -2 ⭐"); + stringList.add("-1\uD83C\uDF56/-2\uD83C\uDFC5"); table.addRow(stringList); - return "TURN ORDER\n" + table.build() + "\n"; + return table.build() + "\n"; } } \ No newline at end of file diff --git a/src/main/java/it/polimi/ingsw/gc14/Model/Orders/Order4.java b/src/main/java/it/polimi/ingsw/gc14/Model/Orders/Order4.java index 517e061..c48340f 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Model/Orders/Order4.java +++ b/src/main/java/it/polimi/ingsw/gc14/Model/Orders/Order4.java @@ -81,9 +81,9 @@ public class Order4 extends OrderLogicCard { { try { if(playerList.get(i).played) - stringUp.add(" "); + stringUp.add(""); else - stringUp.add(i+". "+playerList.get(i).player.getUserName()); + stringUp.add(playerList.get(i).player.getUserName()); } catch (IndexOutOfBoundsException e) { stringUp.add(""); @@ -92,11 +92,11 @@ public class Order4 extends OrderLogicCard { table.addRow(stringUp); List stringList=new ArrayList<>(); - stringList.add("+2 🍗"); - stringList.add("+1 🍗"); + stringList.add("+2\uD83C\uDF56"); + stringList.add("+1\uD83C\uDF56"); stringList.add("--"); - stringList.add("-1 🍗 / -2 ⭐"); + stringList.add("-1\uD83C\uDF56/-2\uD83C\uDFC5"); table.addRow(stringList); - return "TURN ORDER\n" + table.build() + "\n"; + return table.build() + "\n"; } } \ No newline at end of file diff --git a/src/main/java/it/polimi/ingsw/gc14/Model/Orders/Order5.java b/src/main/java/it/polimi/ingsw/gc14/Model/Orders/Order5.java index 221dae6..d08bb2f 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Model/Orders/Order5.java +++ b/src/main/java/it/polimi/ingsw/gc14/Model/Orders/Order5.java @@ -82,9 +82,9 @@ public class Order5 extends OrderLogicCard { { try { if(playerList.get(i).played) - stringUp.add(" "); + stringUp.add(""); else - stringUp.add(i+". "+playerList.get(i).player.getUserName()); + stringUp.add(playerList.get(i).player.getUserName()); } catch (IndexOutOfBoundsException e) { stringUp.add(""); @@ -93,12 +93,12 @@ public class Order5 extends OrderLogicCard { table.addRow(stringUp); List stringList=new ArrayList<>(); - stringList.add("+3 🍗"); - stringList.add("+1 🍗"); + stringList.add("+3\uD83C\uDF56"); + stringList.add("+1\uD83C\uDF56"); stringList.add("--"); stringList.add("--"); - stringList.add("-1 🍗 / -2 ⭐"); + stringList.add("-1\uD83C\uDF56/-2\uD83C\uDFC5"); table.addRow(stringList); - return "TURN ORDER\n" + table.build() + "\n"; + return table.build() + "\n"; } } \ No newline at end of file diff --git a/src/main/java/it/polimi/ingsw/gc14/Model/PlayableCard.java b/src/main/java/it/polimi/ingsw/gc14/Model/PlayableCard.java index 5e805ca..39bddb2 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Model/PlayableCard.java +++ b/src/main/java/it/polimi/ingsw/gc14/Model/PlayableCard.java @@ -74,7 +74,7 @@ public abstract class PlayableCard implements Serializable { */ @Override public String toString() { - return ":"; + return ""; } /** diff --git a/src/main/java/it/polimi/ingsw/gc14/Model/Player.java b/src/main/java/it/polimi/ingsw/gc14/Model/Player.java index c185a05..d08ff72 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Model/Player.java +++ b/src/main/java/it/polimi/ingsw/gc14/Model/Player.java @@ -273,13 +273,8 @@ public class Player implements Serializable { var table = new AsciiTable(ROUNDED, 1); - table.addHeader(this.getUserName()); - table.addRow("RESOURCES:"); - if(this.totem != null) { - table.addRow("Totem: " + this.totem.toString()); - } - table.addRow("🍗 " + this.getFoodValue()); - table.addRow("2\uD83C\uDFC5 " + this.getPrestigeValue()); + String totemStr = (this.totem != null) ? " (" + this.totem.toString() + ")" : ""; + table.addHeader(this.getUserName() + totemStr + " | \uD83C\uDF56:" + this.getFoodValue() + " | \uD83C\uDFC5:" + this.getPrestigeValue() + " "); table.addSeparator(); if(!this.hunters.isEmpty()){ diff --git a/src/main/java/it/polimi/ingsw/gc14/Model/Slot.java b/src/main/java/it/polimi/ingsw/gc14/Model/Slot.java index b114a76..c876643 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Model/Slot.java +++ b/src/main/java/it/polimi/ingsw/gc14/Model/Slot.java @@ -182,7 +182,7 @@ public class Slot implements Serializable { s.append("↓"); } if(getFood()!=0) - s.append("+"+getFood()+" 🍗"); + s.append("+"+getFood()+" \uD83C\uDF56"); return s.toString(); } diff --git a/src/main/java/it/polimi/ingsw/gc14/View/TUI/AsciiTable.java b/src/main/java/it/polimi/ingsw/gc14/View/TUI/AsciiTable.java index 79e419d..e3c575f 100644 --- a/src/main/java/it/polimi/ingsw/gc14/View/TUI/AsciiTable.java +++ b/src/main/java/it/polimi/ingsw/gc14/View/TUI/AsciiTable.java @@ -14,7 +14,7 @@ import java.util.*; *

Example usage: *

{@code
  * AsciiTable table = new AsciiTable(BorderStyle.UNICODE, 3);
- * table.addHeader("Name", "🍗", "⭐");
+ * table.addHeader("Name", "🍖", "⭐");
  * table.addRow("Alice", "4", "12");
  * table.addRow("Bob",   "2", "8");
  * System.out.println(table.build());
@@ -122,7 +122,7 @@ public class AsciiTable {
     /**
      * Returns {@code true} when {@code cp} is a wide (2-column) character.
      * Covers CJK blocks, Hangul, full-width forms, and emoji (including
-     * the specific emoji used in this project: 🍗 U+1F357, ⭐ U+2B50).
+     * the specific emoji used in this project: 🍖 U+1F357, ⭐ U+2B50).
      */
     private static boolean isWide(int cp) {
         if (cp < 0x1100) return false;
@@ -151,7 +151,7 @@ public class AsciiTable {
         if (cp <= 0xFFE6) return true;    // Fullwidth Signs
         if (cp < 0x1F004) return false;
         if (cp <= 0x1FAFF) return true;   // Emoji (mahjong, playing cards, flags,
-                                          // misc symbols, transport, 🍗 U+1F357, ...)
+                                          // misc symbols, transport, 🍖 U+1F357, ...)
         if (cp < 0x20000) return false;
         return cp <= 0x3FFFD;             // CJK Extension B through G
     }
diff --git a/src/main/java/it/polimi/ingsw/gc14/View/TUI/TUI.java b/src/main/java/it/polimi/ingsw/gc14/View/TUI/TUI.java
index 45c2af1..fd5b60a 100644
--- a/src/main/java/it/polimi/ingsw/gc14/View/TUI/TUI.java
+++ b/src/main/java/it/polimi/ingsw/gc14/View/TUI/TUI.java
@@ -9,7 +9,6 @@ import org.jline.reader.LineReader;
 import org.jline.terminal.Terminal;
 
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.List;
 import java.util.Map;
 
@@ -143,8 +142,8 @@ public class TUI implements IView {
      */
     private String buildBoardContent() {
         List left  = List.of(BoardStamp().split("\n"));
-        List right = List.of(printMenuOptions().split("\n"));
-        return AsciiTable.sideBySide(left, right, 3) + "\n" + buildAllHandsContent();
+        List right = List.of(buildAllHandsContent().split("\n"));
+        return AsciiTable.sideBySide(left, right, 3);
     }
 
     /**
@@ -154,35 +153,9 @@ public class TUI implements IView {
     private String buildAllHandsContent() {
         List players = new ArrayList<>(model.players.values());
         if (players.isEmpty()) return "";
-
-        int termWidth = (terminal != null && terminal.getWidth() > 0) ? terminal.getWidth() : 80;
-        int gap = 3;
-
-        List> panels      = new ArrayList<>();
-        List      panelWidths = new ArrayList<>();
-        for (Player p : players) {
-            List lines = Arrays.asList(p.toString().split("\n"));
-            panels.add(lines);
-            panelWidths.add(lines.stream().mapToInt(l -> visibleLength(l)).max().orElse(0));
-        }
-
         StringBuilder result = new StringBuilder();
-        int i = 0;
-        while (i < panels.size()) {
-            int rowWidth = panelWidths.get(i);
-            int j = i + 1;
-            while (j < panels.size()
-                    && rowWidth + gap + panelWidths.get(j) <= termWidth) {
-                rowWidth += gap + panelWidths.get(j);
-                j++;
-            }
-            List merged = panels.get(i);
-            for (int k = i + 1; k < j; k++) {
-                merged = Arrays.asList(
-                        AsciiTable.sideBySide(merged, panels.get(k), gap).split("\n"));
-            }
-            result.append(String.join("\n", merged)).append("\n");
-            i = j;
+        for (Player p : players) {
+            result.append(p.toString()).append("\n");
         }
         return result.toString();
     }
@@ -317,62 +290,58 @@ public class TUI implements IView {
             slotPlayers.add(entry.getValue() != null ? entry.getValue().getUserName() : " ");
         }
 
-        var TribeUpper = new AsciiTable(BorderStyle.ROUNDED, 1);
-        var TribeLower = new AsciiTable(BorderStyle.ROUNDED, 1);
-        var BuildUpper = new AsciiTable(BorderStyle.ROUNDED, 1);
-        BuildUpper.addHeader("Building     ");
-        var BuildLower = new AsciiTable(BorderStyle.ROUNDED, 1);
-        BuildLower.addHeader("Building     ");
+        var UpperCards = new AsciiTable(BorderStyle.ROUNDED, 2);
+        var LowerCards = new AsciiTable(BorderStyle.ROUNDED, 2);
+        UpperCards.addHeader("Char/Events", "Building");
+        LowerCards.addHeader("Char/Events", "Building");
 
-        List upperTribeRows = new ArrayList<>();
-        List lowerTribeRows = new ArrayList<>();
-        upperTribeRows.add("Char/Events");
-        lowerTribeRows.add("Char/Events");
-
-        int max = Math.max(model.upperListTribeCards.size(), model.lowerListTribeCards.size());
-        for (int i = 0; i < max; i++) {
-            if (i < model.upperListTribeCards.size())
-                upperTribeRows.add(i + model.upperListTribeCards.get(i).toStringBoard());
-            if (i < model.lowerListTribeCards.size())
-                lowerTribeRows.add(i + "" + model.lowerListTribeCards.get(i).toStringBoard());
+        int maxU = Math.max(model.upperListTribeCards.size(), model.upperListBuildingCards.size());
+        for (int i = 0; i < maxU; i++) {
+            String t = i < model.upperListTribeCards.size() ? i + model.upperListTribeCards.get(i).toStringBoard() : "";
+            String b = i < model.upperListBuildingCards.size() ? i + model.upperListBuildingCards.get(i).toString() : "";
+            UpperCards.addRow(t, b);
         }
 
-        int maxB = Math.max(model.upperListBuildingCards.size(), model.lowerListBuildingCards.size());
-        for (int i = 0; i < maxB; i++) {
-            if (i < model.upperListBuildingCards.size())
-                BuildUpper.addRow(i + model.upperListBuildingCards.get(i).toString());
-            if (i < model.lowerListBuildingCards.size())
-                BuildLower.addRow(i + model.lowerListBuildingCards.get(i).toString());
+        int maxL = Math.max(model.lowerListTribeCards.size(), model.lowerListBuildingCards.size());
+        for (int i = 0; i < maxL; i++) {
+            String t = i < model.lowerListTribeCards.size() ? i + model.lowerListTribeCards.get(i).toStringBoard() : "";
+            String b = i < model.lowerListBuildingCards.size() ? i + model.lowerListBuildingCards.get(i).toString() : "";
+            LowerCards.addRow(t, b);
         }
 
-        upperTribeRows.forEach(TribeUpper::addRow);
-        lowerTribeRows.forEach(TribeLower::addRow);
         offerTrack.addRow(slotPlayers);
         offerTrack.addRow(slotNames);
 
-        return "CURRENT STATE\n" + model.currentState + "\n" + model.orderLogicCard + "\n"
-                + AsciiTable.sideBySide(
-                        Arrays.stream(TribeUpper.build().split("\n")).toList(),
-                        Arrays.stream(BuildUpper.build().split("\n")).toList(), 2)
-                + "\n" + offerTrack.build() + "\n"
-                + AsciiTable.sideBySide(
-                        List.of(TribeLower.build().split("\n")),
-                        Arrays.stream(BuildLower.build().split("\n")).toList(), 2);
+        String upperSection = UpperCards.build();
+
+        String middleSection = AsciiTable.sideBySide(
+                List.of(model.orderLogicCard.toString().split("\n")),
+                List.of(offerTrack.build().split("\n")), 3);
+
+        String lowerSection = LowerCards.build();
+
+        return model.currentState + "\n"
+                + upperSection + "\n"
+                + middleSection + "\n"
+                + lowerSection;
     }
 
-    // ── Menu options ──────────────────────────────────────────────────────────
+    // ── Help ──────────────────────────────────────────────────────────────────
 
-    private String printMenuOptions() {
+    /** Displays the command help panel. */
+    public void renderHelp() {
+        display(buildHelpContent());
+    }
+
+    private String buildHelpContent() {
         var table = new AsciiTable(BorderStyle.ROUNDED, 1);
         table.addHeader("Commands");
         table.addRow("slot ");
-        table.addRow("draw upper tribe ");
-        table.addRow("draw upper building ");
-        table.addRow("draw lower tribe ");
-        table.addRow("draw lower building ");
+        table.addRow("draw upper|lower  tribe|building  ");
         table.addRow("totem ");
         table.addRow("skip");
         table.addRow("render");
+        table.addRow("help");
         table.addRow("rematch  |  quit");
         return table.build();
     }