Fix crash when reloading a world that uses custom placed features. Closes #9979

This commit is contained in:
RealMangoRage authored and GitHub committed 2024-05-20 23:23:45 -07:00
1 parent 7c36115e3d
commit 95b49bedbc
8 files changed
+236 -1

No files matched your search

@@ -0,0 +1,88 @@
package net.minecraftforge.common.util;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.function.Supplier;
public interface ClearableLazy<T> extends Lazy<T> {
void invalidate();
/**
* Constructs a lazy-initialized object
* @param supplier The supplier for the value, to be called the first time the value is needed.
*/
static <T> ClearableLazy<T> of(@NotNull Supplier<T> supplier) {
return new ClearableLazy.Fast<T>(supplier);
}
/**
* Constructs a thread-safe lazy-initialized object
* @param supplier The supplier for the value, to be called the first time the value is needed.
*/
static <T> ClearableLazy<T> concurrentOf(@NotNull Supplier<T> supplier) {
return new ClearableLazy.Concurrent<>(supplier);
}
/**
* Non-thread-safe implementation.
*/
final class Fast<T> implements ClearableLazy<T> {
private final Supplier<T> supplier;
private T instance;
private Fast(Supplier<T> supplier) {
this.supplier = supplier;
}
@Nullable
@Override
public final T get() {
if (instance == null) {
instance = supplier.get();
}
return instance;
}
@Override
public void invalidate() {
this.instance = null;
}
}
/**
* Thread-safe implementation.
*/
final class Concurrent<T> implements ClearableLazy<T> {
private final Object lock = new Object();
private final Supplier<T> supplier;
private volatile T instance;
private Concurrent(Supplier<T> supplier) {
this.supplier = supplier;
}
@Nullable
@Override
public final T get()
{
var ret = instance;
if (ret == null) {
synchronized (lock) {
if (instance == null) {
return instance = supplier.get();
}
}
}
return ret;
}
@Override
public void invalidate() {
synchronized (lock) {
this.instance = null;
}
}
}
}
@@ -132,6 +132,10 @@ public class ServerLifecycleHooks {
registries.registryOrThrow(Registries.BIOME).holders().forEach(biomeHolder ->
biomeHolder.value().modifiableBiomeInfo().applyBiomeModifiers(biomeHolder, biomeModifiers)
);
// Rebuild the indexed feature list
registries.registryOrThrow(Registries.LEVEL_STEM).forEach(levelStem -> {
levelStem.generator().refreshFeaturesPerStep();
});
// Apply sorted structure modifiers to each structure.
registries.registryOrThrow(Registries.STRUCTURE).holders().forEach(structureHolder ->
structureHolder.value().modifiableStructureInfo().applyStructureModifiers(structureHolder, structureModifiers)