feat: A lot of new features
This commit is contained in:
		@ -0,0 +1,88 @@
 | 
				
			|||||||
 | 
					package cz.jzitnik.chronos.controllers;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import cz.jzitnik.chronos.entities.Item;
 | 
				
			||||||
 | 
					import cz.jzitnik.chronos.interactions.InteractionService;
 | 
				
			||||||
 | 
					import cz.jzitnik.chronos.payload.requests.InteractionRequest;
 | 
				
			||||||
 | 
					import cz.jzitnik.chronos.payload.responses.InteractionResponse;
 | 
				
			||||||
 | 
					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.utils.anotations.CheckUser;
 | 
				
			||||||
 | 
					import org.springframework.beans.factory.annotation.Autowired;
 | 
				
			||||||
 | 
					import org.springframework.http.HttpStatus;
 | 
				
			||||||
 | 
					import org.springframework.http.ResponseEntity;
 | 
				
			||||||
 | 
					import org.springframework.web.bind.annotation.*;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@CrossOrigin(origins = "*", maxAge = 3600)
 | 
				
			||||||
 | 
					@RestController
 | 
				
			||||||
 | 
					@RequestMapping("/game/characters")
 | 
				
			||||||
 | 
					public class CharacterController {
 | 
				
			||||||
 | 
					    @Autowired
 | 
				
			||||||
 | 
					    private InteractionService interactionService;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Autowired
 | 
				
			||||||
 | 
					    private PlayerRepository playerRepository;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Autowired
 | 
				
			||||||
 | 
					    private CharacterRepository characterRepository;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @PostMapping("/interact")
 | 
				
			||||||
 | 
					    @CheckUser
 | 
				
			||||||
 | 
					    public ResponseEntity<UnifiedResponse<InteractionResponse, Error>> interact(@RequestParam String playerKey, @RequestBody InteractionRequest interactionRequest) {
 | 
				
			||||||
 | 
					        var player = playerRepository.findByPlayerKey(playerKey).get();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        var characterOptional = characterRepository.findById(interactionRequest.getCharacterId());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (characterOptional.isEmpty()) {
 | 
				
			||||||
 | 
					            return ResponseEntity.status(HttpStatus.NOT_FOUND).body(UnifiedResponse.failure(null));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if (!characterOptional.get().getRoom().equals(player.getCurrentRoom())) {
 | 
				
			||||||
 | 
					            return ResponseEntity.badRequest().body(UnifiedResponse.failure(null));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if (characterOptional.get().isInteractedWith()) {
 | 
				
			||||||
 | 
					            return ResponseEntity.noContent().build();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        var interaction = characterOptional.get().getInteraction();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        var interactionFunc = interactionService.mapInteraction(interaction);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        var interactionResponse = interactionFunc.apply(player, characterOptional.get(), interactionRequest.getData());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return ResponseEntity.ok(
 | 
				
			||||||
 | 
					                UnifiedResponse.success(interactionResponse)
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @PostMapping("/take_items")
 | 
				
			||||||
 | 
					    @CheckUser
 | 
				
			||||||
 | 
					    public ResponseEntity<UnifiedResponse<TakeItemsResponse, Error>> takeItems(@RequestParam String playerKey, @RequestParam Long characterId) {
 | 
				
			||||||
 | 
					        var player = playerRepository.findByPlayerKey(playerKey).get();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        var characterOptional = characterRepository.findById(characterId);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (characterOptional.isEmpty()) {
 | 
				
			||||||
 | 
					            return ResponseEntity.status(HttpStatus.NOT_FOUND).body(UnifiedResponse.failure(null));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        var character = characterOptional.get();
 | 
				
			||||||
 | 
					        if (!character.getRoom().equals(player.getCurrentRoom())) {
 | 
				
			||||||
 | 
					            return ResponseEntity.badRequest().body(UnifiedResponse.failure(null));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (character.getPlayersWhoSaw().contains(player)) {
 | 
				
			||||||
 | 
					            return ResponseEntity.ok(UnifiedResponse.success(TakeItemsResponse.ALREADY_TAKEN));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for (Item item : character.getInventory()) {
 | 
				
			||||||
 | 
					            var itemClone = new Item(item.getItemType(), player);
 | 
				
			||||||
 | 
					            player.addItem(itemClone);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        player.getSeenCharacters().add(character);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        playerRepository.save(player);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return ResponseEntity.ok(UnifiedResponse.success(TakeItemsResponse.DONE));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -1,10 +1,16 @@
 | 
				
			|||||||
package cz.jzitnik.chronos.controllers;
 | 
					package cz.jzitnik.chronos.controllers;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import cz.jzitnik.chronos.entities.Game;
 | 
					import cz.jzitnik.chronos.entities.Game;
 | 
				
			||||||
 | 
					import cz.jzitnik.chronos.payload.errors.NotFoundError;
 | 
				
			||||||
 | 
					import cz.jzitnik.chronos.payload.responses.TestGameKeyResponse;
 | 
				
			||||||
import cz.jzitnik.chronos.payload.responses.UnifiedResponse;
 | 
					import cz.jzitnik.chronos.payload.responses.UnifiedResponse;
 | 
				
			||||||
import cz.jzitnik.chronos.repository.GameRepository;
 | 
					import cz.jzitnik.chronos.repository.GameRepository;
 | 
				
			||||||
 | 
					import cz.jzitnik.chronos.repository.PlayerRepository;
 | 
				
			||||||
import cz.jzitnik.chronos.services.GameService;
 | 
					import cz.jzitnik.chronos.services.GameService;
 | 
				
			||||||
 | 
					import cz.jzitnik.chronos.utils.anotations.CheckUser;
 | 
				
			||||||
import org.springframework.beans.factory.annotation.Autowired;
 | 
					import org.springframework.beans.factory.annotation.Autowired;
 | 
				
			||||||
 | 
					import org.springframework.http.HttpStatus;
 | 
				
			||||||
 | 
					import org.springframework.http.ResponseEntity;
 | 
				
			||||||
import org.springframework.web.bind.annotation.*;
 | 
					import org.springframework.web.bind.annotation.*;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@CrossOrigin(origins = "*", maxAge = 3600)
 | 
					@CrossOrigin(origins = "*", maxAge = 3600)
 | 
				
			||||||
@ -17,6 +23,9 @@ public class GameController {
 | 
				
			|||||||
    @Autowired
 | 
					    @Autowired
 | 
				
			||||||
    private GameRepository gameRepository;
 | 
					    private GameRepository gameRepository;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Autowired
 | 
				
			||||||
 | 
					    private PlayerRepository playerRepository;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @PostMapping("/new")
 | 
					    @PostMapping("/new")
 | 
				
			||||||
    public UnifiedResponse<Game, Error> createGame() {
 | 
					    public UnifiedResponse<Game, Error> createGame() {
 | 
				
			||||||
        var game = gameService.createGame();
 | 
					        var game = gameService.createGame();
 | 
				
			||||||
@ -24,4 +33,52 @@ public class GameController {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        return UnifiedResponse.success(game);
 | 
					        return UnifiedResponse.success(game);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @PostMapping("/start")
 | 
				
			||||||
 | 
					    @CheckUser
 | 
				
			||||||
 | 
					    public ResponseEntity<UnifiedResponse<Object, Error>> startGame(@RequestParam String playerKey, @RequestParam String gameKey) {
 | 
				
			||||||
 | 
					        var gameOptional = gameRepository.findByGameKey(gameKey);
 | 
				
			||||||
 | 
					        var player = playerRepository.findByPlayerKey(playerKey).get();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (gameOptional.isEmpty()) {
 | 
				
			||||||
 | 
					            return ResponseEntity.status(HttpStatus.NOT_FOUND).body(
 | 
				
			||||||
 | 
					                    UnifiedResponse.failure(new NotFoundError("Game with key " + gameKey + " was not found!"))
 | 
				
			||||||
 | 
					            );
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        var game = gameOptional.get();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (!game.getAdminPlayer().equals(player)) {
 | 
				
			||||||
 | 
					            return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(
 | 
				
			||||||
 | 
					                    UnifiedResponse.failure(new Error("Not authorized!"))
 | 
				
			||||||
 | 
					            );
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        game.setStarted(true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        gameRepository.save(game);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return ResponseEntity.ok(UnifiedResponse.success(null));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @GetMapping("/test")
 | 
				
			||||||
 | 
					    public ResponseEntity<UnifiedResponse<TestGameKeyResponse, Error>> testGameKey(@RequestParam String gameKey) {
 | 
				
			||||||
 | 
					        var gameOptional = gameRepository.findByGameKey(gameKey);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (gameOptional.isEmpty()) {
 | 
				
			||||||
 | 
					            return ResponseEntity.ok(UnifiedResponse.success(TestGameKeyResponse.INVALID_KEY));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        var game = gameOptional.get();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (game.isStarted()) {
 | 
				
			||||||
 | 
					            return ResponseEntity.ok(UnifiedResponse.success(TestGameKeyResponse.GAME_STARTED));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (game.getPlayers().size() >= 3) {
 | 
				
			||||||
 | 
					            return ResponseEntity.ok(UnifiedResponse.success(TestGameKeyResponse.MAXIUM_PLAYERS));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return ResponseEntity.ok(UnifiedResponse.success(TestGameKeyResponse.WORKING));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -38,8 +38,6 @@ public class PlayerController {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        var player = gameService.addPlayer(game, playerNameRequest.getName());
 | 
					        var player = gameService.addPlayer(game, playerNameRequest.getName());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        gameRepository.save(game);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return ResponseEntity.ok(
 | 
					        return ResponseEntity.ok(
 | 
				
			||||||
                UnifiedResponse.success(player.getPlayerKey())
 | 
					                UnifiedResponse.success(player.getPlayerKey())
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
 | 
				
			|||||||
@ -0,0 +1,60 @@
 | 
				
			|||||||
 | 
					package cz.jzitnik.chronos.controllers;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import cz.jzitnik.chronos.entities.Room;
 | 
				
			||||||
 | 
					import cz.jzitnik.chronos.payload.responses.UnifiedResponse;
 | 
				
			||||||
 | 
					import cz.jzitnik.chronos.repository.PlayerRepository;
 | 
				
			||||||
 | 
					import cz.jzitnik.chronos.repository.RoomRepository;
 | 
				
			||||||
 | 
					import cz.jzitnik.chronos.services.GameService;
 | 
				
			||||||
 | 
					import cz.jzitnik.chronos.utils.anotations.CheckUser;
 | 
				
			||||||
 | 
					import org.springframework.beans.factory.annotation.Autowired;
 | 
				
			||||||
 | 
					import org.springframework.http.HttpStatus;
 | 
				
			||||||
 | 
					import org.springframework.http.ResponseEntity;
 | 
				
			||||||
 | 
					import org.springframework.web.bind.annotation.*;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@CrossOrigin(origins = "*", maxAge = 3600)
 | 
				
			||||||
 | 
					@RestController
 | 
				
			||||||
 | 
					@RequestMapping("/game/rooms")
 | 
				
			||||||
 | 
					public class RoomController {
 | 
				
			||||||
 | 
					    @Autowired
 | 
				
			||||||
 | 
					    private PlayerRepository playerRepository;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Autowired
 | 
				
			||||||
 | 
					    private RoomRepository roomRepository;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Autowired
 | 
				
			||||||
 | 
					    private GameService gameService;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @GetMapping("/current_room")
 | 
				
			||||||
 | 
					    @CheckUser
 | 
				
			||||||
 | 
					    public ResponseEntity<UnifiedResponse<Room, Error>> getCurrentRoom(@RequestParam("playerKey") String playerKey) {
 | 
				
			||||||
 | 
					        var player = playerRepository.findByPlayerKey(playerKey).get();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return ResponseEntity.ok(
 | 
				
			||||||
 | 
					                UnifiedResponse.success(player.getCurrentRoom())
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @PostMapping("/move")
 | 
				
			||||||
 | 
					    @CheckUser
 | 
				
			||||||
 | 
					    public ResponseEntity<UnifiedResponse<Object, Error>> moveToRoom(@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(null));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        var fromThisGame = gameService.isFromThisGame(player.getGame(), roomOptional.get());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (!fromThisGame) {
 | 
				
			||||||
 | 
					            return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(UnifiedResponse.failure(new Error("Invalid roomId")));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        player.setCurrentRoom(roomOptional.get());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        playerRepository.save(player);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return ResponseEntity.ok(UnifiedResponse.success(null));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,19 @@
 | 
				
			|||||||
 | 
					package cz.jzitnik.chronos.controllers;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import cz.jzitnik.chronos.payload.responses.UnifiedResponse;
 | 
				
			||||||
 | 
					import org.springframework.web.bind.annotation.CrossOrigin;
 | 
				
			||||||
 | 
					import org.springframework.web.bind.annotation.GetMapping;
 | 
				
			||||||
 | 
					import org.springframework.web.bind.annotation.RequestMapping;
 | 
				
			||||||
 | 
					import org.springframework.web.bind.annotation.RestController;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@CrossOrigin(origins = "*", maxAge = 3600)
 | 
				
			||||||
 | 
					@RestController
 | 
				
			||||||
 | 
					@RequestMapping("/status")
 | 
				
			||||||
 | 
					public class StatusController {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Don't decode this base64, just go to /status endpoint, you'll be surprised
 | 
				
			||||||
 | 
					    @GetMapping
 | 
				
			||||||
 | 
					    public UnifiedResponse<String, Error> getStatus() {
 | 
				
			||||||
 | 
					        return UnifiedResponse.success("working");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -2,7 +2,9 @@ package cz.jzitnik.chronos.entities;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import com.fasterxml.jackson.annotation.JsonBackReference;
 | 
					import com.fasterxml.jackson.annotation.JsonBackReference;
 | 
				
			||||||
 | 
					import com.fasterxml.jackson.annotation.JsonIgnore;
 | 
				
			||||||
import com.fasterxml.jackson.annotation.JsonManagedReference;
 | 
					import com.fasterxml.jackson.annotation.JsonManagedReference;
 | 
				
			||||||
 | 
					import cz.jzitnik.chronos.interactions.Interaction;
 | 
				
			||||||
import jakarta.persistence.*;
 | 
					import jakarta.persistence.*;
 | 
				
			||||||
import lombok.Getter;
 | 
					import lombok.Getter;
 | 
				
			||||||
import lombok.NoArgsConstructor;
 | 
					import lombok.NoArgsConstructor;
 | 
				
			||||||
@ -15,6 +17,7 @@ import java.util.List;
 | 
				
			|||||||
@Setter
 | 
					@Setter
 | 
				
			||||||
@Entity
 | 
					@Entity
 | 
				
			||||||
@NoArgsConstructor
 | 
					@NoArgsConstructor
 | 
				
			||||||
 | 
					@Table(name = "characters")
 | 
				
			||||||
public class Character {
 | 
					public class Character {
 | 
				
			||||||
    @Id
 | 
					    @Id
 | 
				
			||||||
    @GeneratedValue(strategy = GenerationType.IDENTITY)
 | 
					    @GeneratedValue(strategy = GenerationType.IDENTITY)
 | 
				
			||||||
@ -29,10 +32,16 @@ public class Character {
 | 
				
			|||||||
    @Enumerated(EnumType.STRING)
 | 
					    @Enumerated(EnumType.STRING)
 | 
				
			||||||
    private Interaction interaction;
 | 
					    private Interaction interaction;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private boolean interactedWith;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @ManyToOne
 | 
					    @ManyToOne
 | 
				
			||||||
    @JsonBackReference(value = "room-characters")
 | 
					    @JsonBackReference(value = "room-characters")
 | 
				
			||||||
    private Room room;
 | 
					    private Room room;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @ManyToMany(mappedBy = "seenCharacters", cascade = CascadeType.ALL)
 | 
				
			||||||
 | 
					    @JsonIgnore
 | 
				
			||||||
 | 
					    private List<Player> playersWhoSaw = new ArrayList<>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private String dialog;
 | 
					    private String dialog;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public Character(String name, Room room, String dialog) {
 | 
					    public Character(String name, Room room, String dialog) {
 | 
				
			||||||
 | 
				
			|||||||
@ -1,5 +1,6 @@
 | 
				
			|||||||
package cz.jzitnik.chronos.entities;
 | 
					package cz.jzitnik.chronos.entities;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import com.fasterxml.jackson.annotation.JsonIgnore;
 | 
				
			||||||
import jakarta.persistence.*;
 | 
					import jakarta.persistence.*;
 | 
				
			||||||
import com.fasterxml.jackson.annotation.JsonManagedReference;
 | 
					import com.fasterxml.jackson.annotation.JsonManagedReference;
 | 
				
			||||||
import lombok.Getter;
 | 
					import lombok.Getter;
 | 
				
			||||||
@ -26,9 +27,20 @@ public class Game {
 | 
				
			|||||||
    private List<Player> players = new ArrayList<>();
 | 
					    private List<Player> players = new ArrayList<>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @OneToMany(mappedBy = "game", cascade = CascadeType.ALL)
 | 
					    @OneToMany(mappedBy = "game", cascade = CascadeType.ALL)
 | 
				
			||||||
    @JsonManagedReference(value = "game-rooms")
 | 
					    @JsonIgnore
 | 
				
			||||||
    private List<Room> rooms = new ArrayList<>();
 | 
					    private List<Room> rooms = new ArrayList<>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @OneToOne(cascade = CascadeType.ALL)
 | 
				
			||||||
 | 
					    @JoinColumn(name = "default_room_id", referencedColumnName = "id")
 | 
				
			||||||
 | 
					    private Room defaultRoom;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @OneToOne(cascade = CascadeType.ALL)
 | 
				
			||||||
 | 
					    @JoinColumn(name = "admin_player_id", referencedColumnName = "id")
 | 
				
			||||||
 | 
					    @JsonIgnore
 | 
				
			||||||
 | 
					    private Player adminPlayer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private boolean started = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public void addPlayer(Player player) {
 | 
					    public void addPlayer(Player player) {
 | 
				
			||||||
        this.players.add(player);
 | 
					        this.players.add(player);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
@ -34,4 +34,9 @@ public class Item {
 | 
				
			|||||||
        this.itemType = itemType;
 | 
					        this.itemType = itemType;
 | 
				
			||||||
        this.charowner = charowner;
 | 
					        this.charowner = charowner;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public Item(ItemType itemType, Player owner) {
 | 
				
			||||||
 | 
					        this.itemType = itemType;
 | 
				
			||||||
 | 
					        this.owner = owner;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -33,14 +33,29 @@ public class Player {
 | 
				
			|||||||
    private Game game;
 | 
					    private Game game;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @ManyToOne
 | 
					    @ManyToOne
 | 
				
			||||||
    @Column(name = "current_room")
 | 
					    @JoinColumn(name = "current_room")
 | 
				
			||||||
    private Room currentRoom;
 | 
					    private Room currentRoom;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Column(unique = true, nullable = false)
 | 
					    @Column(unique = true, nullable = false)
 | 
				
			||||||
    @JsonIgnore
 | 
					    @JsonIgnore
 | 
				
			||||||
    private String playerKey;
 | 
					    private String playerKey;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private boolean luck = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @ManyToMany
 | 
				
			||||||
 | 
					    @JoinTable(
 | 
				
			||||||
 | 
					            name = "character_player",
 | 
				
			||||||
 | 
					            joinColumns = @JoinColumn(name = "player_id"),
 | 
				
			||||||
 | 
					            inverseJoinColumns = @JoinColumn(name = "character_id")
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					    @JsonIgnore
 | 
				
			||||||
 | 
					    private List<Character> seenCharacters = new ArrayList<>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public Player(String name) {
 | 
					    public Player(String name) {
 | 
				
			||||||
        this.name = name;
 | 
					        this.name = name;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public void addItem(Item item) {
 | 
				
			||||||
 | 
					        inventory.add(item);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -1,6 +1,5 @@
 | 
				
			|||||||
package cz.jzitnik.chronos.entities;
 | 
					package cz.jzitnik.chronos.entities;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import com.fasterxml.jackson.annotation.JsonBackReference;
 | 
					 | 
				
			||||||
import com.fasterxml.jackson.annotation.JsonIgnore;
 | 
					import com.fasterxml.jackson.annotation.JsonIgnore;
 | 
				
			||||||
import com.fasterxml.jackson.annotation.JsonManagedReference;
 | 
					import com.fasterxml.jackson.annotation.JsonManagedReference;
 | 
				
			||||||
import jakarta.persistence.*;
 | 
					import jakarta.persistence.*;
 | 
				
			||||||
@ -31,13 +30,17 @@ public class Room {
 | 
				
			|||||||
    private List<Character> characters = new ArrayList<>();
 | 
					    private List<Character> characters = new ArrayList<>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @ManyToOne
 | 
					    @ManyToOne
 | 
				
			||||||
    @JsonBackReference(value = "game-rooms")
 | 
					    @JsonIgnore
 | 
				
			||||||
    private Game game;
 | 
					    private Game game;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @OneToMany(mappedBy = "current_room", cascade = CascadeType.ALL)
 | 
					    @OneToMany(mappedBy = "currentRoom", cascade = CascadeType.ALL)
 | 
				
			||||||
    @JsonIgnore
 | 
					    @JsonIgnore
 | 
				
			||||||
    private List<Player> players = new ArrayList<>();
 | 
					    private List<Player> players = new ArrayList<>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @OneToOne(mappedBy = "defaultRoom")
 | 
				
			||||||
 | 
					    @JsonIgnore
 | 
				
			||||||
 | 
					    private Game gameDefault;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public Room(String name, Game game) {
 | 
					    public Room(String name, Game game) {
 | 
				
			||||||
        this.name = name;
 | 
					        this.name = name;
 | 
				
			||||||
        this.game = game;
 | 
					        this.game = game;
 | 
				
			||||||
 | 
				
			|||||||
@ -0,0 +1,5 @@
 | 
				
			|||||||
 | 
					package cz.jzitnik.chronos.interactions;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public enum Interaction {
 | 
				
			||||||
 | 
					    Farmer
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,80 @@
 | 
				
			|||||||
 | 
					package cz.jzitnik.chronos.interactions;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import cz.jzitnik.chronos.entities.Item;
 | 
				
			||||||
 | 
					import cz.jzitnik.chronos.entities.ItemType;
 | 
				
			||||||
 | 
					import cz.jzitnik.chronos.entities.Player;
 | 
				
			||||||
 | 
					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 org.springframework.beans.factory.annotation.Autowired;
 | 
				
			||||||
 | 
					import org.springframework.stereotype.Service;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.util.Random;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@Service
 | 
				
			||||||
 | 
					public class InteractionService {
 | 
				
			||||||
 | 
					    @Autowired
 | 
				
			||||||
 | 
					    private PlayerRepository playerRepository;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Autowired
 | 
				
			||||||
 | 
					    private CharacterRepository characterRepository;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @FunctionalInterface
 | 
				
			||||||
 | 
					    public interface Function3<T, U, V, W> {
 | 
				
			||||||
 | 
					        W apply(T t, U u, V v);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public Function3<Player, Character, String, InteractionResponse> mapInteraction(Interaction interaction) {
 | 
				
			||||||
 | 
					        return switch (interaction) {
 | 
				
			||||||
 | 
					            case Farmer -> ((player, character, data) -> {
 | 
				
			||||||
 | 
					                Random random = new Random();
 | 
				
			||||||
 | 
					                boolean isLucky = player.isLuck();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                int characterChoice = random.nextInt(3);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                int userChoice = switch (data) {
 | 
				
			||||||
 | 
					                    case "0" -> 0; // Rock
 | 
				
			||||||
 | 
					                    case "1" -> 1; // Paper
 | 
				
			||||||
 | 
					                    case "2" -> 2; // Scissors
 | 
				
			||||||
 | 
					                    default -> throw new IllegalArgumentException("Invalid choice");
 | 
				
			||||||
 | 
					                };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if (isLucky) {
 | 
				
			||||||
 | 
					                    // 50/50 chance
 | 
				
			||||||
 | 
					                    boolean playerWins = random.nextBoolean();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    // Reset the luck potion after use
 | 
				
			||||||
 | 
					                    player.setLuck(false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    if (playerWins) {
 | 
				
			||||||
 | 
					                        player.addItem(new Item(ItemType.KEY_FRAGMENT, player));
 | 
				
			||||||
 | 
					                        playerRepository.save(player);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        character.setInteractedWith(true);
 | 
				
			||||||
 | 
					                        characterRepository.save(character);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        return new InteractionResponse(true, "Vyhrál jsi, dostáváš jeden fragment klíče.");
 | 
				
			||||||
 | 
					                    } else {
 | 
				
			||||||
 | 
					                        return new InteractionResponse(false, "Prohrál jsi");
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                    // Standard rock-paper-scissors game logic
 | 
				
			||||||
 | 
					                    if (userChoice == characterChoice) {
 | 
				
			||||||
 | 
					                        return new InteractionResponse(false, "Remíza, oběma hráčům se podařilo uhádnout.");
 | 
				
			||||||
 | 
					                    } else if ((userChoice == 0 && characterChoice == 2) || (userChoice == 1 && characterChoice == 0) || (userChoice == 2 && characterChoice == 1)) {
 | 
				
			||||||
 | 
					                        player.addItem(new Item(ItemType.KEY_FRAGMENT, player));
 | 
				
			||||||
 | 
					                        playerRepository.save(player);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        character.setInteractedWith(true);
 | 
				
			||||||
 | 
					                        characterRepository.save(character);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        return new InteractionResponse(true, "Vyhrál jsi, dostáváš jeden fragment klíče.");
 | 
				
			||||||
 | 
					                    } else {
 | 
				
			||||||
 | 
					                        return new InteractionResponse(false, "Prohrál jsi");
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -1,12 +1,7 @@
 | 
				
			|||||||
package cz.jzitnik.chronos.payload.errors;
 | 
					package cz.jzitnik.chronos.payload.errors;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public class NotFoundError extends Error {
 | 
					public class NotFoundError extends Error {
 | 
				
			||||||
    public NotFoundError() {
 | 
					 | 
				
			||||||
        super("Not Found Error");
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public NotFoundError(String message) {
 | 
					    public NotFoundError(String message) {
 | 
				
			||||||
        super(message);
 | 
					        super(message);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -0,0 +1,7 @@
 | 
				
			|||||||
 | 
					package cz.jzitnik.chronos.payload.errors;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public class PlayerNotFoundError extends Error {
 | 
				
			||||||
 | 
					    public PlayerNotFoundError(String message) {
 | 
				
			||||||
 | 
					        super(message);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,13 @@
 | 
				
			|||||||
 | 
					package cz.jzitnik.chronos.payload.requests;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import lombok.AllArgsConstructor;
 | 
				
			||||||
 | 
					import lombok.Getter;
 | 
				
			||||||
 | 
					import lombok.NoArgsConstructor;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@Getter
 | 
				
			||||||
 | 
					@AllArgsConstructor
 | 
				
			||||||
 | 
					@NoArgsConstructor
 | 
				
			||||||
 | 
					public class InteractionRequest {
 | 
				
			||||||
 | 
					    private String data;
 | 
				
			||||||
 | 
					    private Long characterId;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,13 @@
 | 
				
			|||||||
 | 
					package cz.jzitnik.chronos.payload.responses;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import lombok.AllArgsConstructor;
 | 
				
			||||||
 | 
					import lombok.Getter;
 | 
				
			||||||
 | 
					import lombok.Setter;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@Getter
 | 
				
			||||||
 | 
					@Setter
 | 
				
			||||||
 | 
					@AllArgsConstructor
 | 
				
			||||||
 | 
					public class InteractionResponse {
 | 
				
			||||||
 | 
					    private boolean success;
 | 
				
			||||||
 | 
					    private String responseText;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,6 @@
 | 
				
			|||||||
 | 
					package cz.jzitnik.chronos.payload.responses;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public enum TakeItemsResponse {
 | 
				
			||||||
 | 
					    DONE,
 | 
				
			||||||
 | 
					    ALREADY_TAKEN
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,8 @@
 | 
				
			|||||||
 | 
					package cz.jzitnik.chronos.payload.responses;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public enum TestGameKeyResponse {
 | 
				
			||||||
 | 
					    WORKING,
 | 
				
			||||||
 | 
					    GAME_STARTED,
 | 
				
			||||||
 | 
					    INVALID_KEY,
 | 
				
			||||||
 | 
					    MAXIUM_PLAYERS
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -5,14 +5,12 @@ import lombok.Setter;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import java.util.Optional;
 | 
					import java.util.Optional;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public class UnifiedResponse<T, U> {
 | 
					 | 
				
			||||||
@Getter
 | 
					@Getter
 | 
				
			||||||
 | 
					public class UnifiedResponse<T, U> {
 | 
				
			||||||
    private final Optional<T> data;
 | 
					    private final Optional<T> data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Getter
 | 
					 | 
				
			||||||
    private final Optional<U> error;
 | 
					    private final Optional<U> error;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Getter
 | 
					 | 
				
			||||||
    private final Boolean success;
 | 
					    private final Boolean success;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private UnifiedResponse(Optional<T> data, Optional<U> error, Boolean success) {
 | 
					    private UnifiedResponse(Optional<T> data, Optional<U> error, Boolean success) {
 | 
				
			||||||
 | 
				
			|||||||
@ -0,0 +1,11 @@
 | 
				
			|||||||
 | 
					package cz.jzitnik.chronos.repository;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import cz.jzitnik.chronos.entities.Character;
 | 
				
			||||||
 | 
					import org.springframework.data.jpa.repository.JpaRepository;
 | 
				
			||||||
 | 
					import org.springframework.stereotype.Repository;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@Repository
 | 
				
			||||||
 | 
					public interface CharacterRepository extends JpaRepository<Character, Long> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -4,7 +4,10 @@ import cz.jzitnik.chronos.entities.Player;
 | 
				
			|||||||
import org.springframework.data.jpa.repository.JpaRepository;
 | 
					import org.springframework.data.jpa.repository.JpaRepository;
 | 
				
			||||||
import org.springframework.stereotype.Repository;
 | 
					import org.springframework.stereotype.Repository;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.util.Optional;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@Repository
 | 
					@Repository
 | 
				
			||||||
public interface PlayerRepository extends JpaRepository<Player, Long> {
 | 
					public interface PlayerRepository extends JpaRepository<Player, Long> {
 | 
				
			||||||
    boolean existsByPlayerKey(String playerKey);
 | 
					    boolean existsByPlayerKey(String playerKey);
 | 
				
			||||||
 | 
					    Optional<Player> findByPlayerKey(String playerKey);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -0,0 +1,11 @@
 | 
				
			|||||||
 | 
					package cz.jzitnik.chronos.repository;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import cz.jzitnik.chronos.entities.Room;
 | 
				
			||||||
 | 
					import org.springframework.data.jpa.repository.JpaRepository;
 | 
				
			||||||
 | 
					import org.springframework.stereotype.Repository;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@Repository
 | 
				
			||||||
 | 
					public interface RoomRepository extends JpaRepository<Room, Long> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -2,6 +2,7 @@ package cz.jzitnik.chronos.services;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import cz.jzitnik.chronos.entities.Game;
 | 
					import cz.jzitnik.chronos.entities.Game;
 | 
				
			||||||
import cz.jzitnik.chronos.entities.Player;
 | 
					import cz.jzitnik.chronos.entities.Player;
 | 
				
			||||||
 | 
					import cz.jzitnik.chronos.entities.Room;
 | 
				
			||||||
import cz.jzitnik.chronos.repository.GameRepository;
 | 
					import cz.jzitnik.chronos.repository.GameRepository;
 | 
				
			||||||
import cz.jzitnik.chronos.repository.PlayerRepository;
 | 
					import cz.jzitnik.chronos.repository.PlayerRepository;
 | 
				
			||||||
import org.springframework.beans.factory.annotation.Autowired;
 | 
					import org.springframework.beans.factory.annotation.Autowired;
 | 
				
			||||||
@ -59,7 +60,9 @@ public class GameService {
 | 
				
			|||||||
        Game newGame = new Game();
 | 
					        Game newGame = new Game();
 | 
				
			||||||
        newGame.setGameKey(generateUniqueGameKey());
 | 
					        newGame.setGameKey(generateUniqueGameKey());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        initGameService.initGame(newGame);
 | 
					        var defaultRoom = initGameService.initGame(newGame);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        newGame.setDefaultRoom(defaultRoom);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return gameRepository.save(newGame);
 | 
					        return gameRepository.save(newGame);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -68,9 +71,21 @@ public class GameService {
 | 
				
			|||||||
        var player = new Player(playerName);
 | 
					        var player = new Player(playerName);
 | 
				
			||||||
        player.setPlayerKey(generateUniquePlayerKey());
 | 
					        player.setPlayerKey(generateUniquePlayerKey());
 | 
				
			||||||
        player.setGame(game);
 | 
					        player.setGame(game);
 | 
				
			||||||
 | 
					        player.setCurrentRoom(game.getDefaultRoom());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (game.getPlayers().isEmpty()) {
 | 
				
			||||||
 | 
					            game.setAdminPlayer(player);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        game.addPlayer(player);
 | 
					        game.addPlayer(player);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        gameRepository.save(game);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return player;
 | 
					        return player;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public boolean isFromThisGame(Game game, Room room) {
 | 
				
			||||||
 | 
					        return game.getRooms().stream().anyMatch(rm -> rm.equals(room));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -2,16 +2,16 @@ package cz.jzitnik.chronos.services;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import cz.jzitnik.chronos.entities.*;
 | 
					import cz.jzitnik.chronos.entities.*;
 | 
				
			||||||
import cz.jzitnik.chronos.entities.Character;
 | 
					import cz.jzitnik.chronos.entities.Character;
 | 
				
			||||||
 | 
					import cz.jzitnik.chronos.interactions.Interaction;
 | 
				
			||||||
import org.springframework.stereotype.Service;
 | 
					import org.springframework.stereotype.Service;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import java.util.ArrayList;
 | 
					import java.util.ArrayList;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@Service
 | 
					@Service
 | 
				
			||||||
public class InitGameService {
 | 
					public class InitGameService {
 | 
				
			||||||
    public void initGame(Game game) {
 | 
					    public Room initGame(Game game) {
 | 
				
			||||||
        var rooms = new ArrayList<Room>();
 | 
					        var rooms = new ArrayList<Room>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
        // Outside
 | 
					        // Outside
 | 
				
			||||||
        var outside = new Room(
 | 
					        var outside = new Room(
 | 
				
			||||||
                "Outside", // Name
 | 
					                "Outside", // Name
 | 
				
			||||||
@ -48,5 +48,8 @@ public class InitGameService {
 | 
				
			|||||||
        rooms.add(stodola);
 | 
					        rooms.add(stodola);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        game.setRooms(rooms);
 | 
					        game.setRooms(rooms);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Return a room that all players will spawn in
 | 
				
			||||||
 | 
					        return outside;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -0,0 +1,11 @@
 | 
				
			|||||||
 | 
					package cz.jzitnik.chronos.utils.anotations;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.lang.annotation.ElementType;
 | 
				
			||||||
 | 
					import java.lang.annotation.Retention;
 | 
				
			||||||
 | 
					import java.lang.annotation.RetentionPolicy;
 | 
				
			||||||
 | 
					import java.lang.annotation.Target;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@Target(ElementType.METHOD)
 | 
				
			||||||
 | 
					@Retention(RetentionPolicy.RUNTIME)
 | 
				
			||||||
 | 
					public @interface CheckUser {
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,35 @@
 | 
				
			|||||||
 | 
					package cz.jzitnik.chronos.utils.anotations;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import cz.jzitnik.chronos.payload.errors.PlayerNotFoundError;
 | 
				
			||||||
 | 
					import cz.jzitnik.chronos.payload.responses.UnifiedResponse;
 | 
				
			||||||
 | 
					import cz.jzitnik.chronos.repository.PlayerRepository;
 | 
				
			||||||
 | 
					import org.aspectj.lang.ProceedingJoinPoint;
 | 
				
			||||||
 | 
					import org.aspectj.lang.annotation.Around;
 | 
				
			||||||
 | 
					import org.aspectj.lang.annotation.Aspect;
 | 
				
			||||||
 | 
					import org.springframework.beans.factory.annotation.Autowired;
 | 
				
			||||||
 | 
					import org.springframework.http.HttpStatus;
 | 
				
			||||||
 | 
					import org.springframework.http.ResponseEntity;
 | 
				
			||||||
 | 
					import org.springframework.stereotype.Component;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@Aspect
 | 
				
			||||||
 | 
					@Component
 | 
				
			||||||
 | 
					public class UserCheckAspect {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Autowired
 | 
				
			||||||
 | 
					    private PlayerRepository playerRepository;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Around("@annotation(CheckUser)")
 | 
				
			||||||
 | 
					    public Object checkUser(ProceedingJoinPoint joinPoint) throws Throwable {
 | 
				
			||||||
 | 
					        String playerKey = (String) joinPoint.getArgs()[0]; // Assuming playerKey is the first argument
 | 
				
			||||||
 | 
					        var playerOptional = playerRepository.findByPlayerKey(playerKey);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (playerOptional.isEmpty()) {
 | 
				
			||||||
 | 
					            return ResponseEntity
 | 
				
			||||||
 | 
					                    .status(HttpStatus.NOT_FOUND)
 | 
				
			||||||
 | 
					                    .body(UnifiedResponse.failure(new PlayerNotFoundError("Player was not found!")));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Proceed with the original method if the player exists
 | 
				
			||||||
 | 
					        return joinPoint.proceed();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -1,17 +0,0 @@
 | 
				
			|||||||
<?xml version="1.0" encoding="UTF-8"?>
 | 
					 | 
				
			||||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
 | 
					 | 
				
			||||||
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 | 
					 | 
				
			||||||
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 | 
					 | 
				
			||||||
    <modelVersion>4.0.0</modelVersion>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    <groupId>cz.jzitnik</groupId>
 | 
					 | 
				
			||||||
    <artifactId>chronos</artifactId>
 | 
					 | 
				
			||||||
    <version>1.0-SNAPSHOT</version>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    <properties>
 | 
					 | 
				
			||||||
        <maven.compiler.source>23</maven.compiler.source>
 | 
					 | 
				
			||||||
        <maven.compiler.target>23</maven.compiler.target>
 | 
					 | 
				
			||||||
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
 | 
					 | 
				
			||||||
    </properties>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
</project>
 | 
					 | 
				
			||||||
@ -1,7 +0,0 @@
 | 
				
			|||||||
package cz.jzitnik;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
public class Main {
 | 
					 | 
				
			||||||
    public static void main(String[] args) {
 | 
					 | 
				
			||||||
        System.out.println("Hello, World!");
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										0
									
								
								chronos/.idea/.gitignore → frontend/.idea/.gitignore
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										0
									
								
								chronos/.idea/.gitignore → frontend/.idea/.gitignore
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
								
								
									
										2
									
								
								chronos/.idea/misc.xml → frontend/.idea/misc.xml
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										2
									
								
								chronos/.idea/misc.xml → frontend/.idea/misc.xml
									
									
									
										generated
									
									
									
								
							@ -8,7 +8,7 @@
 | 
				
			|||||||
      </list>
 | 
					      </list>
 | 
				
			||||||
    </option>
 | 
					    </option>
 | 
				
			||||||
  </component>
 | 
					  </component>
 | 
				
			||||||
  <component name="ProjectRootManager" version="2" languageLevel="JDK_23" default="true" project-jdk-name="20" project-jdk-type="JavaSDK">
 | 
					  <component name="ProjectRootManager" version="2" languageLevel="JDK_23" default="true" project-jdk-name="openjdk-23" project-jdk-type="JavaSDK">
 | 
				
			||||||
    <output url="file://$PROJECT_DIR$/out" />
 | 
					    <output url="file://$PROJECT_DIR$/out" />
 | 
				
			||||||
  </component>
 | 
					  </component>
 | 
				
			||||||
</project>
 | 
					</project>
 | 
				
			||||||
							
								
								
									
										6
									
								
								frontend/.idea/vcs.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								frontend/.idea/vcs.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							@ -0,0 +1,6 @@
 | 
				
			|||||||
 | 
					<?xml version="1.0" encoding="UTF-8"?>
 | 
				
			||||||
 | 
					<project version="4">
 | 
				
			||||||
 | 
					  <component name="VcsDirectoryMappings">
 | 
				
			||||||
 | 
					    <mapping directory="$PROJECT_DIR$/.." vcs="Git" />
 | 
				
			||||||
 | 
					  </component>
 | 
				
			||||||
 | 
					</project>
 | 
				
			||||||
							
								
								
									
										51
									
								
								frontend/pom.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								frontend/pom.xml
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,51 @@
 | 
				
			|||||||
 | 
					<?xml version="1.0" encoding="UTF-8"?>
 | 
				
			||||||
 | 
					<project xmlns="http://maven.apache.org/POM/4.0.0"
 | 
				
			||||||
 | 
					         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 | 
				
			||||||
 | 
					         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 | 
				
			||||||
 | 
					    <modelVersion>4.0.0</modelVersion>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <groupId>cz.jzitnik</groupId>
 | 
				
			||||||
 | 
					    <artifactId>chronos</artifactId>
 | 
				
			||||||
 | 
					    <version>1.0-SNAPSHOT</version>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <properties>
 | 
				
			||||||
 | 
					        <maven.compiler.source>23</maven.compiler.source>
 | 
				
			||||||
 | 
					        <maven.compiler.target>23</maven.compiler.target>
 | 
				
			||||||
 | 
					        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
 | 
				
			||||||
 | 
					        <java.version>23</java.version>
 | 
				
			||||||
 | 
					    </properties>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <dependencies>
 | 
				
			||||||
 | 
					        <dependency>
 | 
				
			||||||
 | 
					            <groupId>com.squareup.retrofit2</groupId>
 | 
				
			||||||
 | 
					            <artifactId>retrofit</artifactId>
 | 
				
			||||||
 | 
					            <version>2.9.0</version>
 | 
				
			||||||
 | 
					        </dependency>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        <dependency>
 | 
				
			||||||
 | 
					            <groupId>com.squareup.retrofit2</groupId>
 | 
				
			||||||
 | 
					            <artifactId>converter-jackson</artifactId>
 | 
				
			||||||
 | 
					            <version>2.9.0</version>
 | 
				
			||||||
 | 
					        </dependency>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        <dependency>
 | 
				
			||||||
 | 
					            <groupId>org.apache.httpcomponents.client5</groupId>
 | 
				
			||||||
 | 
					            <artifactId>httpclient5</artifactId>
 | 
				
			||||||
 | 
					            <version>5.2</version>
 | 
				
			||||||
 | 
					        </dependency>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        <dependency>
 | 
				
			||||||
 | 
					            <groupId>org.projectlombok</groupId>
 | 
				
			||||||
 | 
					            <artifactId>lombok</artifactId>
 | 
				
			||||||
 | 
					            <optional>true</optional>
 | 
				
			||||||
 | 
					            <version>1.18.36</version>
 | 
				
			||||||
 | 
					        </dependency>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        <dependency>
 | 
				
			||||||
 | 
					            <groupId>com.fasterxml.jackson.core</groupId>
 | 
				
			||||||
 | 
					            <artifactId>jackson-databind</artifactId>
 | 
				
			||||||
 | 
					            <version>2.15.2</version> <!-- Use the latest version -->
 | 
				
			||||||
 | 
					        </dependency>
 | 
				
			||||||
 | 
					    </dependencies>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					</project>
 | 
				
			||||||
							
								
								
									
										56
									
								
								frontend/src/main/java/cz/jzitnik/Main.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								frontend/src/main/java/cz/jzitnik/Main.java
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,56 @@
 | 
				
			|||||||
 | 
					package cz.jzitnik;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import cz.jzitnik.game.Chronos;
 | 
				
			||||||
 | 
					import cz.jzitnik.utils.Cli;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.io.IOException;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public class Main {
 | 
				
			||||||
 | 
					    public static void main(String[] args) throws IOException {
 | 
				
			||||||
 | 
					        Chronos chronos = new Chronos();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Cli.printHeader("Načítání hry Chronos");
 | 
				
			||||||
 | 
					        Cli.info("Načítání konfigurace...");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (chronos.hasConfig()) {
 | 
				
			||||||
 | 
					            chronos.loadData();
 | 
				
			||||||
 | 
					            Cli.success("Konfigurace byla úspěšně nalezena a načtena!");
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            // Setup a server
 | 
				
			||||||
 | 
					            Cli.info("Konfigurace nebyla nalezena! Vytvářím novou.");
 | 
				
			||||||
 | 
					            chronos.setup();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (!chronos.hasUser()) {
 | 
				
			||||||
 | 
					            System.out.println();
 | 
				
			||||||
 | 
					            Cli.type("Nyní si buď vytvoříte vlastní hru a nebo se připojíte do již existující hry");
 | 
				
			||||||
 | 
					            System.out.println();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            String[] options = {"Vytvořit novou hru", "Připojit se do již existující hry"};
 | 
				
			||||||
 | 
					            var option = Cli.selectOption(options);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            switch (option) {
 | 
				
			||||||
 | 
					                case "Vytvořit novou hru":
 | 
				
			||||||
 | 
					                    chronos.createNewGame();
 | 
				
			||||||
 | 
					                    chronos.addUser();
 | 
				
			||||||
 | 
					                    Cli.success("Byl jste úspěšně zaregistrován jako první hráč!");
 | 
				
			||||||
 | 
					                    chronos.adminPanel();
 | 
				
			||||||
 | 
					                    break;
 | 
				
			||||||
 | 
					                case "Připojit se do hry":
 | 
				
			||||||
 | 
					                    chronos.connectToExisting();
 | 
				
			||||||
 | 
					                    chronos.addUser();
 | 
				
			||||||
 | 
					                    Cli.success("Byl jste úspěšně zaregistrován jako hráč!");
 | 
				
			||||||
 | 
					                    break;
 | 
				
			||||||
 | 
					                default:
 | 
				
			||||||
 | 
					                    System.out.println("Error"); // This will never happen
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        chronos.waitForStart();
 | 
				
			||||||
 | 
					        Cli.info("Hra začala!");
 | 
				
			||||||
 | 
					        System.out.println("\n\n");
 | 
				
			||||||
 | 
					        Cli.printHeader("Chronos");
 | 
				
			||||||
 | 
					        chronos.visit();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										55
									
								
								frontend/src/main/java/cz/jzitnik/api/ApiService.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								frontend/src/main/java/cz/jzitnik/api/ApiService.java
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,55 @@
 | 
				
			|||||||
 | 
					package cz.jzitnik.api;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import cz.jzitnik.api.requests.PlayerNameRequest;
 | 
				
			||||||
 | 
					import cz.jzitnik.api.responses.UnifiedResponse;
 | 
				
			||||||
 | 
					import cz.jzitnik.api.types.Game;
 | 
				
			||||||
 | 
					import cz.jzitnik.api.types.Room;
 | 
				
			||||||
 | 
					import cz.jzitnik.api.types.TakeItemsResponse;
 | 
				
			||||||
 | 
					import cz.jzitnik.api.types.TestGameKeyResponse;
 | 
				
			||||||
 | 
					import retrofit2.Call;
 | 
				
			||||||
 | 
					import retrofit2.http.Body;
 | 
				
			||||||
 | 
					import retrofit2.http.GET;
 | 
				
			||||||
 | 
					import retrofit2.http.POST;
 | 
				
			||||||
 | 
					import retrofit2.http.Query;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public interface ApiService {
 | 
				
			||||||
 | 
					    @GET("status")
 | 
				
			||||||
 | 
					    Call<UnifiedResponse<String, Error>> status();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @POST("game/new")
 | 
				
			||||||
 | 
					    Call<UnifiedResponse<Game, Error>> newGame();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @POST("game/players/new")
 | 
				
			||||||
 | 
					    Call<UnifiedResponse<String, Error>> newPlayer(
 | 
				
			||||||
 | 
					            @Query("gameKey") String gameKey,
 | 
				
			||||||
 | 
					            @Body PlayerNameRequest requestBody
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @POST("game/start")
 | 
				
			||||||
 | 
					    Call<UnifiedResponse<Object, Error>> startGame(
 | 
				
			||||||
 | 
					            @Query("playerKey") String playerKey,
 | 
				
			||||||
 | 
					            @Query("gameKey") String gameKey
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @GET("game/test")
 | 
				
			||||||
 | 
					    Call<UnifiedResponse<TestGameKeyResponse, Error>> testGameKey(
 | 
				
			||||||
 | 
					            @Query("gameKey") String gameKey
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @GET("game/rooms/current_room")
 | 
				
			||||||
 | 
					    Call<UnifiedResponse<Room, Error>> getCurrentRoom(
 | 
				
			||||||
 | 
					            @Query("playerKey") String playerKey
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @POST("game/rooms/move")
 | 
				
			||||||
 | 
					    Call<UnifiedResponse<Object, Error>> moveToRoom(
 | 
				
			||||||
 | 
					            @Query("playerKey") String playerKey,
 | 
				
			||||||
 | 
					            @Query("roomId") Long roomId
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @POST("game/characters/take_items")
 | 
				
			||||||
 | 
					    Call<UnifiedResponse<TakeItemsResponse, Error>> takeItems(
 | 
				
			||||||
 | 
					            @Query("playerKey") String playerKey,
 | 
				
			||||||
 | 
					            @Query("characterId") Long characterId
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,12 @@
 | 
				
			|||||||
 | 
					package cz.jzitnik.api.requests;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import lombok.AllArgsConstructor;
 | 
				
			||||||
 | 
					import lombok.Getter;
 | 
				
			||||||
 | 
					import lombok.Setter;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@Getter
 | 
				
			||||||
 | 
					@Setter
 | 
				
			||||||
 | 
					@AllArgsConstructor
 | 
				
			||||||
 | 
					public class PlayerNameRequest {
 | 
				
			||||||
 | 
					    private String name;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,20 @@
 | 
				
			|||||||
 | 
					package cz.jzitnik.api.responses;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import lombok.Getter;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.util.Optional;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@Getter
 | 
				
			||||||
 | 
					public class UnifiedResponse<T, U> {
 | 
				
			||||||
 | 
					    private Optional<T> data;
 | 
				
			||||||
 | 
					    private Optional<U> error;
 | 
				
			||||||
 | 
					    private Boolean success;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public void setData(T data) {
 | 
				
			||||||
 | 
					        this.data = Optional.ofNullable(data);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public void setError(U error) {
 | 
				
			||||||
 | 
					        this.error = Optional.ofNullable(error);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										24
									
								
								frontend/src/main/java/cz/jzitnik/api/types/Character.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								frontend/src/main/java/cz/jzitnik/api/types/Character.java
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,24 @@
 | 
				
			|||||||
 | 
					package cz.jzitnik.api.types;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import lombok.Getter;
 | 
				
			||||||
 | 
					import lombok.NoArgsConstructor;
 | 
				
			||||||
 | 
					import lombok.Setter;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.util.List;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@Getter
 | 
				
			||||||
 | 
					@Setter
 | 
				
			||||||
 | 
					@NoArgsConstructor
 | 
				
			||||||
 | 
					public class Character {
 | 
				
			||||||
 | 
					    private Long id;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private String name;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private List<Item> inventory;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private Interaction interaction;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private boolean interactedWith;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private String dialog;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										24
									
								
								frontend/src/main/java/cz/jzitnik/api/types/Game.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								frontend/src/main/java/cz/jzitnik/api/types/Game.java
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,24 @@
 | 
				
			|||||||
 | 
					package cz.jzitnik.api.types;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import lombok.AllArgsConstructor;
 | 
				
			||||||
 | 
					import lombok.Getter;
 | 
				
			||||||
 | 
					import lombok.NoArgsConstructor;
 | 
				
			||||||
 | 
					import lombok.Setter;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.util.List;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@Getter
 | 
				
			||||||
 | 
					@Setter
 | 
				
			||||||
 | 
					@NoArgsConstructor
 | 
				
			||||||
 | 
					@AllArgsConstructor
 | 
				
			||||||
 | 
					public class Game {
 | 
				
			||||||
 | 
					    private Long id;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private String gameKey;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private List<Player> players;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private Room defaultRoom;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private boolean started;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -1,4 +1,4 @@
 | 
				
			|||||||
package cz.jzitnik.chronos.entities;
 | 
					package cz.jzitnik.api.types;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public enum Interaction {
 | 
					public enum Interaction {
 | 
				
			||||||
    Farmer
 | 
					    Farmer
 | 
				
			||||||
							
								
								
									
										12
									
								
								frontend/src/main/java/cz/jzitnik/api/types/Item.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								frontend/src/main/java/cz/jzitnik/api/types/Item.java
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,12 @@
 | 
				
			|||||||
 | 
					package cz.jzitnik.api.types;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import lombok.Getter;
 | 
				
			||||||
 | 
					import lombok.Setter;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@Getter
 | 
				
			||||||
 | 
					@Setter
 | 
				
			||||||
 | 
					public class Item {
 | 
				
			||||||
 | 
					    private Long id;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private ItemType itemType;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,6 @@
 | 
				
			|||||||
 | 
					package cz.jzitnik.api.types;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public enum ItemType {
 | 
				
			||||||
 | 
					    KEY_FRAGMENT,
 | 
				
			||||||
 | 
					    LUCK_POTION
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										18
									
								
								frontend/src/main/java/cz/jzitnik/api/types/Player.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								frontend/src/main/java/cz/jzitnik/api/types/Player.java
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,18 @@
 | 
				
			|||||||
 | 
					package cz.jzitnik.api.types;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import lombok.Getter;
 | 
				
			||||||
 | 
					import lombok.Setter;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.util.List;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@Getter
 | 
				
			||||||
 | 
					@Setter
 | 
				
			||||||
 | 
					public class Player {
 | 
				
			||||||
 | 
					    private Long id;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private String name;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private List<Item> inventory;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private Room currentRoom;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										18
									
								
								frontend/src/main/java/cz/jzitnik/api/types/Room.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								frontend/src/main/java/cz/jzitnik/api/types/Room.java
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,18 @@
 | 
				
			|||||||
 | 
					package cz.jzitnik.api.types;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import lombok.Getter;
 | 
				
			||||||
 | 
					import lombok.Setter;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.util.List;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@Getter
 | 
				
			||||||
 | 
					@Setter
 | 
				
			||||||
 | 
					public class Room {
 | 
				
			||||||
 | 
					    private Long id;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private String name;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private List<Item> items;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private List<Character> characters;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,6 @@
 | 
				
			|||||||
 | 
					package cz.jzitnik.api.types;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public enum TakeItemsResponse {
 | 
				
			||||||
 | 
					    DONE,
 | 
				
			||||||
 | 
					    ALREADY_TAKEN
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,8 @@
 | 
				
			|||||||
 | 
					package cz.jzitnik.api.types;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public enum TestGameKeyResponse {
 | 
				
			||||||
 | 
					    WORKING,
 | 
				
			||||||
 | 
					    GAME_STARTED,
 | 
				
			||||||
 | 
					    INVALID_KEY,
 | 
				
			||||||
 | 
					    MAXIUM_PLAYERS
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										243
									
								
								frontend/src/main/java/cz/jzitnik/game/Chronos.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										243
									
								
								frontend/src/main/java/cz/jzitnik/game/Chronos.java
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,243 @@
 | 
				
			|||||||
 | 
					package cz.jzitnik.game;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import cz.jzitnik.api.ApiService;
 | 
				
			||||||
 | 
					import cz.jzitnik.api.requests.PlayerNameRequest;
 | 
				
			||||||
 | 
					import cz.jzitnik.api.types.Character;
 | 
				
			||||||
 | 
					import cz.jzitnik.api.types.Room;
 | 
				
			||||||
 | 
					import cz.jzitnik.api.types.TakeItemsResponse;
 | 
				
			||||||
 | 
					import cz.jzitnik.api.types.TestGameKeyResponse;
 | 
				
			||||||
 | 
					import cz.jzitnik.utils.Cli;
 | 
				
			||||||
 | 
					import cz.jzitnik.utils.ConfigPathProvider;
 | 
				
			||||||
 | 
					import lombok.Getter;
 | 
				
			||||||
 | 
					import lombok.NoArgsConstructor;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.io.Console;
 | 
				
			||||||
 | 
					import java.io.File;
 | 
				
			||||||
 | 
					import java.io.IOException;
 | 
				
			||||||
 | 
					import java.net.ConnectException;
 | 
				
			||||||
 | 
					import java.nio.file.Files;
 | 
				
			||||||
 | 
					import java.nio.file.Path;
 | 
				
			||||||
 | 
					import java.util.Arrays;
 | 
				
			||||||
 | 
					import java.util.Objects;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import com.fasterxml.jackson.databind.ObjectMapper;
 | 
				
			||||||
 | 
					import retrofit2.Retrofit;
 | 
				
			||||||
 | 
					import retrofit2.converter.jackson.JacksonConverterFactory;
 | 
				
			||||||
 | 
					import retrofit2.http.GET;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@NoArgsConstructor
 | 
				
			||||||
 | 
					@Getter
 | 
				
			||||||
 | 
					public class Chronos {
 | 
				
			||||||
 | 
					    private static final String IPV4_PATTERN =
 | 
				
			||||||
 | 
					           "^(([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.){3}([01]?\\d\\d?|2[0-4]\\d|25[0-5])$";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private static boolean isValidIPv4(String ip) {
 | 
				
			||||||
 | 
					        return ip.matches(IPV4_PATTERN);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private LocalData localData = new LocalData();
 | 
				
			||||||
 | 
					    private ApiService apiService;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public boolean hasConfig() {
 | 
				
			||||||
 | 
					        var config_path = ConfigPathProvider.getPath();
 | 
				
			||||||
 | 
					        File file = new File(Path.of(config_path, "config.json").toString());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return file.exists();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public boolean hasUser() {
 | 
				
			||||||
 | 
					        return localData.getUserSecret() != null;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public void loadData() throws IOException {
 | 
				
			||||||
 | 
					        var config_path = ConfigPathProvider.getPath();
 | 
				
			||||||
 | 
					        File file = new File(Path.of(config_path, "config.json").toString());
 | 
				
			||||||
 | 
					        String content = Files.readString(file.toPath());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        ObjectMapper objectMapper = new ObjectMapper();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					            this.localData = objectMapper.readValue(content, LocalData.class);
 | 
				
			||||||
 | 
					        } catch (Exception e) {
 | 
				
			||||||
 | 
					            e.printStackTrace();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        setupApi(localData.getServer());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private void setupApi(String baseUrl) {
 | 
				
			||||||
 | 
					        Retrofit retrofit = new Retrofit.Builder()
 | 
				
			||||||
 | 
					                .baseUrl(baseUrl)
 | 
				
			||||||
 | 
					                .addConverterFactory(JacksonConverterFactory.create(new ObjectMapper()))
 | 
				
			||||||
 | 
					                .build();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        this.apiService = retrofit.create(ApiService.class);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public void setup() throws IOException {
 | 
				
			||||||
 | 
					        System.out.println("\n");
 | 
				
			||||||
 | 
					        Cli.type("Nyní se budeme muset připojit na Chronos server. Zadejte prosím IP adresu serveru na kterém běží chronos server.\nNapř: 127.0.0.1");
 | 
				
			||||||
 | 
					        Console console = System.console();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        String ipaddr = null;
 | 
				
			||||||
 | 
					        do {
 | 
				
			||||||
 | 
					            ipaddr = console.readLine(ipaddr == null ? "Zadejte ip adresu serveru: " : "Zadejte platnou ip adresu serveru: ");
 | 
				
			||||||
 | 
					        } while (!isValidIPv4(ipaddr));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Cli.info("Pokouším se připojit k serveru");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        String baseUrl = "http://" + ipaddr + ":8080/";
 | 
				
			||||||
 | 
					        setupApi(baseUrl);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					            var response = apiService.status().execute().body();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (response.getData().isEmpty() || !response.getData().get().equals("working")) {
 | 
				
			||||||
 | 
					                Cli.error("Tento server pravděpodobně není Chronos server.");
 | 
				
			||||||
 | 
					                setup();
 | 
				
			||||||
 | 
					                return;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        } catch (ConnectException e) {
 | 
				
			||||||
 | 
					            Cli.error("Nastala chyba při připojování k serveru, zkuste to znovu");
 | 
				
			||||||
 | 
					            setup();
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Cli.success("Server byl úspěšně nastaven");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        this.localData.setServer(baseUrl);
 | 
				
			||||||
 | 
					        this.localData.saveData();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public void createNewGame() throws IOException {
 | 
				
			||||||
 | 
					        Cli.printHeader("Vytvoření hry");
 | 
				
			||||||
 | 
					        Cli.info("Vytvářím novou hru");
 | 
				
			||||||
 | 
					        var body = apiService.newGame().execute().body();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (!Objects.requireNonNull(body).getSuccess()) {
 | 
				
			||||||
 | 
					            System.err.println("Nastala chyba při vytváření hry!");
 | 
				
			||||||
 | 
					            System.exit(1);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        var data = body.getData().get();
 | 
				
			||||||
 | 
					        localData.setGameKey(data.getGameKey());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Cli.success("Byla úspěšně vytvořena hra");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public void addUser() throws IOException {
 | 
				
			||||||
 | 
					        Cli.printHeader("Vytvoření hráče");
 | 
				
			||||||
 | 
					        Console console = System.console();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        var name = console.readLine("Zadejte vaše jméno: ");
 | 
				
			||||||
 | 
					        var newPlayerBody = apiService.newPlayer(localData.getGameKey(), new PlayerNameRequest(name)).execute().body();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (!Objects.requireNonNull(newPlayerBody).getSuccess()) {
 | 
				
			||||||
 | 
					            System.err.println("Nastala chyba při vytváření hráče!");
 | 
				
			||||||
 | 
					            System.exit(1);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        localData.setUserSecret(newPlayerBody.getData().get());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public void adminPanel() throws IOException {
 | 
				
			||||||
 | 
					        Cli.printHeader("Čekání na připojení hráčů");
 | 
				
			||||||
 | 
					        System.out.println();
 | 
				
			||||||
 | 
					        Cli.center("Kód pro připojení:");
 | 
				
			||||||
 | 
					        System.out.print(Cli.Colors.GREEN);
 | 
				
			||||||
 | 
					        Cli.center(localData.getGameKey());
 | 
				
			||||||
 | 
					        System.out.print(Cli.Colors.RESET);
 | 
				
			||||||
 | 
					        Cli.center("(pomocí tohoto kódu se hráči můžou napojit)");
 | 
				
			||||||
 | 
					        System.out.println("\nPo startu hry už se nemůžou napojit noví hráči!");
 | 
				
			||||||
 | 
					        System.out.println("Stiskněte " + Cli.Colors.CYAN + "Enter" + Cli.Colors.RESET + " pro start hry...");
 | 
				
			||||||
 | 
					        System.console().readLine();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        localData.saveData();
 | 
				
			||||||
 | 
					        apiService.startGame(localData.getUserSecret(), localData.getGameKey()).execute();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public void connectToExisting() throws IOException {
 | 
				
			||||||
 | 
					        Console console = System.console();
 | 
				
			||||||
 | 
					        Cli.printHeader("Připojení do hry");
 | 
				
			||||||
 | 
					        System.out.println();
 | 
				
			||||||
 | 
					        String code = console.readLine("Zadejte kod pro připojení: ");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        var testGameKeyResponse = apiService.testGameKey(code).execute().body().getData().get();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (testGameKeyResponse == TestGameKeyResponse.INVALID_KEY) {
 | 
				
			||||||
 | 
					            Cli.error("Nebyla nalezena hra s tímto kódem!");
 | 
				
			||||||
 | 
					            connectToExisting();
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (testGameKeyResponse == TestGameKeyResponse.GAME_STARTED) {
 | 
				
			||||||
 | 
					            Cli.error("Tato hra již začala!");
 | 
				
			||||||
 | 
					            connectToExisting();
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (testGameKeyResponse == TestGameKeyResponse.MAXIUM_PLAYERS) {
 | 
				
			||||||
 | 
					            Cli.error("V této hře je již maximální počet hráčů!");
 | 
				
			||||||
 | 
					            connectToExisting();
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        localData.setGameKey(code);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public void waitForStart() throws IOException {
 | 
				
			||||||
 | 
					        boolean started = false;
 | 
				
			||||||
 | 
					        while (!started) {
 | 
				
			||||||
 | 
					            var res = apiService.testGameKey(localData.getGameKey()).execute();
 | 
				
			||||||
 | 
					            var data = res.body().getData().get();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            started = data == TestGameKeyResponse.GAME_STARTED;
 | 
				
			||||||
 | 
					            try {
 | 
				
			||||||
 | 
					                Thread.sleep(2000);
 | 
				
			||||||
 | 
					            } catch (InterruptedException e) {
 | 
				
			||||||
 | 
					                throw new RuntimeException(e);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public void visit() throws IOException {
 | 
				
			||||||
 | 
					        var res = apiService.getCurrentRoom(localData.getUserSecret()).execute();
 | 
				
			||||||
 | 
					        var room = res.body().getData().get();
 | 
				
			||||||
 | 
					        visit(room, false);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    public void visit(Room room) throws IOException {
 | 
				
			||||||
 | 
					        visit(room, true);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    public void visit(Room room, boolean changeRoom) throws IOException {
 | 
				
			||||||
 | 
					        if (changeRoom) {
 | 
				
			||||||
 | 
					            apiService.moveToRoom(localData.getUserSecret(), room.getId());
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Cli.info("Nyní se nacházíte v místnosti " + room.getName());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (room.getCharacters().isEmpty()) {
 | 
				
			||||||
 | 
					            Cli.type("V místnosti  je prázno... Ani jedna duše.");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        for (Character character : room.getCharacters()) {
 | 
				
			||||||
 | 
					            talkWith(character);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public void talkWith(Character character) throws IOException {
 | 
				
			||||||
 | 
					        Cli.type("V místnosti je " + character.getName());
 | 
				
			||||||
 | 
					        System.out.println();
 | 
				
			||||||
 | 
					        Cli.type(Cli.Colors.YELLOW + character.getName() + ": " + Cli.Colors.RESET + character.getDialog());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (!character.getInventory().isEmpty()) {
 | 
				
			||||||
 | 
					            var res = apiService.takeItems(getLocalData().getUserSecret(), character.getId()).execute();
 | 
				
			||||||
 | 
					            var body = res.body().getData().get();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (body == TakeItemsResponse.ALREADY_TAKEN) {
 | 
				
			||||||
 | 
					                Cli.type(Cli.Colors.YELLOW + character.getName() + ": " + Cli.Colors.RESET + "Už jsem ti mé itemy dal. Už pro tebe nic nemám.");
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                var characters = character.getInventory().stream().map(item -> item.getItemType().toString()).toList();
 | 
				
			||||||
 | 
					                Cli.info("Dostal jste: " + String.join(", ", characters));
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										41
									
								
								frontend/src/main/java/cz/jzitnik/game/LocalData.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								frontend/src/main/java/cz/jzitnik/game/LocalData.java
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,41 @@
 | 
				
			|||||||
 | 
					package cz.jzitnik.game;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import com.fasterxml.jackson.core.JsonProcessingException;
 | 
				
			||||||
 | 
					import com.fasterxml.jackson.databind.ObjectMapper;
 | 
				
			||||||
 | 
					import cz.jzitnik.utils.ConfigPathProvider;
 | 
				
			||||||
 | 
					import lombok.AllArgsConstructor;
 | 
				
			||||||
 | 
					import lombok.Getter;
 | 
				
			||||||
 | 
					import lombok.NoArgsConstructor;
 | 
				
			||||||
 | 
					import lombok.Setter;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.io.File;
 | 
				
			||||||
 | 
					import java.io.IOException;
 | 
				
			||||||
 | 
					import java.nio.file.Path;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@Getter
 | 
				
			||||||
 | 
					@Setter
 | 
				
			||||||
 | 
					@NoArgsConstructor
 | 
				
			||||||
 | 
					public class LocalData {
 | 
				
			||||||
 | 
					    private String server;
 | 
				
			||||||
 | 
					    private String userSecret;
 | 
				
			||||||
 | 
					    private String gameKey;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public void saveData() {
 | 
				
			||||||
 | 
					        ObjectMapper objectMapper = new ObjectMapper();
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					            String configPath = ConfigPathProvider.getPath();
 | 
				
			||||||
 | 
					            File file = new File(Path.of(configPath, "config.json").toString());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            File parentDir = file.getParentFile();
 | 
				
			||||||
 | 
					            if (!parentDir.exists()) {
 | 
				
			||||||
 | 
					                parentDir.mkdirs();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            objectMapper.writeValue(file, this);
 | 
				
			||||||
 | 
					        } catch (JsonProcessingException e) {
 | 
				
			||||||
 | 
					            e.printStackTrace();
 | 
				
			||||||
 | 
					        } catch (IOException e) {
 | 
				
			||||||
 | 
					            e.printStackTrace();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										172
									
								
								frontend/src/main/java/cz/jzitnik/utils/Cli.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										172
									
								
								frontend/src/main/java/cz/jzitnik/utils/Cli.java
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,172 @@
 | 
				
			|||||||
 | 
					package cz.jzitnik.utils;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.util.Scanner;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public class Cli {
 | 
				
			||||||
 | 
					    public static class Colors {
 | 
				
			||||||
 | 
					        public static final String RESET = "\033[0m";  // ANSI escape code to reset the terminal
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Text colors
 | 
				
			||||||
 | 
					        public static final String BLACK = "\033[0;30m";
 | 
				
			||||||
 | 
					        public static final String RED = "\033[0;31m";
 | 
				
			||||||
 | 
					        public static final String GREEN = "\033[0;32m";
 | 
				
			||||||
 | 
					        public static final String YELLOW = "\033[0;33m";
 | 
				
			||||||
 | 
					        public static final String BLUE = "\033[0;34m";
 | 
				
			||||||
 | 
					        public static final String PURPLE = "\033[0;35m";
 | 
				
			||||||
 | 
					        public static final String CYAN = "\033[0;36m";
 | 
				
			||||||
 | 
					        public static final String WHITE = "\033[0;37m";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Bold text colors (in bold)
 | 
				
			||||||
 | 
					        public static final String BOLD_BLACK = "\033[1;30m";
 | 
				
			||||||
 | 
					        public static final String BOLD_RED = "\033[1;31m";
 | 
				
			||||||
 | 
					        public static final String BOLD_GREEN = "\033[1;32m";
 | 
				
			||||||
 | 
					        public static final String BOLD_YELLOW = "\033[1;33m";
 | 
				
			||||||
 | 
					        public static final String BOLD_BLUE = "\033[1;34m";
 | 
				
			||||||
 | 
					        public static final String BOLD_PURPLE = "\033[1;35m";
 | 
				
			||||||
 | 
					        public static final String BOLD_CYAN = "\033[1;36m";
 | 
				
			||||||
 | 
					        public static final String BOLD_WHITE = "\033[1;37m";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Background colors
 | 
				
			||||||
 | 
					        public static final String BLACK_BACKGROUND = "\033[40m";
 | 
				
			||||||
 | 
					        public static final String RED_BACKGROUND = "\033[41m";
 | 
				
			||||||
 | 
					        public static final String GREEN_BACKGROUND = "\033[42m";
 | 
				
			||||||
 | 
					        public static final String YELLOW_BACKGROUND = "\033[43m";
 | 
				
			||||||
 | 
					        public static final String BLUE_BACKGROUND = "\033[44m";
 | 
				
			||||||
 | 
					        public static final String PURPLE_BACKGROUND = "\033[45m";
 | 
				
			||||||
 | 
					        public static final String CYAN_BACKGROUND = "\033[46m";
 | 
				
			||||||
 | 
					        public static final String WHITE_BACKGROUND = "\033[47m";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Bold background colors
 | 
				
			||||||
 | 
					        public static final String BOLD_BLACK_BACKGROUND = "\033[1;40m";
 | 
				
			||||||
 | 
					        public static final String BOLD_RED_BACKGROUND = "\033[1;41m";
 | 
				
			||||||
 | 
					        public static final String BOLD_GREEN_BACKGROUND = "\033[1;42m";
 | 
				
			||||||
 | 
					        public static final String BOLD_YELLOW_BACKGROUND = "\033[1;43m";
 | 
				
			||||||
 | 
					        public static final String BOLD_BLUE_BACKGROUND = "\033[1;44m";
 | 
				
			||||||
 | 
					        public static final String BOLD_PURPLE_BACKGROUND = "\033[1;45m";
 | 
				
			||||||
 | 
					        public static final String BOLD_CYAN_BACKGROUND = "\033[1;46m";
 | 
				
			||||||
 | 
					        public static final String BOLD_WHITE_BACKGROUND = "\033[1;47m";
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static void printHeader(String text) {
 | 
				
			||||||
 | 
					        int totalWidth = 100;
 | 
				
			||||||
 | 
					        int padding = (totalWidth - text.length()) / 2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        StringBuilder sb = new StringBuilder(totalWidth);
 | 
				
			||||||
 | 
					        for (int i = 0; i < padding; i++) {
 | 
				
			||||||
 | 
					            sb.append("=");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        sb.append(" ");
 | 
				
			||||||
 | 
					        sb.append(text);
 | 
				
			||||||
 | 
					        sb.append(" ");
 | 
				
			||||||
 | 
					        for (int i = 0; i < padding; i++) {
 | 
				
			||||||
 | 
					            sb.append("=");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        while (sb.length() < totalWidth) {
 | 
				
			||||||
 | 
					            sb.insert(0, "=");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        System.out.println();
 | 
				
			||||||
 | 
					        System.out.println(sb);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static void center(String text) {
 | 
				
			||||||
 | 
					        int totalWidth = 100;
 | 
				
			||||||
 | 
					        int padding = (totalWidth - text.length()) / 2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        StringBuilder sb = new StringBuilder(totalWidth);
 | 
				
			||||||
 | 
					        for (int i = 0; i < padding; i++) {
 | 
				
			||||||
 | 
					            sb.append(" ");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        sb.append(text);
 | 
				
			||||||
 | 
					        for (int i = 0; i < padding; i++) {
 | 
				
			||||||
 | 
					            sb.append(" ");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        while (sb.length() < totalWidth) {
 | 
				
			||||||
 | 
					            sb.insert(0, " ");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        System.out.println(sb);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static String wrapText(String text) {
 | 
				
			||||||
 | 
					        return wrapText(text, 0);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static String wrapText(String text, int charsRemove) {
 | 
				
			||||||
 | 
					        StringBuilder wrappedText = new StringBuilder();
 | 
				
			||||||
 | 
					        int line = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        var words = text.split(" ");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for (var word : words) {
 | 
				
			||||||
 | 
					            if ((line + word.length() + 1) > (100 - charsRemove)) {
 | 
				
			||||||
 | 
					                wrappedText.append("\n");
 | 
				
			||||||
 | 
					                line = 0;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            line += word.length() + 1;
 | 
				
			||||||
 | 
					            wrappedText.append(word).append(" ");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return wrappedText.toString();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static void typeText(String text) {
 | 
				
			||||||
 | 
					        for (int i = 0; i < text.length(); i++) {
 | 
				
			||||||
 | 
					            System.out.print(text.charAt(i));
 | 
				
			||||||
 | 
					            try {
 | 
				
			||||||
 | 
					                Thread.sleep(10);
 | 
				
			||||||
 | 
					            } catch (InterruptedException e) {
 | 
				
			||||||
 | 
					                e.printStackTrace();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        System.out.println();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static void type(String text) {
 | 
				
			||||||
 | 
					        Cli.typeText(Cli.wrapText(text));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static void info(String text) {
 | 
				
			||||||
 | 
					        System.out.println(Colors.BLUE + "Info: " + Colors.RESET + Cli.wrapText(text, 6));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    public static void success(String text) {
 | 
				
			||||||
 | 
					        System.out.println(Colors.GREEN + "Úspěch: " + Colors.RESET + Cli.wrapText(text, 8));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    public static void error(String text) {
 | 
				
			||||||
 | 
					        System.out.println(Colors.RED + "Chyba: " + Colors.RESET + Cli.wrapText(text, 7));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Displays a menu with the provided options and returns the selected option.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param options Array of options to display to the user.
 | 
				
			||||||
 | 
					     * @return The selected option as a String.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public static String selectOption(String[] options) {
 | 
				
			||||||
 | 
					        Scanner scanner = new Scanner(System.in);
 | 
				
			||||||
 | 
					        int choice;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        System.out.println("Vyberte možnost:");
 | 
				
			||||||
 | 
					        for (int i = 0; i < options.length; i++) {
 | 
				
			||||||
 | 
					            System.out.println((i + 1) + ". " + options[i]);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        while (true) {
 | 
				
			||||||
 | 
					            System.out.print("Vložte číslo možnosti: ");
 | 
				
			||||||
 | 
					            if (scanner.hasNextInt()) {
 | 
				
			||||||
 | 
					                choice = scanner.nextInt();
 | 
				
			||||||
 | 
					                if (choice >= 1 && choice <= options.length) {
 | 
				
			||||||
 | 
					                    return options[choice - 1];
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                    System.out.println("Neplatní možnost, vyberte číslo mezi 1 a " + options.length);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                System.out.println("Neplatný vstup, vložte číslo.");
 | 
				
			||||||
 | 
					                scanner.next();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,19 @@
 | 
				
			|||||||
 | 
					package cz.jzitnik.utils;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public class ConfigPathProvider {
 | 
				
			||||||
 | 
					    public static String getPath() {
 | 
				
			||||||
 | 
					        String configDir;
 | 
				
			||||||
 | 
					        String os = System.getProperty("os.name").toLowerCase();
 | 
				
			||||||
 | 
					        if (os.contains("win")) {
 | 
				
			||||||
 | 
					            configDir = System.getenv("APPDATA") + "\\Chronos";
 | 
				
			||||||
 | 
					        } else if (os.contains("nix") || os.contains("nux")) {
 | 
				
			||||||
 | 
					            configDir = System.getProperty("user.home") + "/.config/Chronos";
 | 
				
			||||||
 | 
					        } else if (os.contains("mac")) {
 | 
				
			||||||
 | 
					            configDir = System.getProperty("user.home") + "/Library/Application Support/Chronos";
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            configDir = System.getProperty("user.home") + "/Chronos";
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return configDir;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Reference in New Issue
	
	Block a user