From 4b2981ba13b7225005421eef88116b0bffc5381f Mon Sep 17 00:00:00 2001 From: raoulvdberge Date: Fri, 11 Oct 2024 16:35:24 +0200 Subject: [PATCH] fix: resources with changed data format or id causing load error --- CHANGELOG.md | 1 + .../storage/ErrorHandlingListCodec.java | 76 +++++++++++++++++++ .../common/storage/StorageCodecs.java | 2 +- 3 files changed, 78 insertions(+), 1 deletion(-) create mode 100644 refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/storage/ErrorHandlingListCodec.java diff --git a/CHANGELOG.md b/CHANGELOG.md index b670f9698..607f44f6d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -39,6 +39,7 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - Fixed mouse keybindings not working on NeoForge. - Fixed upgrade destinations not being shown on upgrades. +- Fixed resources with changed data format or ID causing entire storage to fail to load. ## [2.0.0-milestone.4.7] - 2024-08-11 diff --git a/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/storage/ErrorHandlingListCodec.java b/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/storage/ErrorHandlingListCodec.java new file mode 100644 index 000000000..51c464ac9 --- /dev/null +++ b/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/storage/ErrorHandlingListCodec.java @@ -0,0 +1,76 @@ +package com.refinedmods.refinedstorage.common.storage; + +import java.util.ArrayList; +import java.util.List; + +import com.mojang.datafixers.util.Pair; +import com.mojang.serialization.Codec; +import com.mojang.serialization.DataResult; +import com.mojang.serialization.DynamicOps; +import com.mojang.serialization.Lifecycle; +import com.mojang.serialization.ListBuilder; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +class ErrorHandlingListCodec implements Codec> { + private static final String ERROR_MESSAGE = """ + Refined Storage could not load a resource in storage. + This could be because the resource no longer exists after a mod update, or if the data format of the + resource has changed. In any case, this is NOT caused by Refined Storage. + Refined Storage will try to gracefully handle this problem and continue to load the storage data. + The problematic resource might end up being removed from storage, or may no longer have any additional data + associated with it. + Error message:"""; + + private static final Logger LOGGER = LoggerFactory.getLogger(ErrorHandlingListCodec.class); + + private final Codec elementCodec; + + ErrorHandlingListCodec(final Codec elementCodec) { + this.elementCodec = elementCodec; + } + + @Override + public DataResult encode(final List input, final DynamicOps ops, final T prefix) { + final ListBuilder builder = ops.listBuilder(); + for (final E element : input) { + builder.add(elementCodec.encodeStart(ops, element)); + } + return builder.build(prefix); + } + + @Override + public DataResult, T>> decode(final DynamicOps ops, final T input) { + return ops.getList(input).setLifecycle(Lifecycle.stable()).flatMap(stream -> { + final DecoderState decoder = new DecoderState<>(ops); + stream.accept(decoder::accept); + return decoder.build(); + }); + } + + @Override + public String toString() { + return "ErrorHandlingListCodec[" + elementCodec + ']'; + } + + private class DecoderState { + private final DynamicOps ops; + private final List elements = new ArrayList<>(); + + private DecoderState(final DynamicOps ops) { + this.ops = ops; + } + + private void accept(final T value) { + final DataResult> elementResult = elementCodec.decode(ops, value); + elementResult.error().ifPresent( + error -> LOGGER.warn("{} {}", ERROR_MESSAGE, error.message()) + ); + elementResult.resultOrPartial().ifPresent(pair -> elements.add(pair.getFirst())); + } + + private DataResult, T>> build() { + return DataResult.success(Pair.of(elements, ops.empty())); + } + } +} diff --git a/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/storage/StorageCodecs.java b/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/storage/StorageCodecs.java index cfd0c8031..c19707385 100644 --- a/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/storage/StorageCodecs.java +++ b/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/storage/StorageCodecs.java @@ -49,7 +49,7 @@ static MapCodec> sameTypeStorageData(fina return RecordCodecBuilder.mapCodec(instance -> instance.group( Codec.optionalField("capacity", Codec.LONG, false).forGetter(StorageData::capacity), - Codec.list(storageResourceCodec).fieldOf("resources").forGetter(StorageData::resources) + new ErrorHandlingListCodec<>(storageResourceCodec).fieldOf("resources").forGetter(StorageData::resources) ).apply(instance, StorageData::new)); }