Округление и перезапись в config'е

Версия Minecraft
1.20+
API
Forge
342
33
54
HI

Такие две проблемы

1. При сохранении значения восстанавливаются до стандартных:

Была уже такая тема, но с того момента я переписал саму систему сохранения + как-то подзабил на cfg
Общий метод остался примерно тем же

Java:
public void save() {
  try (final PrintWriter writer = new PrintWriter(new OutputStreamWriter(new FileOutputStream(this.getConfig().toFile()), StandardCharsets.UTF_8))) {
      this.entries.forEach(configEntry -> configEntry.save(writer));
  } catch (IOException e) {
      ToadLib.LOGGER.error(ToadLib.CONFIG, "Failed to save '{}'", this.path);
  }
}

Только внутри каждого configEntry теперь есть свой save()
Java:
public void save(PrintWriter writer) {
   DataResult<JsonElement> result = this.codec.encodeStart(JsonOps.INSTANCE, this.get());
   result.error().ifPresent(r -> ToadLib.LOGGER.error(ToadLib.CONFIG, "Failed to save '{}':{}", this.name, r.message()));
   result.result().ifPresent(r -> {
        writer.print(this.name);
        writer.print(":");
        writer.println(r);
   });
 }

codec зависит он entry(т.е может быть и float и bool и т.д)

Ну проблема та же...

2. Округление чисел:

Код загрузки:

Общий
Java:
public void load() {
     if (Files.notExists(this.getConfig())) {
         return;
     }

     CompoundTag nbt = new CompoundTag();

     try (BufferedReader bufferedreader = Files.newBufferedReader(this.getConfig(), Charsets.UTF_8)) {
          bufferedreader.lines().forEach((line) -> {
             try {
                 Iterator<String> iterator = OPTION_SPLITTER.split(line).iterator();
                 nbt.putString(iterator.next(), iterator.next());
             } catch (Exception e) {
                 ToadLib.LOGGER.error(ToadLib.CONFIG, "Skipping bad entry: '{}' in '{}'", line, this.path);
             }
         });
     } catch (IOException e) {
         ToadLib.LOGGER.error(ToadLib.CONFIG, "Failed to load '{}'", this.path, e);
     }

     StringFunction<OptionalString> value = s -> nbt.contains(s) ? OptionalString.of(nbt.getString(s)) : OptionalString.empty();
     this.entries.forEach(configEntry -> value.apply(configEntry.toString()).ifPresent(s -> configEntry.load(new JsonReader(new StringReader(s.isEmpty() ? "\"\"" : s)))));


     ToadLib.LOGGER.info(ToadLib.CONFIG, "E is '{}'", ToadLibConfig.E.get());
}


Внутри entry
Java:
public void load(JsonReader reader) {
    JsonElement element = JsonParser.parseReader(reader);
    DataResult<T> result = this.codec.parse(JsonOps.INSTANCE, element);
    result.error().ifPresent(r -> ToadLib.LOGGER.error(ToadLib.CONFIG, "Error parsing '{}':{}", this.name, r.message()));
    result.result().ifPresent(this::setValue);
}

Грузит всё нормально... кроме float и double(возможно)
Загрузчик округляет числа
Например 2.99999999 -> 3

конфиг все еще .txt
 
Решение
Во первых, советую добавить логирование в save(entries), так ты будешь видеть точно какие значения загружаются.
Java:
    public void save() {
        try (final PrintWriter writer = new PrintWriter(new OutputStreamWriter(new FileOutputStream(this.getConfig().toFile()), StandardCharsets.UTF_8))) {
            this.entries.forEach(configEntry -> {
                ToadLib.LOGGER.info("Saving entry: {} with value: {}", configEntry.getName(), configEntry.get());
                configEntry.save(writer);
            });
        } catch (IOException e) {
            ToadLib.LOGGER.error(ToadLib.CONFIG, "Failed to save '{}'", this.path);
        }
    }

Во вторых, попробуй использовать BigDecimal.
Он хорошо подходит для работы с float и...
Во первых, советую добавить логирование в save(entries), так ты будешь видеть точно какие значения загружаются.
Java:
    public void save() {
        try (final PrintWriter writer = new PrintWriter(new OutputStreamWriter(new FileOutputStream(this.getConfig().toFile()), StandardCharsets.UTF_8))) {
            this.entries.forEach(configEntry -> {
                ToadLib.LOGGER.info("Saving entry: {} with value: {}", configEntry.getName(), configEntry.get());
                configEntry.save(writer);
            });
        } catch (IOException e) {
            ToadLib.LOGGER.error(ToadLib.CONFIG, "Failed to save '{}'", this.path);
        }
    }

Во вторых, попробуй использовать BigDecimal.
Он хорошо подходит для работы с float и double.
Java:
    private BigDecimal value;

    public void setValue(BigDecimal value) {
        this.value = value;
    }

    public BigDecimal getValue() {
        return value;
    }
В третьих, ты проверял как ты парсишь?
Ты уверен что ты не допускаешь ошибку?

Тут единственное что поменялось, это writer.println(r.toString());
Java:
    public void save(PrintWriter writer) {
        DataResult<JsonElement> result = this.codec.encodeStart(JsonOps.INSTANCE, this.get());
        result.error().ifPresent(r -> ToadLib.LOGGER.error(ToadLib.CONFIG, "Failed to save '{}':{}", this.name, r.message()));
        result.result().ifPresent(r -> {
            writer.print(this.name);
            writer.print(":");
            writer.println(r.toString());
        });
    }
 
Во вторых, попробуй использовать BigDecimal.
Спасибо, это решило проблему с округлением

Codec для big decimal, может кому пригодится(может и кривой, но работает)
Java:
    public static final Codec<BigDecimal> BIG_DECIMAL = ExtraCodecs.JSON.flatXmap(f -> {
        try {
            return DataResult.success(f.getAsBigDecimal());
        } catch (JsonParseException | UnsupportedOperationException e) {
            return DataResult.error(e::getMessage);
        }
    }, d -> {
        try {
            return DataResult.success(new JsonPrimitive(d));
        } catch (IllegalArgumentException e) {
            return DataResult.error(e::getMessage);
        }
    });

Вторую проблему так же удалось решить, изменил codec, и расставил правильно методы save и load
 
Код со StackOverflow. Должен работать в 30 быстрее манипуляций со String, и уж тем более BigDecimal.

Java:
public double limitPrecision(String dblAsString, int maxDigitsAfterDecimal) {
    int multiplier = (int) Math.pow(10, maxDigitsAfterDecimal);
    double truncated = (double) ((long) ((Double.parseDouble(dblAsString)) * multiplier)) / multiplier;
    System.out.println(dblAsString + " ==> " + truncated); //Тута просто вывод
    return truncated;
}
 
Назад
Сверху