feat: A lot of new features
This commit is contained in:
parent
7fac24d073
commit
acb0cf2164
@ -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;
|
||||||
|
|
||||||
|
@Getter
|
||||||
public class UnifiedResponse<T, U> {
|
public class UnifiedResponse<T, U> {
|
||||||
@Getter
|
|
||||||
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;
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user