Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: resources with changed data format or id causing load error #701

Merged
merged 1 commit into from
Oct 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
Original file line number Diff line number Diff line change
@@ -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<E> implements Codec<List<E>> {
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<E> elementCodec;

ErrorHandlingListCodec(final Codec<E> elementCodec) {
this.elementCodec = elementCodec;
}

@Override
public <T> DataResult<T> encode(final List<E> input, final DynamicOps<T> ops, final T prefix) {
final ListBuilder<T> builder = ops.listBuilder();
for (final E element : input) {
builder.add(elementCodec.encodeStart(ops, element));
}
return builder.build(prefix);
}

@Override
public <T> DataResult<Pair<List<E>, T>> decode(final DynamicOps<T> ops, final T input) {
return ops.getList(input).setLifecycle(Lifecycle.stable()).flatMap(stream -> {
final DecoderState<T> decoder = new DecoderState<>(ops);
stream.accept(decoder::accept);
return decoder.build();
});
}

@Override
public String toString() {
return "ErrorHandlingListCodec[" + elementCodec + ']';
}

private class DecoderState<T> {
private final DynamicOps<T> ops;
private final List<E> elements = new ArrayList<>();

private DecoderState(final DynamicOps<T> ops) {
this.ops = ops;
}

private void accept(final T value) {
final DataResult<Pair<E, T>> 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<Pair<List<E>, T>> build() {
return DataResult.success(Pair.of(elements, ops.empty()));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ static <T extends ResourceKey> MapCodec<StorageData<T>> 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));
}

Expand Down
Loading