Вопрос Заносить ник и локацию в json с помощью gson

Версия Minecraft
1.16.X

elpomoika

Пользователь
Сообщения
10
Мне нужно заносить ник игрока(или uuid) в качестве ключа, а локацию в качестве значения в json файл. Первое что пришло мне на ум это хеш таблица, но плагин при выполнении команды выдает ошибку. Объясните что я делаю не так
Java:
    private static Location location = new Location(Bukkit.getWorld("world"), 12, 12, 12, 0, 0);
    private Map<Player, Location> map = new HashMap<>();
    private static FirstPlugin plugin;
    public spawn1(FirstPlugin plugin) {
        this.plugin = plugin;
    }

    @Override
    public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
        Player player = (Player) sender;
        if(sender instanceof Player) {
            try {
                saveJson();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return true;
    }

    public void saveJson() throws IOException {
        Gson gson = new Gson();
        // Создаем файл *.json
        File file = new File(plugin.getDataFolder().getAbsoluteFile() +"/data.json");
        file.getParentFile().mkdir();
        file.createNewFile();
        Writer writer = new FileWriter(file, false);
        gson.toJson(map, writer);
        writer.flush();
        writer.close();
        System.out.println("Player Saved");
    }
.
 
Упрощенная схема:
Код:
        File file = new File("Path to out file");
        JsonObject json = new JsonObject();
        json.add("Player UUID", new JsonPrimitive("Player Location"));
        Gson gson = new GsonBuilder().disableHtmlEscaping().create();
        try (BufferedWriter out = new BufferedWriter(new OutputStreamWriter(Files.newOutputStream(file.toPath())))) {
            gson.toJson(json, out);
        }
 
Упрощенная схема:
Код:
        File file = new File("Path to out file");
        JsonObject json = new JsonObject();
        json.add("Player UUID", new JsonPrimitive("Player Location"));
        Gson gson = new GsonBuilder().disableHtmlEscaping().create();
        try (BufferedWriter out = new BufferedWriter(new OutputStreamWriter(Files.newOutputStream(file.toPath())))) {
            gson.toJson(json, out);
        }
спасибо, но как можно
json.add("Player UUID", new JsonPrimitive("Player Location"));
где PlayerLocation превратить не в строку как по умолчанию, а в double (несколько значений). Я так понимаю все данные локации нужно сериализовать, но а дальше как их заносить

Java:
int x = location.getBlockX();
int y = location.getBlockY();
int z = location.getBlockZ();
int yaw = (int) location.getYaw();
int pitch = (int) location.getPitch();

вот эти все значения нужно поместить в json
 
Последнее редактирование:
Ты можешь преобразовать Location в строку, Location#getX() + ";" + Location#getZ()... и т.д
Либо, ты можешь систему json расширять, я скинул самую простую рабочую схему
но ведь это предназначено только для 1 игрока, тоесть когда зайдет 1 игрок и напишет эту команду, то все сохранится, но если и 2 игрок тоже напишет эту команду, то данные первого сотрутся, а данные второго занесутся
 
Использовать gson и не использовать его сериализацию/десериализацию данных это, конечно, странная идея.
В отличии от сериализации в строку вида x;y;z;yaw;pitch потребует больше места для хранения, но будет правильнее:
Java:
public class BukkitLocationSerializer implements JsonSerializer<Location>, JsonDeserializer<Location> {

    @Override
    public JsonElement serialize(Location location, Type type, JsonSerializationContext context) {
        JsonObject jo = new JsonObject();
        jo.addProperty("world", location.getWorld().getName());
        jo.addProperty("x", location.getX());
        jo.addProperty("y", location.getY());
        jo.addProperty("z", location.getZ());
        jo.addProperty("yaw", location.getYaw());
        jo.addProperty("pitch", location.getPitch());
        return jo;
    }

    @Override
    public Location deserialize(JsonElement json, Type type, JsonDeserializationContext context) throws JsonParseException {
        JsonObject jo = json.getAsJsonObject();
        return new Location(
            Bukkit.getWorld(jo.get("world").getAsString()),
            jo.get("x").getAsDouble(),
            jo.get("y").getAsDouble(),
            jo.get("z").getAsDouble(),
            jo.get("yaw").getAsFloat(),
            jo.get("pitch").getAsFloat()
       );
    }
}
Java:
private final Map<String, Location> map = new HashMap<>();
private static final Gson GSON = new GsonBuilder().registerTypeAdapter(Location.class, new BukkitLocationSerializer()).create();

//...
map.put(player.getUniqueId().toString(), location);
//...
try (final Writer writer = new FileWriter(file, false)) {
    GSON.toJson(map, writer);
}
Код написан на коленке.
 
Использовать gson и не использовать его сериализацию/десериализацию данных это, конечно, странная идея.
В отличии от сериализации в строку вида x;y;z;yaw;pitch потребует больше места для хранения, но будет правильнее:
Java:
public class BukkitLocationSerializer implements JsonSerializer<Location>, JsonDeserializer<Location> {

    @Override
    public JsonElement serialize(Location location, Type type, JsonSerializationContext context) {
        JsonObject jo = new JsonObject();
        jo.addProperty("world", location.getWorld().getName());
        jo.addProperty("x", location.getX());
        jo.addProperty("y", location.getY());
        jo.addProperty("z", location.getZ());
        jo.addProperty("yaw", location.getYaw());
        jo.addProperty("pitch", location.getPitch());
        return jo;
    }

    @Override
    public Location deserialize(JsonElement json, Type type, JsonDeserializationContext context) throws JsonParseException {
        JsonObject jo = json.getAsJsonObject();
        return new Location(
            Bukkit.getWorld(jo.get("world").getAsString()),
            jo.get("x").getAsDouble(),
            jo.get("y").getAsDouble(),
            jo.get("z").getAsDouble(),
            jo.get("yaw").getAsFloat(),
            jo.get("pitch").getAsFloat()
       );
    }
}
Java:
private final Map<String, Location> map = new HashMap<>();
private static final Gson GSON = new GsonBuilder().registerTypeAdapter(Location.class, new BukkitLocationSerializer()).create();

//...
map.put(player.getUniqueId().toString(), location);
//...
try (final Writer writer = new FileWriter(file, false)) {
    GSON.toJson(map, writer);
}
Код написан на коленке.
тоесть он добавился в json одной командой, а телепортировать его нужно другой, тоесть как считать то что находится внутри json файла? (нужно из json взять ник и локацию и телепортировать его по ней)
 
тоесть он добавился в json одной командой, а телепортировать его нужно другой, тоесть как считать то что находится внутри json файла? (нужно из json взять ник и локацию и телепортировать его по ней)
Пока сервер не перезагружен все данные есть в HashMap и брать локацию можно оттуда. Если их там нет – загружать JSON из файла, десериализовать и помещать в HashMap нужную запись (или все, в зависимости от необходимости).
Java:
final Map<String, Location> map;
try {
    map = GSON.fromJson(
        Files.readString(path, StandardCharsets.UTF_8),
        new TypeToken<Map<String, Location>>(){}.getType()
    );
} catch (IOException ex) {
    // ...
}
 
Пока сервер не перезагружен все данные есть в HashMap и брать локацию можно оттуда. Если их там нет – загружать JSON из файла, десериализовать и помещать в HashMap нужную запись (или все, в зависимости от необходимости).
Java:
final Map<String, Location> map;
try {
    map = GSON.fromJson(
        Files.readString(path, StandardCharsets.UTF_8),
        new TypeToken<Map<String, Location>>(){}.getType()
    );
} catch (IOException ex) {
    // ...
}
еще один вопросик, а если нужно иметь 2 команды с разными локациями (допустим есть spawn1 и она заносит игрока и координаты: elpomoika, 1, 1, 1; и есть вторая команда которая заносит: elpomoika: 2 2 2) как это сделать
 
еще один вопросик, а если нужно иметь 2 команды с разными локациями (допустим есть spawn1 и она заносит игрока и координаты: elpomoika, 1, 1, 1; и есть вторая команда которая заносит: elpomoika: 2 2 2) как это сделать
Не совсем до конца понимаю. Наверное, если хочется и дальше хранить в мапе эти данные, то пусть их будет просто две?
 
Не совсем до конца понимаю. Наверное, если хочется и дальше хранить в мапе эти данные, то пусть их будет просто две?
нет, нужно что-бы у игрока был выбор, либо спавнится на координатах 1 1 1 или на координатах 2 2 2 и эти координаты он будет выбирать как раз этими командами
 
нет, нужно что-бы у игрока был выбор, либо спавнится на координатах 1 1 1 или на координатах 2 2 2 и эти координаты он будет выбирать как раз этими командами
Ну тогда HashMap<String, List<Location>> или HashMap<String, Set<Location>>.
TypeToken будет new TypeToken<HashMap<String, List<Location>>>(){}.getType() соответственно.
 
Назад
Сверху Снизу