mirror of
https://github.com/Creators-of-Create/Create.git
synced 2025-01-27 05:18:08 +01:00
Prevent entries added through CopperRegistries from crashing the game
Most reported issues of this happening are actually caused by a different issue during registration that is suppressed due to the crash. Now that the crash can't happen, the underlying exception will be properly reported. This change also allows using Create with the Compressed mod, but if Compressed loads before Create, Create's additions to the CopperRegistries will fail to apply.
This commit is contained in:
parent
e40b844aa1
commit
088cc1a336
1 changed files with 48 additions and 2 deletions
|
@ -1,8 +1,12 @@
|
|||
package com.simibubi.create.foundation.block;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import com.google.common.base.Suppliers;
|
||||
import com.google.common.collect.BiMap;
|
||||
import com.google.common.collect.HashBiMap;
|
||||
|
@ -51,9 +55,11 @@ public class CopperRegistries {
|
|||
weatheringMemoized = true;
|
||||
ImmutableBiMap.Builder<Block, Block> builder = ImmutableBiMap.builder();
|
||||
builder.putAll(originalWeatheringMapDelegate.get());
|
||||
WEATHERING.forEach((original, weathered) -> {
|
||||
ErrorHandlingBiConsumer<Supplier<Block>, Supplier<Block>> consumer = new ErrorHandlingBiConsumer<>((original, weathered) -> {
|
||||
builder.put(original.get(), weathered.get());
|
||||
});
|
||||
WEATHERING.forEach(consumer);
|
||||
consumer.reportExceptions(Create.LOGGER, "weathering");
|
||||
return builder.build();
|
||||
};
|
||||
// Replace the memoized supplier's delegate, since interface fields cannot be reassigned
|
||||
|
@ -67,11 +73,51 @@ public class CopperRegistries {
|
|||
waxableMemoized = true;
|
||||
ImmutableBiMap.Builder<Block, Block> builder = ImmutableBiMap.builder();
|
||||
builder.putAll(originalWaxableMapSupplier.get());
|
||||
WAXABLE.forEach((original, waxed) -> {
|
||||
ErrorHandlingBiConsumer<Supplier<Block>, Supplier<Block>> consumer = new ErrorHandlingBiConsumer<>((original, waxed) -> {
|
||||
builder.put(original.get(), waxed.get());
|
||||
});
|
||||
WAXABLE.forEach(consumer);
|
||||
consumer.reportExceptions(Create.LOGGER, "waxable");
|
||||
return builder.build();
|
||||
});
|
||||
HoneycombItem.WAXABLES = waxableMapSupplier;
|
||||
}
|
||||
|
||||
// Create itself only ever adds BlockEntry objects to these registries, which throw if they are not populated with their
|
||||
// Block object. Normally this shouldn't happen as the weathering/waxable maps shouldn't be accessed before block
|
||||
// registration is complete, but internal Forge code or other mods may cause this to happen. It is better to catch the
|
||||
// exception rather than letting it crash the game.
|
||||
private static class ErrorHandlingBiConsumer<T, U> implements BiConsumer<T, U> {
|
||||
private final BiConsumer<T, U> delegate;
|
||||
private int exceptionCount = 0;
|
||||
@Nullable
|
||||
private Throwable firstException;
|
||||
|
||||
public ErrorHandlingBiConsumer(BiConsumer<T, U> delegate) {
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(T t, U u) {
|
||||
try {
|
||||
delegate.accept(t, u);
|
||||
} catch (Throwable throwable) {
|
||||
exceptionCount++;
|
||||
|
||||
if (firstException == null) {
|
||||
firstException = throwable;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void reportExceptions(Logger logger, String type) {
|
||||
if (exceptionCount != 0) {
|
||||
logger.error("Adding " + type + " copper entries from CopperRegistries encountered " + exceptionCount + " exception(s)!");
|
||||
|
||||
if (firstException != null) {
|
||||
logger.error("The first exception that was thrown is logged below.", firstException);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue