293 lines
10 KiB
Java
293 lines
10 KiB
Java
package cz.jzitnik.game;
|
|
|
|
import cz.jzitnik.api.ApiService;
|
|
import cz.jzitnik.api.requests.PlayerNameRequest;
|
|
import cz.jzitnik.api.types.*;
|
|
import cz.jzitnik.api.types.Character;
|
|
import cz.jzitnik.game.interactions.Interactions;
|
|
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.ArrayList;
|
|
import java.util.Arrays;
|
|
import java.util.List;
|
|
import java.util.Objects;
|
|
|
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
import retrofit2.Retrofit;
|
|
import retrofit2.converter.jackson.JacksonConverterFactory;
|
|
|
|
@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();
|
|
|
|
switch (testGameKeyResponse) {
|
|
case INVALID_KEY -> {
|
|
Cli.error("Nebyla nalezena hra s tímto kódem!");
|
|
connectToExisting();
|
|
}
|
|
case GAME_STARTED -> {
|
|
Cli.error("Tato hra již začala!");
|
|
connectToExisting();
|
|
}
|
|
case MAXIUM_PLAYERS -> {
|
|
Cli.error("V této hře je již maximální počet hráčů!");
|
|
connectToExisting();
|
|
}
|
|
case WORKING -> 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);
|
|
}
|
|
public void visit(Long roomId, boolean changeRoom) throws IOException {
|
|
if (changeRoom) {
|
|
apiService.moveToRoom(localData.getUserSecret(), roomId).execute();
|
|
}
|
|
|
|
visit();
|
|
}
|
|
public void visit(Room room) throws IOException {
|
|
System.out.println("\n");
|
|
if (room.getName().equals("Outside")) {
|
|
Cli.info("Nyní jste na náměstí.");
|
|
} else {
|
|
Cli.info("Nyní se nacházíte v " + Cli.Colors.BLUE + room.getName() + Cli.Colors.RESET + ".");
|
|
}
|
|
|
|
var items = room.getItems();
|
|
if (!items.isEmpty()) {
|
|
Cli.info("V místnosti se nachází: " + String.join(", ", items.stream().map(Item::toString).toList()));
|
|
var options = new String[] {"Vzít si itemy", "Nebrat si itemy"};
|
|
var selected = Cli.selectOptionIndex(Arrays.asList(options));
|
|
|
|
if (selected == 0) {
|
|
var response = apiService.takeItemsFromRoom(localData.getUserSecret()).execute();
|
|
var itemsGot = response.body().getData().get();
|
|
|
|
Cli.gotItems(itemsGot);
|
|
|
|
if (itemsGot.size() < items.size()) {
|
|
Cli.info("Některé itemy jste nemohl vzít, protože váš inventář je plný.");
|
|
}
|
|
}
|
|
}
|
|
|
|
System.out.println();
|
|
var characters = room.getCharacters();
|
|
if (characters.isEmpty()) {
|
|
Cli.type("V místnosti se nenachází jediná duše...");
|
|
} else {
|
|
talk(characters);
|
|
}
|
|
|
|
var responseRooms = apiService.getAllRooms(localData.getUserSecret()).execute();
|
|
var rooms = responseRooms.body().getData().get().stream().filter(rm -> !rm.getId().equals(room.getId())).toList();
|
|
|
|
System.out.println();
|
|
Cli.info("Nyni si vyberte do jaké místnosti chcete jít.");
|
|
|
|
int selectedIndex = Cli.selectOptionIndex(rooms.stream().map(Room::toString).toList());
|
|
|
|
visit(rooms.get(selectedIndex).getId(), true);
|
|
}
|
|
|
|
public void talk(List<Character> characters) throws IOException {
|
|
List<String> commands = new ArrayList<>(characters.stream().map(chachar -> "Promluvit si s " + chachar.getName()).toList());
|
|
commands.add("Přejít do jiné místnosti");
|
|
CommandPalette commandPalette = new CommandPalette(commands, apiService, localData.getUserSecret());
|
|
int selectedIndex = commandPalette.displayIndex();
|
|
|
|
if (selectedIndex == commands.size() - 1) {
|
|
// Přejít do jiné místnosti
|
|
return;
|
|
}
|
|
|
|
// Dangerous I would say but whatever
|
|
Character character = characters.get(selectedIndex);
|
|
System.out.println();
|
|
Cli.type(character, 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 {
|
|
Cli.gotItems(character.getInventory());
|
|
}
|
|
}
|
|
|
|
// 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());
|
|
}
|
|
} |