From 4bb9a31ffa3c35230e75c884be039a5112af3e18 Mon Sep 17 00:00:00 2001 From: jzitnik-dev Date: Mon, 23 Dec 2024 14:42:01 +0100 Subject: [PATCH] feat: Implemented chat --- .../controllers/CharacterController.java | 6 +- .../chronos/controllers/ChatController.java | 58 ++++++++++++++++++ .../chronos/controllers/PlayerController.java | 14 +++++ .../chronos/controllers/RoomController.java | 32 ++++++++++ .../cz/jzitnik/chronos/entities/Message.java | 36 +++++++++++ .../jzitnik/chronos/entities/MessageType.java | 8 +++ .../cz/jzitnik/chronos/entities/Player.java | 4 ++ .../interactions/InteractionService.java | 11 ++-- .../payload/requests/MessageRequest.java | 10 +++ .../chronos/repository/MessageRepository.java | 19 ++++++ .../jzitnik/chronos/services/ItemService.java | 28 +++++++++ .../main/java/cz/jzitnik/api/ApiService.java | 24 ++++++++ .../jzitnik/api/requests/MessageRequest.java | 12 ++++ .../java/cz/jzitnik/api/types/Message.java | 61 +++++++++++++++++++ .../cz/jzitnik/api/types/MessageType.java | 8 +++ .../src/main/java/cz/jzitnik/game/Chat.java | 51 ++++++++++++++++ .../java/cz/jzitnik/game/CommandPalette.java | 18 +++++- .../main/java/cz/jzitnik/game/Inventory.java | 2 +- 18 files changed, 394 insertions(+), 8 deletions(-) create mode 100644 backend/src/main/java/cz/jzitnik/chronos/controllers/ChatController.java create mode 100644 backend/src/main/java/cz/jzitnik/chronos/entities/Message.java create mode 100644 backend/src/main/java/cz/jzitnik/chronos/entities/MessageType.java create mode 100644 backend/src/main/java/cz/jzitnik/chronos/payload/requests/MessageRequest.java create mode 100644 backend/src/main/java/cz/jzitnik/chronos/repository/MessageRepository.java create mode 100644 backend/src/main/java/cz/jzitnik/chronos/services/ItemService.java create mode 100644 frontend/src/main/java/cz/jzitnik/api/requests/MessageRequest.java create mode 100644 frontend/src/main/java/cz/jzitnik/api/types/Message.java create mode 100644 frontend/src/main/java/cz/jzitnik/api/types/MessageType.java create mode 100644 frontend/src/main/java/cz/jzitnik/game/Chat.java diff --git a/backend/src/main/java/cz/jzitnik/chronos/controllers/CharacterController.java b/backend/src/main/java/cz/jzitnik/chronos/controllers/CharacterController.java index 0fd4ac4..2fbf48a 100644 --- a/backend/src/main/java/cz/jzitnik/chronos/controllers/CharacterController.java +++ b/backend/src/main/java/cz/jzitnik/chronos/controllers/CharacterController.java @@ -9,6 +9,7 @@ import cz.jzitnik.chronos.payload.responses.TakeItemsResponse; import cz.jzitnik.chronos.payload.responses.UnifiedResponse; import cz.jzitnik.chronos.repository.CharacterRepository; import cz.jzitnik.chronos.repository.PlayerRepository; +import cz.jzitnik.chronos.services.ItemService; import cz.jzitnik.chronos.utils.anotations.CheckUser; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; @@ -28,6 +29,9 @@ public class CharacterController { @Autowired private CharacterRepository characterRepository; + @Autowired + private ItemService itemService; + @GetMapping("/interaction") @CheckUser public ResponseEntity> getInteractionData(@RequestParam String playerKey, @RequestParam Long characterId) { @@ -99,7 +103,7 @@ public class CharacterController { for (Item item : character.getInventory()) { var itemClone = new Item(item.getItemType(), player); - player.addItem(itemClone); + itemService.addItem(player, itemClone); } player.getSeenCharacters().add(character); diff --git a/backend/src/main/java/cz/jzitnik/chronos/controllers/ChatController.java b/backend/src/main/java/cz/jzitnik/chronos/controllers/ChatController.java new file mode 100644 index 0000000..a3de3ec --- /dev/null +++ b/backend/src/main/java/cz/jzitnik/chronos/controllers/ChatController.java @@ -0,0 +1,58 @@ +package cz.jzitnik.chronos.controllers; + +import cz.jzitnik.chronos.entities.Message; +import cz.jzitnik.chronos.payload.requests.MessageRequest; +import cz.jzitnik.chronos.payload.responses.UnifiedResponse; +import cz.jzitnik.chronos.repository.MessageRepository; +import cz.jzitnik.chronos.repository.PlayerRepository; +import cz.jzitnik.chronos.utils.anotations.CheckUser; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@CrossOrigin(origins = "*", maxAge = 3600) +@RestController +@RequestMapping("/game/chat") +public class ChatController { + @Autowired + private MessageRepository messageRepository; + + @Autowired + private PlayerRepository playerRepository; + + @GetMapping + @CheckUser + public ResponseEntity, Error>> getMessages(@RequestParam String playerKey) { + var player = playerRepository.findByPlayerKey(playerKey).get(); + var gameId = player.getGame().getId(); + + Pageable pageable = PageRequest.of(0, 20); + + var messages = messageRepository.findLastMessagesByGameId(gameId, pageable); + + return ResponseEntity.ok(UnifiedResponse.success(messages)); + } + + @PostMapping + @CheckUser + public ResponseEntity> sendMessage(@RequestParam String playerKey, @RequestBody MessageRequest messageRequest) { + var player = playerRepository.findByPlayerKey(playerKey).get(); + + if (messageRequest.getContent().length() > 100 || messageRequest.getContent().isEmpty()) { + return ResponseEntity.status(HttpStatus.BAD_REQUEST).body( + UnifiedResponse.failure(new Error("Message cannot be longer than 100 characters and cannot be empty!")) + ); + } + + var message = new Message(player, messageRequest.getContent()); + + messageRepository.save(message); + + return ResponseEntity.ok(UnifiedResponse.success(null)); + } +} diff --git a/backend/src/main/java/cz/jzitnik/chronos/controllers/PlayerController.java b/backend/src/main/java/cz/jzitnik/chronos/controllers/PlayerController.java index 26dc96c..afa904e 100644 --- a/backend/src/main/java/cz/jzitnik/chronos/controllers/PlayerController.java +++ b/backend/src/main/java/cz/jzitnik/chronos/controllers/PlayerController.java @@ -1,5 +1,6 @@ package cz.jzitnik.chronos.controllers; +import cz.jzitnik.chronos.entities.Item; import cz.jzitnik.chronos.entities.Player; import cz.jzitnik.chronos.payload.errors.ItemNotUsableException; import cz.jzitnik.chronos.payload.errors.NotFoundError; @@ -87,4 +88,17 @@ public class PlayerController { return ResponseEntity.ok(UnifiedResponse.success(null)); } + + @GetMapping("/item") + @CheckUser + public ResponseEntity> getItemInfo(@RequestParam String playerKey, @RequestParam Long itemId) { + var itemOptional = itemRepository.findById(itemId); + + if (itemOptional.isEmpty()) { + return ResponseEntity.status(HttpStatus.NOT_FOUND).body(UnifiedResponse.failure(new NotFoundError("Item was not found!"))); + } + var item = itemOptional.get(); + + return ResponseEntity.ok(UnifiedResponse.success(item)); + } } diff --git a/backend/src/main/java/cz/jzitnik/chronos/controllers/RoomController.java b/backend/src/main/java/cz/jzitnik/chronos/controllers/RoomController.java index ced8013..c612fc1 100644 --- a/backend/src/main/java/cz/jzitnik/chronos/controllers/RoomController.java +++ b/backend/src/main/java/cz/jzitnik/chronos/controllers/RoomController.java @@ -1,6 +1,9 @@ package cz.jzitnik.chronos.controllers; +import cz.jzitnik.chronos.entities.Message; +import cz.jzitnik.chronos.entities.MessageType; import cz.jzitnik.chronos.entities.Room; +import cz.jzitnik.chronos.payload.errors.NotFoundError; import cz.jzitnik.chronos.payload.responses.UnifiedResponse; import cz.jzitnik.chronos.repository.PlayerRepository; import cz.jzitnik.chronos.repository.RoomRepository; @@ -35,6 +38,30 @@ public class RoomController { ); } + @GetMapping("/room") + @CheckUser + public ResponseEntity> getRoom(@RequestParam("playerKey") String playerKey, @RequestParam("roomId") Long roomId) { + var player = playerRepository.findByPlayerKey(playerKey).get(); + + var roomOptional = roomRepository.findById(roomId); + + if (roomOptional.isEmpty()) { + return ResponseEntity.status(HttpStatus.NOT_FOUND).body( + UnifiedResponse.failure(new NotFoundError("Room with id " + roomId + " was not found!")) + ); + } + + var room = roomOptional.get(); + + if (!room.getGame().getId().equals(player.getGame().getId())) { + return ResponseEntity.status(HttpStatus.FORBIDDEN).body( + UnifiedResponse.failure(new Error("This room is from a different game!")) + ); + } + + return ResponseEntity.ok(UnifiedResponse.success(room)); + } + @GetMapping("/current_room") @CheckUser public ResponseEntity> getCurrentRoom(@RequestParam("playerKey") String playerKey) { @@ -64,6 +91,11 @@ public class RoomController { player.setCurrentRoom(roomOptional.get()); + // Send message to chat + var message = new Message(player, String.valueOf(roomId), MessageType.MOVE_TO_ROOM); + + player.getMessages().add(message); + playerRepository.save(player); return ResponseEntity.ok(UnifiedResponse.success(null)); diff --git a/backend/src/main/java/cz/jzitnik/chronos/entities/Message.java b/backend/src/main/java/cz/jzitnik/chronos/entities/Message.java new file mode 100644 index 0000000..04da46c --- /dev/null +++ b/backend/src/main/java/cz/jzitnik/chronos/entities/Message.java @@ -0,0 +1,36 @@ +package cz.jzitnik.chronos.entities; + +import jakarta.persistence.*; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@Getter +@Setter +@NoArgsConstructor +@Entity +public class Message { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @ManyToOne + private Player author; + + private String content; + + @Enumerated(EnumType.STRING) + private MessageType messageType; + + public Message(Player author, String content) { + this.author = author; + this.content = content; + this.messageType = MessageType.CUSTOM; + } + + public Message(Player author, String content, MessageType messageType) { + this.author = author; + this.content = content; + this.messageType = messageType; + } +} \ No newline at end of file diff --git a/backend/src/main/java/cz/jzitnik/chronos/entities/MessageType.java b/backend/src/main/java/cz/jzitnik/chronos/entities/MessageType.java new file mode 100644 index 0000000..033d509 --- /dev/null +++ b/backend/src/main/java/cz/jzitnik/chronos/entities/MessageType.java @@ -0,0 +1,8 @@ +package cz.jzitnik.chronos.entities; + +public enum MessageType { + CUSTOM, + MOVE_TO_ROOM, + GOT_ITEM, + JOINED, +} diff --git a/backend/src/main/java/cz/jzitnik/chronos/entities/Player.java b/backend/src/main/java/cz/jzitnik/chronos/entities/Player.java index 7f713b6..b727c63 100644 --- a/backend/src/main/java/cz/jzitnik/chronos/entities/Player.java +++ b/backend/src/main/java/cz/jzitnik/chronos/entities/Player.java @@ -42,6 +42,10 @@ public class Player { private boolean luck = false; + @OneToMany(mappedBy = "author", cascade = CascadeType.ALL) + @JsonIgnore + private List messages = new ArrayList<>(); + @ManyToMany @JoinTable( name = "character_player", diff --git a/backend/src/main/java/cz/jzitnik/chronos/interactions/InteractionService.java b/backend/src/main/java/cz/jzitnik/chronos/interactions/InteractionService.java index 714cfd2..cf0c9c9 100644 --- a/backend/src/main/java/cz/jzitnik/chronos/interactions/InteractionService.java +++ b/backend/src/main/java/cz/jzitnik/chronos/interactions/InteractionService.java @@ -7,11 +7,11 @@ import cz.jzitnik.chronos.entities.Character; import cz.jzitnik.chronos.payload.responses.InteractionResponse; import cz.jzitnik.chronos.repository.CharacterRepository; import cz.jzitnik.chronos.repository.PlayerRepository; +import cz.jzitnik.chronos.services.ItemService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.ArrayList; -import java.util.Optional; import java.util.Random; @Service @@ -22,6 +22,9 @@ public class InteractionService { @Autowired private CharacterRepository characterRepository; + @Autowired + private ItemService itemService; + @FunctionalInterface public interface Function3 { W apply(T t, U u, V v); @@ -51,8 +54,7 @@ public class InteractionService { if (playerWins) { var item = new Item(ItemType.KEY_FRAGMENT, player); - player.addItem(item); - playerRepository.save(player); + itemService.addItem(player, item); character.setInteractedWith(true); characterRepository.save(character); @@ -72,8 +74,7 @@ public class InteractionService { return new InteractionResponse(false, "Remíza. Jestli chceš můžeš si se mnou zahrát ještě jednou.", new ArrayList<>()); } else if ((userChoice == 0 && characterChoice == 2) || (userChoice == 1 && characterChoice == 0) || (userChoice == 2 && characterChoice == 1)) { var item = new Item(ItemType.KEY_FRAGMENT, player); - player.addItem(item); - playerRepository.save(player); + itemService.addItem(player, item); character.setInteractedWith(true); characterRepository.save(character); diff --git a/backend/src/main/java/cz/jzitnik/chronos/payload/requests/MessageRequest.java b/backend/src/main/java/cz/jzitnik/chronos/payload/requests/MessageRequest.java new file mode 100644 index 0000000..23f62e2 --- /dev/null +++ b/backend/src/main/java/cz/jzitnik/chronos/payload/requests/MessageRequest.java @@ -0,0 +1,10 @@ +package cz.jzitnik.chronos.payload.requests; + +import lombok.Getter; +import lombok.NoArgsConstructor; + +@NoArgsConstructor +@Getter +public class MessageRequest { + private String content; +} diff --git a/backend/src/main/java/cz/jzitnik/chronos/repository/MessageRepository.java b/backend/src/main/java/cz/jzitnik/chronos/repository/MessageRepository.java new file mode 100644 index 0000000..f5bbf74 --- /dev/null +++ b/backend/src/main/java/cz/jzitnik/chronos/repository/MessageRepository.java @@ -0,0 +1,19 @@ +package cz.jzitnik.chronos.repository; + +import cz.jzitnik.chronos.entities.Message; +import org.springframework.data.domain.Pageable; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +import java.util.List; + +public interface MessageRepository extends JpaRepository { + + @Query(""" + SELECT m FROM Message m + WHERE m.author.game.id = :gameId + ORDER BY m.id DESC + """) + List findLastMessagesByGameId(@Param("gameId") Long gameId, Pageable pageable); +} diff --git a/backend/src/main/java/cz/jzitnik/chronos/services/ItemService.java b/backend/src/main/java/cz/jzitnik/chronos/services/ItemService.java new file mode 100644 index 0000000..e8abe94 --- /dev/null +++ b/backend/src/main/java/cz/jzitnik/chronos/services/ItemService.java @@ -0,0 +1,28 @@ +package cz.jzitnik.chronos.services; + +import cz.jzitnik.chronos.entities.Message; +import cz.jzitnik.chronos.entities.MessageType; +import cz.jzitnik.chronos.entities.Player; +import cz.jzitnik.chronos.entities.Item; +import cz.jzitnik.chronos.repository.ItemRepository; +import cz.jzitnik.chronos.repository.PlayerRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class ItemService { + @Autowired + private PlayerRepository playerRepository; + + @Autowired + private ItemRepository itemRepository; + + public void addItem(Player player, Item item) { + var itemSaved = itemRepository.save(item); + + var message = new Message(player, String.valueOf(itemSaved.getId()), MessageType.GOT_ITEM); + + player.getMessages().add(message); + playerRepository.save(player); + } +} diff --git a/frontend/src/main/java/cz/jzitnik/api/ApiService.java b/frontend/src/main/java/cz/jzitnik/api/ApiService.java index b2f506b..7c329b7 100644 --- a/frontend/src/main/java/cz/jzitnik/api/ApiService.java +++ b/frontend/src/main/java/cz/jzitnik/api/ApiService.java @@ -1,6 +1,7 @@ package cz.jzitnik.api; import cz.jzitnik.api.requests.InteractionRequest; +import cz.jzitnik.api.requests.MessageRequest; import cz.jzitnik.api.requests.PlayerNameRequest; import cz.jzitnik.api.responses.InteractionResponse; import cz.jzitnik.api.responses.UnifiedResponse; @@ -81,4 +82,27 @@ public interface ApiService { @Query("playerKey") String playerKey, @Body InteractionRequest interactionRequest ); + + @GET("game/chat") + Call, Error>> getMessages( + @Query("playerKey") String playerKey + ); + + @POST("game/chat") + Call> sendMessage( + @Query("playerKey") String playerKey, + @Body MessageRequest messageRequest + ); + + @GET("game/players/item") + Call> getItemInfo( + @Query("playerKey") String playerKey, + @Query("itemId") Long itemId + ); + + @GET("game/rooms/room") + Call> getRoom( + @Query("playerKey") String playerKey, + @Query("roomId") Long roomId + ); } diff --git a/frontend/src/main/java/cz/jzitnik/api/requests/MessageRequest.java b/frontend/src/main/java/cz/jzitnik/api/requests/MessageRequest.java new file mode 100644 index 0000000..2c07ad5 --- /dev/null +++ b/frontend/src/main/java/cz/jzitnik/api/requests/MessageRequest.java @@ -0,0 +1,12 @@ +package cz.jzitnik.api.requests; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@AllArgsConstructor +@NoArgsConstructor +@Getter +public class MessageRequest { + private String content; +} diff --git a/frontend/src/main/java/cz/jzitnik/api/types/Message.java b/frontend/src/main/java/cz/jzitnik/api/types/Message.java new file mode 100644 index 0000000..983f691 --- /dev/null +++ b/frontend/src/main/java/cz/jzitnik/api/types/Message.java @@ -0,0 +1,61 @@ +package cz.jzitnik.api.types; + +import cz.jzitnik.api.ApiService; +import cz.jzitnik.utils.Cli; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +import java.io.IOException; + +@Getter +@Setter +@NoArgsConstructor +public class Message { + private Long id; + + private Player author; + + private String content; + + private MessageType messageType; + + public String getString(ApiService apiService, String playerKey) { + return switch (messageType) { + case CUSTOM -> Cli.Colors.BLUE + author.getName() + Cli.Colors.RESET + ": " + content; + case JOINED -> "Hráč " + Cli.Colors.BLUE + author.getName() + Cli.Colors.RESET + " se připojil."; + case GOT_ITEM -> { + try { + var response = apiService.getItemInfo(playerKey, Long.valueOf(content)).execute(); + var body = response.body(); + + if (!body.getSuccess()) { + yield "Hráč " + Cli.Colors.BLUE + author.getName() + Cli.Colors.RESET + " získal unknown."; + } + + var item = body.getData().get(); + + yield "Hráč " + Cli.Colors.BLUE + author.getName() + Cli.Colors.RESET + " získal " + Cli.Colors.BLUE + item + Cli.Colors.RESET + "."; + } catch (IOException e) { + yield "Hráč unknown získal unknown"; + } + } + case MOVE_TO_ROOM -> { + try { + var response = apiService.getRoom(playerKey, Long.valueOf(content)).execute(); + var body = response.body(); + + if (!body.getSuccess()) { + yield "Hráč " + Cli.Colors.BLUE + author.getName() + Cli.Colors.RESET + " vešel do místnosti unknown."; + } + + var room = body.getData().get(); + + yield "Hráč " + Cli.Colors.BLUE + author.getName() + Cli.Colors.RESET + " vešel do místnosti " + Cli.Colors.BLUE + room + Cli.Colors.RESET + "."; + } catch (IOException e) { + yield "Hráč unknown vešel do místnosti unknown"; + } + } + }; + } +} diff --git a/frontend/src/main/java/cz/jzitnik/api/types/MessageType.java b/frontend/src/main/java/cz/jzitnik/api/types/MessageType.java new file mode 100644 index 0000000..50a0052 --- /dev/null +++ b/frontend/src/main/java/cz/jzitnik/api/types/MessageType.java @@ -0,0 +1,8 @@ +package cz.jzitnik.api.types; + +public enum MessageType { + CUSTOM, + MOVE_TO_ROOM, + GOT_ITEM, + JOINED, +} diff --git a/frontend/src/main/java/cz/jzitnik/game/Chat.java b/frontend/src/main/java/cz/jzitnik/game/Chat.java new file mode 100644 index 0000000..6446eaf --- /dev/null +++ b/frontend/src/main/java/cz/jzitnik/game/Chat.java @@ -0,0 +1,51 @@ +package cz.jzitnik.game; + +import cz.jzitnik.api.ApiService; +import cz.jzitnik.api.requests.MessageRequest; +import cz.jzitnik.api.types.Message; +import cz.jzitnik.utils.Cli; +import lombok.AllArgsConstructor; + +import java.io.IOException; +import java.util.Collections; + +@AllArgsConstructor +public class Chat { + private ApiService apiService; + private String playerKey; + + public void display() throws IOException { + System.out.println(); + var response = apiService.getMessages(playerKey).execute(); + var messages = response.body().getData().get(); + Collections.reverse(messages); + + for (Message message : messages) { + System.out.println(message.getString(apiService, playerKey)); + } + } + + public void sendMessage() throws IOException { + System.out.println(); + + var console = System.console(); + + var messageContent = console.readLine("Zadejte zprávu: ").trim(); + + if (messageContent.isEmpty()) { + Cli.error("Zpráva nesmí být prázná!"); + return; + } + + if (messageContent.length() > 100) { + Cli.error("Zpráva nesmí být delší jak 100 znaků!"); + return; + } + + var messageRequest = new MessageRequest(messageContent); + + apiService.sendMessage(playerKey, messageRequest).execute(); + + Cli.success("Zpráva byla odeslána!"); + } +} diff --git a/frontend/src/main/java/cz/jzitnik/game/CommandPalette.java b/frontend/src/main/java/cz/jzitnik/game/CommandPalette.java index 9b51cd9..3827a08 100644 --- a/frontend/src/main/java/cz/jzitnik/game/CommandPalette.java +++ b/frontend/src/main/java/cz/jzitnik/game/CommandPalette.java @@ -17,6 +17,8 @@ public class CommandPalette { CUSTOM, INVENTORY_OPEN, USER_PROFILE, + CHAT_OPEN, + CHAT_SEND, EXIT, } @@ -55,9 +57,11 @@ public class CommandPalette { public int displayIndex() throws IOException { List allCommands = new ArrayList<>(commands); - // Command that can be used anywhere + // Commands that can be used anywhere allCommands.add(new Command("Otevřít inventář", CommandType.INVENTORY_OPEN)); allCommands.add(new Command("Otevřít profil uživatele", CommandType.USER_PROFILE)); + allCommands.add(new Command("Otevřít chat", CommandType.CHAT_OPEN)); + allCommands.add(new Command("Odeslat zprávu do chatu", CommandType.CHAT_SEND)); allCommands.add(new Command("Odejít ze hry", CommandType.EXIT)); System.out.println("\n"); @@ -92,6 +96,18 @@ public class CommandPalette { System.out.println("\n\n" + me); + yield displayIndex(); + } + case CHAT_OPEN -> { + var chat = new Chat(apiService, playerKey); + chat.display(); + + yield displayIndex(); + } + case CHAT_SEND -> { + var chat = new Chat(apiService, playerKey); + chat.sendMessage(); + yield displayIndex(); } }; diff --git a/frontend/src/main/java/cz/jzitnik/game/Inventory.java b/frontend/src/main/java/cz/jzitnik/game/Inventory.java index 2774a74..3c7fd52 100644 --- a/frontend/src/main/java/cz/jzitnik/game/Inventory.java +++ b/frontend/src/main/java/cz/jzitnik/game/Inventory.java @@ -51,7 +51,7 @@ public class Inventory { if (!usableItemList.isEmpty()) { System.out.println("\n\nNyní si můžete vybrat jaký item chcete využít"); var options = new ArrayList<>(usableItemList.stream().map(Item::toString).toList()); - options.add("Zavřít inventář"); + options.add(Cli.Colors.BLUE + "Zavřít inventář" + Cli.Colors.RESET); var selectedIndex = Cli.selectOptionIndex(options);