feat: Implemented moving items between players
This commit is contained in:
parent
5dc191c842
commit
d8969df0d3
@ -6,7 +6,7 @@ Jednoduchá multiplayer hra napsaná v Javě.
|
||||
|
||||
Backend je napsaný v Javě pomocí Spring. Jedná se o jednoduchý HTTP server.
|
||||
|
||||
**Ano jsem debil, využít relační databázi nebyl rozhodě dobrý nápad. Došlo mi to uprostřed programování a už se mi nechtělo vracet zpět.**
|
||||
**Ano jsem debil, využít relační databázi nebyl rozhodně dobrý nápad. Došlo mi to uprostřed programování a už se mi nechtělo vracet zpět.**
|
||||
|
||||
### Enviromental variables
|
||||
|
||||
|
@ -1,13 +1,17 @@
|
||||
package cz.jzitnik.chronos.controllers;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import cz.jzitnik.chronos.entities.Item;
|
||||
import cz.jzitnik.chronos.entities.Message;
|
||||
import cz.jzitnik.chronos.entities.MessageType;
|
||||
import cz.jzitnik.chronos.entities.Player;
|
||||
import cz.jzitnik.chronos.payload.errors.FullInventoryError;
|
||||
import cz.jzitnik.chronos.payload.errors.ItemNotUsableException;
|
||||
import cz.jzitnik.chronos.payload.errors.NotFoundError;
|
||||
import cz.jzitnik.chronos.payload.requests.PlayerNameRequest;
|
||||
import cz.jzitnik.chronos.payload.responses.InventoryFullResponse;
|
||||
import cz.jzitnik.chronos.payload.responses.ItemMoveMessageResponse;
|
||||
import cz.jzitnik.chronos.payload.responses.UnifiedResponse;
|
||||
import cz.jzitnik.chronos.repository.GameRepository;
|
||||
import cz.jzitnik.chronos.repository.ItemRepository;
|
||||
@ -19,6 +23,8 @@ 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/players")
|
||||
@ -116,4 +122,58 @@ public class PlayerController {
|
||||
|
||||
return ResponseEntity.ok(UnifiedResponse.success(item));
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
@CheckUser
|
||||
public ResponseEntity<UnifiedResponse<List<Player>, Error>> getAllPlayers(@RequestParam String playerKey) {
|
||||
var player = playerRepository.findByPlayerKey(playerKey).get();
|
||||
var game = player.getGame();
|
||||
|
||||
var players = game.getPlayers();
|
||||
|
||||
return ResponseEntity.ok(UnifiedResponse.success(players));
|
||||
}
|
||||
|
||||
@PostMapping("/send_item")
|
||||
@CheckUser
|
||||
public ResponseEntity<UnifiedResponse<Object, Error>> sendItem(@RequestParam String playerKey, @RequestParam Long itemId, @RequestParam Long playerId) {
|
||||
var player = playerRepository.findByPlayerKey(playerKey).get();
|
||||
|
||||
var player2Optional = playerRepository.findById(playerId);
|
||||
if (player2Optional.isEmpty()) {
|
||||
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(UnifiedResponse.failure(new NotFoundError("Player with id " + playerId + " was not found!")));
|
||||
}
|
||||
var player2 = player2Optional.get();
|
||||
|
||||
var itemOptional = itemRepository.findById(itemId);
|
||||
if (itemOptional.isEmpty()) {
|
||||
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(UnifiedResponse.failure(new NotFoundError("Item with id " + itemId + " was not found!")));
|
||||
}
|
||||
var item = itemOptional.get();
|
||||
|
||||
if (item.getOwner() == null || !item.getOwner().getId().equals(player.getId())) {
|
||||
return ResponseEntity.status(HttpStatus.FORBIDDEN).body(UnifiedResponse.failure(new Error("You don't own this item!")));
|
||||
}
|
||||
if (player.getInventorySize() - player.getInventory().size() == 0) {
|
||||
// Inventory is full
|
||||
return ResponseEntity.status(HttpStatus.CONFLICT).body(UnifiedResponse.failure(new FullInventoryError("Player has full inventory!")));
|
||||
}
|
||||
|
||||
item.setOwner(player2);
|
||||
itemRepository.save(item);
|
||||
|
||||
ObjectMapper objectMapper = new ObjectMapper();
|
||||
try {
|
||||
var json = objectMapper.writeValueAsString(new ItemMoveMessageResponse(item.getItemType(), player2.getName()));
|
||||
|
||||
var message = new Message(player, json, MessageType.ITEM_MOVED);
|
||||
|
||||
player.getMessages().add(message);
|
||||
playerRepository.save(player);
|
||||
|
||||
return ResponseEntity.ok(UnifiedResponse.success(null));
|
||||
} catch (JsonProcessingException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7,5 +7,6 @@ public enum MessageType {
|
||||
LOST_ITEM,
|
||||
ITEM_USED,
|
||||
KEY_FRAGMENT_HANDED_OVER,
|
||||
ITEM_MOVED,
|
||||
JOINED,
|
||||
}
|
||||
|
@ -0,0 +1,7 @@
|
||||
package cz.jzitnik.chronos.payload.errors;
|
||||
|
||||
public class FullInventoryError extends Error {
|
||||
public FullInventoryError(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
package cz.jzitnik.chronos.payload.responses;
|
||||
|
||||
import cz.jzitnik.chronos.entities.ItemType;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
public class ItemMoveMessageResponse {
|
||||
private ItemType itemType;
|
||||
private String playerToName;
|
||||
}
|
@ -138,4 +138,16 @@ public interface ApiService {
|
||||
Call<UnifiedResponse<GameWonResponse, Error>> gameWon(
|
||||
@Query("playerKey") String playerKey
|
||||
);
|
||||
|
||||
@GET("game/players")
|
||||
Call<UnifiedResponse<List<Player>, Error>> getAllPlayers(
|
||||
@Query("playerKey") String playerKey
|
||||
);
|
||||
|
||||
@POST("game/players/send_item")
|
||||
Call<UnifiedResponse<Object, Error>> sendItem(
|
||||
@Query("playerKey") String playerKey,
|
||||
@Query("itemId") Long itemId,
|
||||
@Query("playerId") Long playerId
|
||||
);
|
||||
}
|
||||
|
@ -0,0 +1,10 @@
|
||||
package cz.jzitnik.api.responses;
|
||||
|
||||
import cz.jzitnik.api.types.ItemType;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
public class ItemMoveMessageResponse {
|
||||
private ItemType itemType;
|
||||
private String playerToName;
|
||||
}
|
@ -3,6 +3,7 @@ package cz.jzitnik.api.types;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import cz.jzitnik.api.ApiService;
|
||||
import cz.jzitnik.api.responses.ItemMoveMessageResponse;
|
||||
import cz.jzitnik.utils.Cli;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
@ -85,6 +86,17 @@ public class Message {
|
||||
yield "Hráč " + Cli.Colors.BLUE + author.getName() + Cli.Colors.RESET + " využil item unknown.";
|
||||
}
|
||||
}
|
||||
case ITEM_MOVED -> {
|
||||
ObjectMapper objectMapper = new ObjectMapper();
|
||||
|
||||
try {
|
||||
var data = objectMapper.readValue(content, ItemMoveMessageResponse.class);
|
||||
|
||||
yield "Hráč " + Cli.Colors.BLUE + author.getName() + Cli.Colors.RESET + " dal " + Cli.Colors.BLUE + data.getItemType() + Cli.Colors.RESET + " hráči " + Cli.Colors.BLUE + data.getPlayerToName() + Cli.Colors.RESET + ".";
|
||||
} catch (JsonProcessingException e) {
|
||||
yield "Hráč " + Cli.Colors.BLUE + author.getName() + Cli.Colors.RESET + " dal neznámý item neznámému hráči.";
|
||||
}
|
||||
}
|
||||
case KEY_FRAGMENT_HANDED_OVER -> "Hráč " + Cli.Colors.BLUE + author.getName() + Cli.Colors.RESET + " odevzdal " + Cli.Colors.BLUE + "Fragment klíče" + Cli.Colors.RESET + ".";
|
||||
};
|
||||
}
|
||||
|
@ -7,5 +7,6 @@ public enum MessageType {
|
||||
LOST_ITEM,
|
||||
ITEM_USED,
|
||||
KEY_FRAGMENT_HANDED_OVER,
|
||||
ITEM_MOVED,
|
||||
JOINED,
|
||||
}
|
||||
|
@ -9,6 +9,7 @@ import lombok.Setter;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@ -21,6 +22,7 @@ public class CommandPalette {
|
||||
USER_PROFILE,
|
||||
CHAT_OPEN,
|
||||
CHAT_SEND,
|
||||
PLAYER_LIST_OPEN,
|
||||
CHECK_WINNABLE,
|
||||
EXIT,
|
||||
}
|
||||
@ -68,7 +70,7 @@ public class CommandPalette {
|
||||
|
||||
var configPath = ConfigPathProvider.getPath();
|
||||
|
||||
File file = new File(configPath);
|
||||
File file = new File(Path.of(configPath, "config.json").toString());
|
||||
file.delete();
|
||||
|
||||
System.exit(0);
|
||||
@ -81,6 +83,7 @@ public class CommandPalette {
|
||||
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("Zobrazit list všech hráčů", CommandType.PLAYER_LIST_OPEN));
|
||||
allCommands.add(new Command("Zkontrolovat vyhratelnost hry", CommandType.CHECK_WINNABLE));
|
||||
allCommands.add(new Command("Odejít ze hry", CommandType.EXIT));
|
||||
|
||||
@ -148,6 +151,12 @@ public class CommandPalette {
|
||||
Cli.info("Hra je dost možná nevyhratelná!");
|
||||
}
|
||||
|
||||
yield displayIndex();
|
||||
}
|
||||
case PLAYER_LIST_OPEN -> {
|
||||
var playerList = new PlayerList(apiService, playerKey);
|
||||
playerList.display();
|
||||
|
||||
yield displayIndex();
|
||||
}
|
||||
};
|
||||
|
@ -21,6 +21,11 @@ public class Inventory {
|
||||
System.out.println();
|
||||
Cli.info("Váš inventář:");
|
||||
|
||||
if (player.getInventory().isEmpty()) {
|
||||
System.out.println("Inventář je prázdný!");
|
||||
return;
|
||||
}
|
||||
|
||||
// Create a map to group items by ItemType and count occurrences
|
||||
Map<ItemType, Integer> itemCounts = new HashMap<>();
|
||||
List<Item> usableItemList = new ArrayList<>();
|
||||
|
74
frontend/src/main/java/cz/jzitnik/game/PlayerList.java
Normal file
74
frontend/src/main/java/cz/jzitnik/game/PlayerList.java
Normal file
@ -0,0 +1,74 @@
|
||||
package cz.jzitnik.game;
|
||||
|
||||
import cz.jzitnik.api.ApiService;
|
||||
import cz.jzitnik.api.types.Item;
|
||||
import cz.jzitnik.api.types.Player;
|
||||
import cz.jzitnik.utils.Cli;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.apache.hc.core5.http.HttpStatus;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
|
||||
@AllArgsConstructor
|
||||
public class PlayerList {
|
||||
private ApiService apiService;
|
||||
private String playerKey;
|
||||
|
||||
|
||||
public void display() throws IOException {
|
||||
var response = apiService.getAllPlayers(playerKey).execute();
|
||||
var players = response.body().getData().get();
|
||||
|
||||
Cli.printHeader("List všech hráčů");
|
||||
|
||||
for (Player player1 : players) {
|
||||
System.out.println("Jméno: " + Cli.Colors.BLUE + player1.getName() + Cli.Colors.RESET + ", V místnosti: " + Cli.Colors.BLUE + player1.getCurrentRoom() + Cli.Colors.RESET);
|
||||
}
|
||||
|
||||
if (players.size() == 1) {
|
||||
// There is only one player so can't send item to another player
|
||||
return;
|
||||
}
|
||||
|
||||
System.out.println("\n");
|
||||
var options = new String[] { "Předat item hráči", "Zavřít list hráčů"};
|
||||
|
||||
var selectedIndex = Cli.selectOptionIndex(Arrays.asList(options));
|
||||
|
||||
if (selectedIndex == 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Select item from inventory
|
||||
var res = apiService.getMe(playerKey).execute();
|
||||
var me = res.body().getData().get();
|
||||
var inventory = me.getInventory();
|
||||
|
||||
if (inventory.isEmpty()) {
|
||||
Cli.error("Nemáte žádné itemy v inventáři");
|
||||
return;
|
||||
}
|
||||
|
||||
var playerList = players.stream().filter(player -> !player.getId().equals(me.getId())).toList();
|
||||
var playerOptions = playerList.stream().map(Player::getName).toList();
|
||||
|
||||
System.out.println("\n\nVyberte hráče kterému chcete dát item");
|
||||
var selectedPlayerIndex = Cli.selectOptionIndex(playerOptions);
|
||||
var selectedPlayer = playerList.get(selectedPlayerIndex);
|
||||
|
||||
System.out.println("\n\nVyberte item který chcete dát hráči");
|
||||
var items = inventory.stream().map(Item::toString).toList();
|
||||
var selectedItemIndex = Cli.selectOptionIndex(items);
|
||||
var selectedItem = inventory.get(selectedItemIndex);
|
||||
|
||||
var finalResponse = apiService.sendItem(playerKey, selectedItem.getId(), selectedPlayer.getId()).execute();
|
||||
|
||||
if (finalResponse.code() == HttpStatus.SC_CONFLICT) {
|
||||
Cli.error("Hráč " + Cli.Colors.BLUE + selectedPlayer.getName() + Cli.Colors.RESET + " má plný inventář!");
|
||||
return;
|
||||
}
|
||||
|
||||
Cli.success("Item byl úspěšně předán hráči " + Cli.Colors.BLUE + selectedPlayer.getName() + Cli.Colors.RESET + ".");
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user