feat: Implemented interactions and rooms
Now you can interact with characters and go between rooms
This commit is contained in:
parent
6786eb1be8
commit
ce1710cfef
@ -1,5 +1,6 @@
|
|||||||
package cz.jzitnik.chronos.controllers;
|
package cz.jzitnik.chronos.controllers;
|
||||||
|
|
||||||
|
import cz.jzitnik.chronos.entities.Interaction;
|
||||||
import cz.jzitnik.chronos.entities.Item;
|
import cz.jzitnik.chronos.entities.Item;
|
||||||
import cz.jzitnik.chronos.interactions.InteractionService;
|
import cz.jzitnik.chronos.interactions.InteractionService;
|
||||||
import cz.jzitnik.chronos.payload.requests.InteractionRequest;
|
import cz.jzitnik.chronos.payload.requests.InteractionRequest;
|
||||||
@ -27,6 +28,27 @@ public class CharacterController {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private CharacterRepository characterRepository;
|
private CharacterRepository characterRepository;
|
||||||
|
|
||||||
|
@GetMapping("/interaction")
|
||||||
|
@CheckUser
|
||||||
|
public ResponseEntity<UnifiedResponse<Interaction, Error>> getInteractionData(@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));
|
||||||
|
}
|
||||||
|
if (!characterOptional.get().getRoom().equals(player.getCurrentRoom())) {
|
||||||
|
return ResponseEntity.badRequest().body(UnifiedResponse.failure(null));
|
||||||
|
}
|
||||||
|
|
||||||
|
var interaction = characterOptional.get().getInteractionData();
|
||||||
|
|
||||||
|
return ResponseEntity.ok(
|
||||||
|
UnifiedResponse.success(interaction)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@PostMapping("/interact")
|
@PostMapping("/interact")
|
||||||
@CheckUser
|
@CheckUser
|
||||||
public ResponseEntity<UnifiedResponse<InteractionResponse, Error>> interact(@RequestParam String playerKey, @RequestBody InteractionRequest interactionRequest) {
|
public ResponseEntity<UnifiedResponse<InteractionResponse, Error>> interact(@RequestParam String playerKey, @RequestBody InteractionRequest interactionRequest) {
|
||||||
|
@ -1,11 +1,15 @@
|
|||||||
package cz.jzitnik.chronos.controllers;
|
package cz.jzitnik.chronos.controllers;
|
||||||
|
|
||||||
|
import cz.jzitnik.chronos.entities.Player;
|
||||||
|
import cz.jzitnik.chronos.payload.errors.ItemNotUsableException;
|
||||||
import cz.jzitnik.chronos.payload.errors.NotFoundError;
|
import cz.jzitnik.chronos.payload.errors.NotFoundError;
|
||||||
import cz.jzitnik.chronos.payload.requests.PlayerNameRequest;
|
import cz.jzitnik.chronos.payload.requests.PlayerNameRequest;
|
||||||
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.ItemRepository;
|
||||||
import cz.jzitnik.chronos.repository.PlayerRepository;
|
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.HttpStatus;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
@ -24,6 +28,9 @@ public class PlayerController {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private GameService gameService;
|
private GameService gameService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ItemRepository itemRepository;
|
||||||
|
|
||||||
@PostMapping("/new")
|
@PostMapping("/new")
|
||||||
public ResponseEntity<UnifiedResponse<String, Error>> newPlayer(@RequestParam String gameKey, @RequestBody PlayerNameRequest playerNameRequest) {
|
public ResponseEntity<UnifiedResponse<String, Error>> newPlayer(@RequestParam String gameKey, @RequestBody PlayerNameRequest playerNameRequest) {
|
||||||
var gameOptional = gameRepository.findByGameKey(gameKey);
|
var gameOptional = gameRepository.findByGameKey(gameKey);
|
||||||
@ -42,4 +49,42 @@ public class PlayerController {
|
|||||||
UnifiedResponse.success(player.getPlayerKey())
|
UnifiedResponse.success(player.getPlayerKey())
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GetMapping("/me")
|
||||||
|
@CheckUser
|
||||||
|
public ResponseEntity<UnifiedResponse<Player, Error>> getMe(@RequestParam String playerKey) {
|
||||||
|
var player = playerRepository.findByPlayerKey(playerKey).get();
|
||||||
|
|
||||||
|
return ResponseEntity.ok(UnifiedResponse.success(player));
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/use_item")
|
||||||
|
@CheckUser
|
||||||
|
public ResponseEntity<UnifiedResponse<Object, Error>> useItem(@RequestParam String playerKey, @RequestParam Long itemId) {
|
||||||
|
var player = playerRepository.findByPlayerKey(playerKey).get();
|
||||||
|
var itemOptional = itemRepository.findById(itemId);
|
||||||
|
|
||||||
|
if (itemOptional.isEmpty()) {
|
||||||
|
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(UnifiedResponse.failure(new NotFoundError("Item was not found!")));
|
||||||
|
}
|
||||||
|
|
||||||
|
var item = itemOptional.get();
|
||||||
|
|
||||||
|
if (!player.getInventory().contains(item)) {
|
||||||
|
return ResponseEntity.status(HttpStatus.FORBIDDEN).body(UnifiedResponse.failure(new Error("You do not own this item!")));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use the item
|
||||||
|
try {
|
||||||
|
item.getItemType().useItem(player);
|
||||||
|
} catch (ItemNotUsableException e) {
|
||||||
|
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(UnifiedResponse.failure(e.toError()));
|
||||||
|
}
|
||||||
|
|
||||||
|
playerRepository.save(player);
|
||||||
|
|
||||||
|
itemRepository.delete(item);
|
||||||
|
|
||||||
|
return ResponseEntity.ok(UnifiedResponse.success(null));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ package cz.jzitnik.chronos.entities;
|
|||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
import jakarta.persistence.*;
|
import jakarta.persistence.*;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
@ -24,4 +25,10 @@ public class Interaction {
|
|||||||
@OneToOne(mappedBy = "interactionData")
|
@OneToOne(mappedBy = "interactionData")
|
||||||
@JsonIgnore
|
@JsonIgnore
|
||||||
private Character character;
|
private Character character;
|
||||||
|
|
||||||
|
public Interaction(String startText, String interactedWithText, Character character) {
|
||||||
|
this.startText = startText;
|
||||||
|
this.interactedWithText = interactedWithText;
|
||||||
|
this.character = character;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,17 @@
|
|||||||
package cz.jzitnik.chronos.entities;
|
package cz.jzitnik.chronos.entities;
|
||||||
|
|
||||||
|
import cz.jzitnik.chronos.payload.errors.ItemNotUsableException;
|
||||||
|
|
||||||
public enum ItemType {
|
public enum ItemType {
|
||||||
KEY_FRAGMENT,
|
KEY_FRAGMENT,
|
||||||
LUCK_POTION
|
LUCK_POTION;
|
||||||
|
|
||||||
|
public void useItem(Player player) throws ItemNotUsableException {
|
||||||
|
switch (this) {
|
||||||
|
case LUCK_POTION -> {
|
||||||
|
player.setLuck(true);
|
||||||
|
}
|
||||||
|
default -> throw new ItemNotUsableException("Item " + this + " is not usable");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,8 @@ import cz.jzitnik.chronos.repository.PlayerRepository;
|
|||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
@ -48,30 +50,42 @@ public class InteractionService {
|
|||||||
player.setLuck(false);
|
player.setLuck(false);
|
||||||
|
|
||||||
if (playerWins) {
|
if (playerWins) {
|
||||||
player.addItem(new Item(ItemType.KEY_FRAGMENT, player));
|
var item = new Item(ItemType.KEY_FRAGMENT, player);
|
||||||
|
player.addItem(item);
|
||||||
playerRepository.save(player);
|
playerRepository.save(player);
|
||||||
|
|
||||||
character.setInteractedWith(true);
|
character.setInteractedWith(true);
|
||||||
characterRepository.save(character);
|
characterRepository.save(character);
|
||||||
|
|
||||||
return new InteractionResponse(true, "Vyhrál jsi, dostáváš jeden fragment klíče.");
|
var items = new ArrayList<Item>();
|
||||||
|
items.add(item);
|
||||||
|
|
||||||
|
return new InteractionResponse(true, "Vyhrál jsi, dostáváš ode mě jeden fragment klíče.", items);
|
||||||
} else {
|
} else {
|
||||||
return new InteractionResponse(false, "Prohrál jsi");
|
character.setInteractedWith(true);
|
||||||
|
characterRepository.save(character);
|
||||||
|
return new InteractionResponse(false, "Prohrál jsi. Žádný fragment klíče ode mě už nedostaneš. Zkus to u někoho jiného.", new ArrayList<>());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Standard rock-paper-scissors game logic
|
// Standard rock-paper-scissors game logic
|
||||||
if (userChoice == characterChoice) {
|
if (userChoice == characterChoice) {
|
||||||
return new InteractionResponse(false, "Remíza, oběma hráčům se podařilo uhádnout.");
|
return new InteractionResponse(false, "Remíza. Jestli chceš můžeš si se mnou zahrát ještě jednou.", new ArrayList<>());
|
||||||
} else if ((userChoice == 0 && characterChoice == 2) || (userChoice == 1 && characterChoice == 0) || (userChoice == 2 && characterChoice == 1)) {
|
} else if ((userChoice == 0 && characterChoice == 2) || (userChoice == 1 && characterChoice == 0) || (userChoice == 2 && characterChoice == 1)) {
|
||||||
player.addItem(new Item(ItemType.KEY_FRAGMENT, player));
|
var item = new Item(ItemType.KEY_FRAGMENT, player);
|
||||||
|
player.addItem(item);
|
||||||
playerRepository.save(player);
|
playerRepository.save(player);
|
||||||
|
|
||||||
character.setInteractedWith(true);
|
character.setInteractedWith(true);
|
||||||
characterRepository.save(character);
|
characterRepository.save(character);
|
||||||
|
|
||||||
return new InteractionResponse(true, "Vyhrál jsi, dostáváš jeden fragment klíče.");
|
var items = new ArrayList<Item>();
|
||||||
|
items.add(item);
|
||||||
|
|
||||||
|
return new InteractionResponse(true, "Vyhrál jsi, dostáváš ode mě jeden fragment klíče.", items);
|
||||||
} else {
|
} else {
|
||||||
return new InteractionResponse(false, "Prohrál jsi");
|
character.setInteractedWith(true);
|
||||||
|
characterRepository.save(character);
|
||||||
|
return new InteractionResponse(false, "Prohrál jsi. Žádný fragment klíče ode mě už nedostaneš. Zkus to u někoho jiného.", new ArrayList<>());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -0,0 +1,17 @@
|
|||||||
|
package cz.jzitnik.chronos.payload.errors;
|
||||||
|
|
||||||
|
public class ItemNotUsableException extends Exception {
|
||||||
|
public static class ItemNotUsableError extends Error {
|
||||||
|
public ItemNotUsableError (String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ItemNotUsableException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ItemNotUsableError toError() {
|
||||||
|
return new ItemNotUsableError(super.getMessage());
|
||||||
|
}
|
||||||
|
}
|
@ -1,13 +1,17 @@
|
|||||||
package cz.jzitnik.chronos.payload.responses;
|
package cz.jzitnik.chronos.payload.responses;
|
||||||
|
|
||||||
|
import cz.jzitnik.chronos.entities.Item;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
@Setter
|
@Setter
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
public class InteractionResponse {
|
public class InteractionResponse {
|
||||||
private boolean success;
|
private boolean success;
|
||||||
private String responseText;
|
private String responseText;
|
||||||
|
private List<Item> items;
|
||||||
}
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
package cz.jzitnik.chronos.repository;
|
||||||
|
|
||||||
|
import cz.jzitnik.chronos.entities.Item;
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
|
@Repository
|
||||||
|
public interface ItemRepository extends JpaRepository<Item, Long> {
|
||||||
|
|
||||||
|
}
|
@ -38,9 +38,14 @@ public class InitGameService {
|
|||||||
var farmar = new Character(
|
var farmar = new Character(
|
||||||
"Farmář",
|
"Farmář",
|
||||||
stodola,
|
stodola,
|
||||||
"Ahoj já jsem farmář a budeš se mnou hrát kámen nůžky papír."
|
"Ahoj já jsem farmář a budeš se mnou hrát kámen nůžky papír. Dialog doplnit."
|
||||||
);
|
);
|
||||||
farmar.setInteraction(Interaction.Farmer);
|
farmar.setInteraction(Interaction.Farmer);
|
||||||
|
farmar.setInteractionData(new cz.jzitnik.chronos.entities.Interaction(
|
||||||
|
"Tak si zahrajeme kámen nůžky papír",
|
||||||
|
"Se mnou jsi již hrál kámen nůžky papír. Znovu už ti fragment klíče nedám",
|
||||||
|
farmar
|
||||||
|
));
|
||||||
stodola_characters.add(farmar);
|
stodola_characters.add(farmar);
|
||||||
stodola.setCharacters(stodola_characters);
|
stodola.setCharacters(stodola_characters);
|
||||||
|
|
||||||
|
@ -46,7 +46,7 @@ public class Main {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Cli.info("Prosím počkejte...");
|
||||||
chronos.waitForStart();
|
chronos.waitForStart();
|
||||||
Cli.info("Hra začala!");
|
Cli.info("Hra začala!");
|
||||||
System.out.println("\n\n");
|
System.out.println("\n\n");
|
||||||
|
@ -1,11 +1,10 @@
|
|||||||
package cz.jzitnik.api;
|
package cz.jzitnik.api;
|
||||||
|
|
||||||
|
import cz.jzitnik.api.requests.InteractionRequest;
|
||||||
import cz.jzitnik.api.requests.PlayerNameRequest;
|
import cz.jzitnik.api.requests.PlayerNameRequest;
|
||||||
|
import cz.jzitnik.api.responses.InteractionResponse;
|
||||||
import cz.jzitnik.api.responses.UnifiedResponse;
|
import cz.jzitnik.api.responses.UnifiedResponse;
|
||||||
import cz.jzitnik.api.types.Game;
|
import cz.jzitnik.api.types.*;
|
||||||
import cz.jzitnik.api.types.Room;
|
|
||||||
import cz.jzitnik.api.types.TakeItemsResponse;
|
|
||||||
import cz.jzitnik.api.types.TestGameKeyResponse;
|
|
||||||
import retrofit2.Call;
|
import retrofit2.Call;
|
||||||
import retrofit2.http.Body;
|
import retrofit2.http.Body;
|
||||||
import retrofit2.http.GET;
|
import retrofit2.http.GET;
|
||||||
@ -27,6 +26,17 @@ public interface ApiService {
|
|||||||
@Body PlayerNameRequest requestBody
|
@Body PlayerNameRequest requestBody
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@GET("game/players/me")
|
||||||
|
Call<UnifiedResponse<Player, Error>> getMe(
|
||||||
|
@Query("playerKey") String playerKey
|
||||||
|
);
|
||||||
|
|
||||||
|
@POST("game/players/use_item")
|
||||||
|
Call<UnifiedResponse<Object, Error>> useItem(
|
||||||
|
@Query("playerKey") String playerKey,
|
||||||
|
@Query("itemId") Long itemId
|
||||||
|
);
|
||||||
|
|
||||||
@POST("game/start")
|
@POST("game/start")
|
||||||
Call<UnifiedResponse<Object, Error>> startGame(
|
Call<UnifiedResponse<Object, Error>> startGame(
|
||||||
@Query("playerKey") String playerKey,
|
@Query("playerKey") String playerKey,
|
||||||
@ -59,4 +69,16 @@ public interface ApiService {
|
|||||||
@Query("playerKey") String playerKey,
|
@Query("playerKey") String playerKey,
|
||||||
@Query("characterId") Long characterId
|
@Query("characterId") Long characterId
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@GET("game/characters/interaction")
|
||||||
|
Call<UnifiedResponse<InteractionData, Error>> getInteractionData(
|
||||||
|
@Query("playerKey") String playerKey,
|
||||||
|
@Query("characterId") Long characterId
|
||||||
|
);
|
||||||
|
|
||||||
|
@POST("game/characters/interact")
|
||||||
|
Call<UnifiedResponse<InteractionResponse, Error>> interact(
|
||||||
|
@Query("playerKey") String playerKey,
|
||||||
|
@Body InteractionRequest interactionRequest
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,13 @@
|
|||||||
|
package cz.jzitnik.api.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,17 @@
|
|||||||
|
package cz.jzitnik.api.responses;
|
||||||
|
|
||||||
|
import cz.jzitnik.api.types.Item;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class InteractionResponse {
|
||||||
|
private boolean success;
|
||||||
|
private String responseText;
|
||||||
|
private List<Item> items;
|
||||||
|
}
|
@ -9,4 +9,9 @@ public class Item {
|
|||||||
private Long id;
|
private Long id;
|
||||||
|
|
||||||
private ItemType itemType;
|
private ItemType itemType;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return itemType.toString();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,27 @@
|
|||||||
package cz.jzitnik.api.types;
|
package cz.jzitnik.api.types;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
public enum ItemType {
|
public enum ItemType {
|
||||||
KEY_FRAGMENT,
|
KEY_FRAGMENT,
|
||||||
LUCK_POTION
|
LUCK_POTION;
|
||||||
|
|
||||||
|
private static final Set<ItemType> usableItems = new HashSet<>();
|
||||||
|
|
||||||
|
static {
|
||||||
|
usableItems.add(ItemType.LUCK_POTION);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isUsable() {
|
||||||
|
return usableItems.contains(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return switch (this) {
|
||||||
|
case LUCK_POTION -> "Lektvar štěstí";
|
||||||
|
case KEY_FRAGMENT -> "Fragment klíče";
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package cz.jzitnik.api.types;
|
package cz.jzitnik.api.types;
|
||||||
|
|
||||||
|
import cz.jzitnik.utils.Cli;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
|
|
||||||
@ -15,4 +16,30 @@ public class Player {
|
|||||||
private List<Item> inventory;
|
private List<Item> inventory;
|
||||||
|
|
||||||
private Room currentRoom;
|
private Room currentRoom;
|
||||||
|
|
||||||
|
private boolean luck;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
String sb = "Hráč: " +
|
||||||
|
Cli.Colors.BLUE +
|
||||||
|
name +
|
||||||
|
Cli.Colors.RESET +
|
||||||
|
"\n\n" +
|
||||||
|
"Vlastnosti:\n" +
|
||||||
|
"Id: " +
|
||||||
|
id +
|
||||||
|
"\n" +
|
||||||
|
"Štěstí: " +
|
||||||
|
(luck ? Cli.Colors.GREEN : Cli.Colors.RED) +
|
||||||
|
(luck ? "Ano" : "Ne") +
|
||||||
|
Cli.Colors.RESET +
|
||||||
|
"\n" +
|
||||||
|
"Místnost: " +
|
||||||
|
Cli.Colors.BLUE +
|
||||||
|
currentRoom +
|
||||||
|
Cli.Colors.RESET;
|
||||||
|
|
||||||
|
return sb;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,4 +15,13 @@ public class Room {
|
|||||||
private List<Item> items;
|
private List<Item> items;
|
||||||
|
|
||||||
private List<Character> characters;
|
private List<Character> characters;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
if (name.equals("Outside")) {
|
||||||
|
return "Venek";
|
||||||
|
}
|
||||||
|
|
||||||
|
return name;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,10 +2,8 @@ package cz.jzitnik.game;
|
|||||||
|
|
||||||
import cz.jzitnik.api.ApiService;
|
import cz.jzitnik.api.ApiService;
|
||||||
import cz.jzitnik.api.requests.PlayerNameRequest;
|
import cz.jzitnik.api.requests.PlayerNameRequest;
|
||||||
|
import cz.jzitnik.api.types.*;
|
||||||
import cz.jzitnik.api.types.Character;
|
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.game.interactions.Interactions;
|
import cz.jzitnik.game.interactions.Interactions;
|
||||||
import cz.jzitnik.utils.Cli;
|
import cz.jzitnik.utils.Cli;
|
||||||
import cz.jzitnik.utils.ConfigPathProvider;
|
import cz.jzitnik.utils.ConfigPathProvider;
|
||||||
@ -220,15 +218,11 @@ public class Chronos {
|
|||||||
Cli.info("Nyní se nacházíte v místnosti " + room.getName());
|
Cli.info("Nyní se nacházíte v místnosti " + room.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (room.getCharacters().isEmpty()) {
|
var characters = room.getCharacters();
|
||||||
|
if (characters.isEmpty()) {
|
||||||
Cli.type("V místnosti je prázno... Ani jedna duše.");
|
Cli.type("V místnosti je prázno... Ani jedna duše.");
|
||||||
}
|
} else {
|
||||||
for (Character character : room.getCharacters()) {
|
talk(characters);
|
||||||
talkWith(character);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!room.getCharacters().isEmpty()) {
|
|
||||||
interactWithAny(room.getCharacters());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var responseRooms = apiService.getAllRooms(localData.getUserSecret()).execute();
|
var responseRooms = apiService.getAllRooms(localData.getUserSecret()).execute();
|
||||||
@ -237,46 +231,26 @@ public class Chronos {
|
|||||||
System.out.println();
|
System.out.println();
|
||||||
Cli.info("Nyni si vyberte do jaké místnosti chcete jít.");
|
Cli.info("Nyni si vyberte do jaké místnosti chcete jít.");
|
||||||
|
|
||||||
int selectedIndex = Cli.selectOptionIndex(rooms.stream().map(Room::getName).toList());
|
int selectedIndex = Cli.selectOptionIndex(rooms.stream().map(Room::toString).toList());
|
||||||
|
|
||||||
visit(rooms.get(selectedIndex).getId(), true);
|
visit(rooms.get(selectedIndex).getId(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void interactWithAny(List<Character> characters) throws IOException {
|
public void talk(List<Character> characters) throws IOException {
|
||||||
if (characters.stream().anyMatch(character -> character.getInteraction() != null)) {
|
List<String> commands = new ArrayList<>(characters.stream().map(chachar -> "Promluvit si s " + chachar.getName()).toList());
|
||||||
List<Character> interactablePostavy = characters.stream().filter(
|
commands.add("Přejít do jiné místnosti");
|
||||||
character -> character.getInteraction() != null &&
|
CommandPalette commandPalette = new CommandPalette(commands, apiService, localData.getUserSecret());
|
||||||
!character.isInteractedWith()
|
int selectedIndex = commandPalette.displayIndex();
|
||||||
).toList();
|
|
||||||
|
|
||||||
if (interactablePostavy.isEmpty()) {
|
if (selectedIndex == commands.size() - 1) {
|
||||||
|
// Přejít do jiné místnosti
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<String> options = new ArrayList<>(interactablePostavy.stream().map(Character::getName).toList());
|
// Dangerous I would say but whatever
|
||||||
options.add("Neinteragovat s nikým");
|
Character character = characters.get(selectedIndex);
|
||||||
|
|
||||||
Cli.info("Můžete interagovat s následujícími postavami:");
|
|
||||||
int selectedIndex = Cli.selectOptionIndex(options);
|
|
||||||
|
|
||||||
if (selectedIndex == options.size() - 1) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var character = characters.get(selectedIndex);
|
|
||||||
|
|
||||||
Interactions.runInteraction(character);
|
|
||||||
|
|
||||||
var currentRoom = apiService.getCurrentRoom(localData.getUserSecret()).execute().body().getData();
|
|
||||||
|
|
||||||
interactWithAny(currentRoom.get().getCharacters().stream().filter(chachar -> !chachar.isInteractedWith()).toList());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void talkWith(Character character) throws IOException {
|
|
||||||
Cli.type("V místnosti je " + character.getName());
|
|
||||||
System.out.println();
|
System.out.println();
|
||||||
Cli.type(Cli.Colors.YELLOW + character.getName() + ": " + Cli.Colors.RESET + character.getDialog());
|
Cli.type(character, character.getDialog());
|
||||||
|
|
||||||
if (!character.getInventory().isEmpty()) {
|
if (!character.getInventory().isEmpty()) {
|
||||||
var res = apiService.takeItems(getLocalData().getUserSecret(), character.getId()).execute();
|
var res = apiService.takeItems(getLocalData().getUserSecret(), character.getId()).execute();
|
||||||
@ -285,9 +259,19 @@ public class Chronos {
|
|||||||
if (body == TakeItemsResponse.ALREADY_TAKEN) {
|
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.");
|
Cli.type(Cli.Colors.YELLOW + character.getName() + ": " + Cli.Colors.RESET + "Už jsem ti mé itemy dal. Už pro tebe nic nemám.");
|
||||||
} else {
|
} else {
|
||||||
var characters = character.getInventory().stream().map(item -> item.getItemType().toString()).toList();
|
Cli.gotItems(character.getInventory());
|
||||||
Cli.info("Dostal jste: " + String.join(", ", characters));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Interact with the character if it is interactable
|
||||||
|
if (character.getInteraction() != null) {
|
||||||
|
Interactions.runInteraction(character, apiService, localData.getUserSecret());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Refetch the characters
|
||||||
|
var res = apiService.getCurrentRoom(localData.getUserSecret()).execute();
|
||||||
|
var room = res.body().getData().get();
|
||||||
|
|
||||||
|
talk(room.getCharacters());
|
||||||
}
|
}
|
||||||
}
|
}
|
99
frontend/src/main/java/cz/jzitnik/game/CommandPalette.java
Normal file
99
frontend/src/main/java/cz/jzitnik/game/CommandPalette.java
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
package cz.jzitnik.game;
|
||||||
|
|
||||||
|
import cz.jzitnik.api.ApiService;
|
||||||
|
import cz.jzitnik.utils.Cli;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class CommandPalette {
|
||||||
|
public enum CommandType {
|
||||||
|
CUSTOM,
|
||||||
|
INVENTORY_OPEN,
|
||||||
|
USER_PROFILE,
|
||||||
|
EXIT,
|
||||||
|
}
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@AllArgsConstructor
|
||||||
|
public static class Command {
|
||||||
|
private String name;
|
||||||
|
private CommandType commandType;
|
||||||
|
|
||||||
|
public Command(String name) {
|
||||||
|
this.name = name;
|
||||||
|
this.commandType = CommandType.CUSTOM;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
if (commandType == CommandType.CUSTOM) {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Cli.Colors.BLUE + name + Cli.Colors.RESET;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<Command> commands;
|
||||||
|
private ApiService apiService;
|
||||||
|
private String playerKey;
|
||||||
|
|
||||||
|
public CommandPalette(List<String> commands, ApiService apiService, String playerKey) {
|
||||||
|
this.commands = commands.stream().map(Command::new).toList();
|
||||||
|
this.apiService = apiService;
|
||||||
|
this.playerKey = playerKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int displayIndex() throws IOException {
|
||||||
|
List<Command> allCommands = new ArrayList<>(commands);
|
||||||
|
|
||||||
|
// Command that can be used anywhere
|
||||||
|
allCommands.add(new Command("Otevřít inventář", CommandType.INVENTORY_OPEN));
|
||||||
|
allCommands.add(new Command("Otevřít profil uživatele", CommandType.USER_PROFILE));
|
||||||
|
allCommands.add(new Command("Odejít ze hry", CommandType.EXIT));
|
||||||
|
|
||||||
|
System.out.println("\n");
|
||||||
|
var selectedOption = Cli.selectOptionIndex(allCommands.stream().map(Command::toString).toList());
|
||||||
|
|
||||||
|
var command = allCommands.get(selectedOption);
|
||||||
|
|
||||||
|
return switch (command.getCommandType()) {
|
||||||
|
case CUSTOM -> selectedOption;
|
||||||
|
case EXIT -> {
|
||||||
|
System.out.println("Exiting game...");
|
||||||
|
System.exit(0);
|
||||||
|
|
||||||
|
yield 0;
|
||||||
|
}
|
||||||
|
case INVENTORY_OPEN -> {
|
||||||
|
var response = apiService.getMe(playerKey).execute();
|
||||||
|
assert response.body() != null;
|
||||||
|
var body = response.body().getData();
|
||||||
|
var me = body.get();
|
||||||
|
|
||||||
|
var inventory = new Inventory(me, apiService, playerKey);
|
||||||
|
inventory.display();
|
||||||
|
|
||||||
|
yield displayIndex();
|
||||||
|
}
|
||||||
|
case USER_PROFILE -> {
|
||||||
|
var response = apiService.getMe(playerKey).execute();
|
||||||
|
assert response.body() != null;
|
||||||
|
var body = response.body().getData();
|
||||||
|
var me = body.get();
|
||||||
|
|
||||||
|
System.out.println("\n\n" + me);
|
||||||
|
|
||||||
|
yield displayIndex();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
69
frontend/src/main/java/cz/jzitnik/game/Inventory.java
Normal file
69
frontend/src/main/java/cz/jzitnik/game/Inventory.java
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
package cz.jzitnik.game;
|
||||||
|
|
||||||
|
import cz.jzitnik.api.ApiService;
|
||||||
|
import cz.jzitnik.api.types.Item;
|
||||||
|
import cz.jzitnik.api.types.ItemType;
|
||||||
|
import cz.jzitnik.api.types.Player;
|
||||||
|
import cz.jzitnik.utils.Cli;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class Inventory {
|
||||||
|
private Player player;
|
||||||
|
private ApiService apiService;
|
||||||
|
private String playerKey;
|
||||||
|
|
||||||
|
|
||||||
|
public void display() throws IOException {
|
||||||
|
System.out.println();
|
||||||
|
Cli.info("Váš inventář:");
|
||||||
|
|
||||||
|
// Create a map to group items by ItemType and count occurrences
|
||||||
|
Map<ItemType, Integer> itemCounts = new HashMap<>();
|
||||||
|
List<Item> usableItemList = new ArrayList<>();
|
||||||
|
|
||||||
|
for (Item item : player.getInventory()) {
|
||||||
|
ItemType itemType = item.getItemType();
|
||||||
|
|
||||||
|
// If the item is usable, add it to the usableItemList
|
||||||
|
if (itemType.isUsable()) {
|
||||||
|
usableItemList.add(item);
|
||||||
|
} else {
|
||||||
|
// Otherwise, count it in the itemCounts map
|
||||||
|
itemCounts.put(itemType, itemCounts.getOrDefault(itemType, 0) + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Display grouped non-usable items
|
||||||
|
for (Map.Entry<ItemType, Integer> entry : itemCounts.entrySet()) {
|
||||||
|
System.out.println(entry.getValue() + "x " + entry.getKey());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Display usable items at the end
|
||||||
|
for (Item usableItem : usableItemList) {
|
||||||
|
System.out.println("1x " + Cli.Colors.BLUE + usableItem + Cli.Colors.RESET + " (lze využít)");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (!usableItemList.isEmpty()) {
|
||||||
|
System.out.println("\n\nNyní si můžete vybrat jaký item chcete využít");
|
||||||
|
var options = new ArrayList<>(usableItemList.stream().map(Item::toString).toList());
|
||||||
|
options.add("Zavřít inventář");
|
||||||
|
|
||||||
|
var selectedIndex = Cli.selectOptionIndex(options);
|
||||||
|
|
||||||
|
if (selectedIndex == options.size() - 1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var item = usableItemList.get(selectedIndex);
|
||||||
|
|
||||||
|
apiService.useItem(playerKey, item.getId()).execute();
|
||||||
|
|
||||||
|
Cli.info(item + " byl využit!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,12 +1,40 @@
|
|||||||
package cz.jzitnik.game.interactions;
|
package cz.jzitnik.game.interactions;
|
||||||
|
|
||||||
|
import cz.jzitnik.api.ApiService;
|
||||||
|
import cz.jzitnik.api.requests.InteractionRequest;
|
||||||
import cz.jzitnik.api.types.Character;
|
import cz.jzitnik.api.types.Character;
|
||||||
|
import cz.jzitnik.utils.Cli;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
public class Interactions {
|
public class Interactions {
|
||||||
public static void runInteraction(Character character) {
|
public static void runInteraction(Character character, ApiService apiService, String playerKey) throws IOException {
|
||||||
|
var response = apiService.getInteractionData(playerKey, character.getId()).execute();
|
||||||
|
var interactionData = response.body().getData().get();
|
||||||
|
|
||||||
|
if (character.isInteractedWith()) {
|
||||||
|
Cli.type(character, interactionData.getInteractedWithText());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Cli.type(character, interactionData.getStartText());
|
||||||
|
|
||||||
switch (character.getInteraction()) {
|
switch (character.getInteraction()) {
|
||||||
case Farmer -> {
|
case Farmer -> {
|
||||||
System.out.println("Inplement interaction with farmer");
|
var options = new String[] {"Kámen", "Nůžky", "Papír"};
|
||||||
|
var selected = Cli.selectOptionIndex(Arrays.stream(options).toList());
|
||||||
|
|
||||||
|
var requestData = new InteractionRequest(String.valueOf(selected), character.getId());
|
||||||
|
|
||||||
|
var res = apiService.interact(playerKey, requestData).execute();
|
||||||
|
var interactionResponse = res.body().getData().get();
|
||||||
|
|
||||||
|
Cli.type(character, interactionResponse.getResponseText());
|
||||||
|
|
||||||
|
if (interactionResponse.isSuccess()) {
|
||||||
|
Cli.gotItems(interactionResponse.getItems());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
package cz.jzitnik.utils;
|
package cz.jzitnik.utils;
|
||||||
|
|
||||||
|
import cz.jzitnik.api.types.Character;
|
||||||
|
import cz.jzitnik.api.types.Item;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Scanner;
|
import java.util.Scanner;
|
||||||
|
|
||||||
@ -53,15 +56,11 @@ public class Cli {
|
|||||||
int padding = (totalWidth - text.length()) / 2;
|
int padding = (totalWidth - text.length()) / 2;
|
||||||
|
|
||||||
StringBuilder sb = new StringBuilder(totalWidth);
|
StringBuilder sb = new StringBuilder(totalWidth);
|
||||||
for (int i = 0; i < padding; i++) {
|
sb.append("=".repeat(Math.max(0, padding)));
|
||||||
sb.append("=");
|
|
||||||
}
|
|
||||||
sb.append(" ");
|
sb.append(" ");
|
||||||
sb.append(text);
|
sb.append(text);
|
||||||
sb.append(" ");
|
sb.append(" ");
|
||||||
for (int i = 0; i < padding; i++) {
|
sb.append("=".repeat(Math.max(0, padding)));
|
||||||
sb.append("=");
|
|
||||||
}
|
|
||||||
|
|
||||||
while (sb.length() < totalWidth) {
|
while (sb.length() < totalWidth) {
|
||||||
sb.insert(0, "=");
|
sb.insert(0, "=");
|
||||||
@ -76,13 +75,9 @@ public class Cli {
|
|||||||
int padding = (totalWidth - text.length()) / 2;
|
int padding = (totalWidth - text.length()) / 2;
|
||||||
|
|
||||||
StringBuilder sb = new StringBuilder(totalWidth);
|
StringBuilder sb = new StringBuilder(totalWidth);
|
||||||
for (int i = 0; i < padding; i++) {
|
sb.append(" ".repeat(Math.max(0, padding)));
|
||||||
sb.append(" ");
|
|
||||||
}
|
|
||||||
sb.append(text);
|
sb.append(text);
|
||||||
for (int i = 0; i < padding; i++) {
|
sb.append(" ".repeat(Math.max(0, padding)));
|
||||||
sb.append(" ");
|
|
||||||
}
|
|
||||||
|
|
||||||
while (sb.length() < totalWidth) {
|
while (sb.length() < totalWidth) {
|
||||||
sb.insert(0, " ");
|
sb.insert(0, " ");
|
||||||
@ -125,6 +120,18 @@ public class Cli {
|
|||||||
System.out.println();
|
System.out.println();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void gotItems(List<Item> items) {
|
||||||
|
if (items.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var itemsMapped = items.stream().map(Item::toString).toList();
|
||||||
|
Cli.info("Dostal jste: " + String.join(", ", itemsMapped));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void type(Character character, String text) {
|
||||||
|
Cli.type(Cli.Colors.YELLOW + character.getName() + ": " + Cli.Colors.RESET + text);
|
||||||
|
}
|
||||||
public static void type(String text) {
|
public static void type(String text) {
|
||||||
Cli.typeText(Cli.wrapText(text));
|
Cli.typeText(Cli.wrapText(text));
|
||||||
}
|
}
|
||||||
@ -171,37 +178,6 @@ public class Cli {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 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 int selectOptionIndex(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 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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Displays a menu with the provided options and returns the selected option.
|
* Displays a menu with the provided options and returns the selected option.
|
||||||
*
|
*
|
||||||
|
Loading…
x
Reference in New Issue
Block a user