minecraft-source/src/net/minecraft/world/level/chunk/storage/SectionStorage.java

317 lines
16 KiB
Java

package net.minecraft.world.level.chunk.storage;
import org.apache.logging.log4j.LogManager;
import com.google.common.collect.ImmutableMap;
import net.minecraft.SharedConstants;
import java.util.Map;
import com.google.common.collect.Maps;
import net.minecraft.nbt.Tag;
import java.io.IOException;
import com.mojang.datafixers.types.DynamicOps;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.NbtOps;
import net.minecraft.world.level.Level;
import net.minecraft.Util;
import javax.annotation.Nullable;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.core.SectionPos;
import java.util.function.BooleanSupplier;
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
import java.io.File;
import net.minecraft.util.datafix.DataFixTypes;
import com.mojang.datafixers.DataFixer;
import java.util.function.Function;
import com.mojang.datafixers.Dynamic;
import java.util.function.BiFunction;
import it.unimi.dsi.fastutil.longs.LongLinkedOpenHashSet;
import java.util.Optional;
import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
import org.apache.logging.log4j.Logger;
import net.minecraft.util.Serializable;
public class SectionStorage<R extends Serializable> implements AutoCloseable {
private static final Logger LOGGER;
private final IOWorker worker;
private final Long2ObjectMap<Optional<R>> storage;
private final LongLinkedOpenHashSet dirty;
private final BiFunction<Runnable, Dynamic<?>, R> deserializer;
private final Function<Runnable, R> factory;
private final DataFixer fixerUpper;
private final DataFixTypes type;
public SectionStorage(final File file, final BiFunction<Runnable, Dynamic<?>, R> biFunction, final Function<Runnable, R> function, final DataFixer dataFixer, final DataFixTypes acd) {
this.storage = (Long2ObjectMap<Optional<R>>)new Long2ObjectOpenHashMap();
this.dirty = new LongLinkedOpenHashSet();
this.deserializer = biFunction;
this.factory = function;
this.fixerUpper = dataFixer;
this.type = acd;
this.worker = new IOWorker(new RegionFileStorage(file), file.getName());
}
protected void tick(final BooleanSupplier booleanSupplier) {
while (!this.dirty.isEmpty() && booleanSupplier.getAsBoolean()) {
final ChunkPos bje3 = SectionPos.of(this.dirty.firstLong()).chunk();
this.writeColumn(bje3);
}
}
@Nullable
protected Optional<R> get(final long long1) {
return (Optional<R>)this.storage.get(long1);
}
protected Optional<R> getOrLoad(final long long1) {
final SectionPos gd4 = SectionPos.of(long1);
if (this.outsideStoredRange(gd4)) {
return Optional.<R>empty();
}
Optional<R> optional5 = this.get(long1);
if (optional5 != null) {
return optional5;
}
this.readColumn(gd4.chunk());
optional5 = this.get(long1);
if (optional5 == null) {
throw Util.<IllegalStateException>pauseInIde(new IllegalStateException());
}
return optional5;
}
protected boolean outsideStoredRange(final SectionPos gd) {
return Level.isOutsideBuildHeight(SectionPos.sectionToBlockCoord(gd.y()));
}
protected R getOrCreate(final long long1) {
final Optional<R> optional4 = this.getOrLoad(long1);
if (optional4.isPresent()) {
return optional4.get();
}
final R abu5 = this.factory.apply(() -> this.setDirty(long1));
this.storage.put(long1, Optional.<R>of(abu5));
return abu5;
}
private void readColumn(final ChunkPos bje) {
this.<CompoundTag>readColumn(bje, (com.mojang.datafixers.types.DynamicOps<CompoundTag>)NbtOps.INSTANCE, this.tryRead(bje));
}
@Nullable
private CompoundTag tryRead(final ChunkPos bje) {
try {
return this.worker.load(bje);
}
catch (IOException iOException3) {
SectionStorage.LOGGER.error("Error reading chunk {} data from disk", bje, iOException3);
return null;
}
}
private <T> void readColumn(final ChunkPos bje, final DynamicOps<T> dynamicOps, @Nullable final T object) {
//
// This method could not be decompiled.
//
// Original Bytecode:
//
// 1: ifnonnull 45
// 4: iconst_0
// 5: istore integer5
// 7: iload integer5
// 9: bipush 16
// 11: if_icmpge 42
// 14: aload_0 /* this */
// 15: getfield net/minecraft/world/level/chunk/storage/SectionStorage.storage:Lit/unimi/dsi/fastutil/longs/Long2ObjectMap;
// 18: aload_1 /* bje */
// 19: iload integer5
// 21: invokestatic net/minecraft/core/SectionPos.of:(Lnet/minecraft/world/level/ChunkPos;I)Lnet/minecraft/core/SectionPos;
// 24: invokevirtual net/minecraft/core/SectionPos.asLong:()J
// 27: invokestatic java/util/Optional.empty:()Ljava/util/Optional;
// 30: invokeinterface it/unimi/dsi/fastutil/longs/Long2ObjectMap.put:(JLjava/lang/Object;)Ljava/lang/Object;
// 35: pop
// 36: iinc integer5, 1
// 39: goto 7
// 42: goto 203
// 45: new Lcom/mojang/datafixers/Dynamic;
// 48: dup
// 49: aload_2 /* dynamicOps */
// 50: aload_3 /* object */
// 51: invokespecial com/mojang/datafixers/Dynamic.<init>:(Lcom/mojang/datafixers/types/DynamicOps;Ljava/lang/Object;)V
// 54: astore dynamic5
// 56: aload dynamic5
// 58: invokestatic net/minecraft/world/level/chunk/storage/SectionStorage.getVersion:(Lcom/mojang/datafixers/Dynamic;)I
// 61: istore integer6
// 63: invokestatic net/minecraft/SharedConstants.getCurrentVersion:()Lcom/mojang/bridge/game/GameVersion;
// 66: invokeinterface com/mojang/bridge/game/GameVersion.getWorldVersion:()I
// 71: istore integer7
// 73: iload integer6
// 75: iload integer7
// 77: if_icmpeq 84
// 80: iconst_1
// 81: goto 85
// 84: iconst_0
// 85: istore boolean8
// 87: aload_0 /* this */
// 88: getfield net/minecraft/world/level/chunk/storage/SectionStorage.fixerUpper:Lcom/mojang/datafixers/DataFixer;
// 91: aload_0 /* this */
// 92: getfield net/minecraft/world/level/chunk/storage/SectionStorage.type:Lnet/minecraft/util/datafix/DataFixTypes;
// 95: invokevirtual net/minecraft/util/datafix/DataFixTypes.getType:()Lcom/mojang/datafixers/DSL$TypeReference;
// 98: aload dynamic5
// 100: iload integer6
// 102: iload integer7
// 104: invokeinterface com/mojang/datafixers/DataFixer.update:(Lcom/mojang/datafixers/DSL$TypeReference;Lcom/mojang/datafixers/Dynamic;II)Lcom/mojang/datafixers/Dynamic;
// 109: astore dynamic9
// 111: aload dynamic9
// 113: ldc_w "Sections"
// 116: invokevirtual com/mojang/datafixers/Dynamic.get:(Ljava/lang/String;)Lcom/mojang/datafixers/OptionalDynamic;
// 119: astore optionalDynamic10
// 121: iconst_0
// 122: istore integer11
// 124: iload integer11
// 126: bipush 16
// 128: if_icmpge 203
// 131: aload_1 /* bje */
// 132: iload integer11
// 134: invokestatic net/minecraft/core/SectionPos.of:(Lnet/minecraft/world/level/ChunkPos;I)Lnet/minecraft/core/SectionPos;
// 137: invokevirtual net/minecraft/core/SectionPos.asLong:()J
// 140: lstore long12
// 142: aload optionalDynamic10
// 144: iload integer11
// 146: invokestatic java/lang/Integer.toString:(I)Ljava/lang/String;
// 149: invokevirtual com/mojang/datafixers/OptionalDynamic.get:(Ljava/lang/String;)Lcom/mojang/datafixers/OptionalDynamic;
// 152: invokevirtual com/mojang/datafixers/OptionalDynamic.get:()Ljava/util/Optional;
// 155: aload_0 /* this */
// 156: lload long12
// 158: invokedynamic BootstrapMethod #1, apply:(Lnet/minecraft/world/level/chunk/storage/SectionStorage;J)Ljava/util/function/Function;
// 163: invokevirtual java/util/Optional.map:(Ljava/util/function/Function;)Ljava/util/Optional;
// 166: astore optional14
// 168: aload_0 /* this */
// 169: getfield net/minecraft/world/level/chunk/storage/SectionStorage.storage:Lit/unimi/dsi/fastutil/longs/Long2ObjectMap;
// 172: lload long12
// 174: aload optional14
// 176: invokeinterface it/unimi/dsi/fastutil/longs/Long2ObjectMap.put:(JLjava/lang/Object;)Ljava/lang/Object;
// 181: pop
// 182: aload optional14
// 184: aload_0 /* this */
// 185: lload long12
// 187: iload boolean8
// 189: invokedynamic BootstrapMethod #2, accept:(Lnet/minecraft/world/level/chunk/storage/SectionStorage;JZ)Ljava/util/function/Consumer;
// 194: invokevirtual java/util/Optional.ifPresent:(Ljava/util/function/Consumer;)V
// 197: iinc integer11, 1
// 200: goto 124
// 203: return
// Signature:
// <T:Ljava/lang/Object;>(Lnet/minecraft/world/level/ChunkPos;Lcom/mojang/datafixers/types/DynamicOps<TT;>;TT;)V
// MethodParameters:
// Name Flags
// ---------- -----
// bje
// dynamicOps
// object
// StackMapTable: 00 07 FF 00 07 00 05 07 00 02 07 00 F5 00 00 01 00 00 FF 00 22 00 00 00 00 FF 00 02 00 04 07 00 02 07 00 F5 07 01 0C 07 00 05 00 00 FF 00 26 00 07 07 00 02 07 00 F5 00 00 07 01 0E 01 01 00 00 40 01 FF 00 26 00 0B 07 00 02 07 00 F5 00 00 00 00 00 01 00 07 01 33 01 00 00 FF 00 4E 00 00 00 00
//
// The error that occurred was:
//
// java.lang.NullPointerException
// at com.strobel.decompiler.languages.java.ast.NameVariables.generateNameForVariable(NameVariables.java:264)
// at com.strobel.decompiler.languages.java.ast.NameVariables.assignNamesToVariables(NameVariables.java:198)
// at com.strobel.decompiler.languages.java.ast.AstMethodBodyBuilder.createMethodBody(AstMethodBodyBuilder.java:276)
// at com.strobel.decompiler.languages.java.ast.AstMethodBodyBuilder.createMethodBody(AstMethodBodyBuilder.java:99)
// at com.strobel.decompiler.languages.java.ast.AstBuilder.createMethodBody(AstBuilder.java:782)
// at com.strobel.decompiler.languages.java.ast.AstBuilder.createMethod(AstBuilder.java:675)
// at com.strobel.decompiler.languages.java.ast.AstBuilder.addTypeMembers(AstBuilder.java:552)
// at com.strobel.decompiler.languages.java.ast.AstBuilder.createTypeCore(AstBuilder.java:519)
// at com.strobel.decompiler.languages.java.ast.AstBuilder.createTypeNoCache(AstBuilder.java:161)
// at com.strobel.decompiler.languages.java.ast.AstBuilder.createType(AstBuilder.java:150)
// at com.strobel.decompiler.languages.java.ast.AstBuilder.addType(AstBuilder.java:125)
// at cuchaz.enigma.SourceProvider.getSources(SourceProvider.java:85)
// at cuchaz.enigma.EnigmaProject$JarExport.decompileClass(EnigmaProject.java:241)
// at cuchaz.enigma.EnigmaProject$JarExport.lambda$decompile$1(EnigmaProject.java:230)
// at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:195)
// at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1654)
// at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484)
// at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
// at java.base/java.util.stream.ReduceOps$ReduceTask.doLeaf(ReduceOps.java:952)
// at java.base/java.util.stream.ReduceOps$ReduceTask.doLeaf(ReduceOps.java:926)
// at java.base/java.util.stream.AbstractTask.compute(AbstractTask.java:327)
// at java.base/java.util.concurrent.CountedCompleter.exec(CountedCompleter.java:746)
// at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:290)
// at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.helpCC(ForkJoinPool.java:1115)
// at java.base/java.util.concurrent.ForkJoinPool.externalHelpComplete(ForkJoinPool.java:1957)
// at java.base/java.util.concurrent.ForkJoinTask.tryExternalHelp(ForkJoinTask.java:378)
// at java.base/java.util.concurrent.ForkJoinTask.externalAwaitDone(ForkJoinTask.java:323)
// at java.base/java.util.concurrent.ForkJoinTask.doInvoke(ForkJoinTask.java:412)
// at java.base/java.util.concurrent.ForkJoinTask.invoke(ForkJoinTask.java:736)
// at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateParallel(ReduceOps.java:919)
// at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:233)
// at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:578)
// at cuchaz.enigma.EnigmaProject$JarExport.decompile(EnigmaProject.java:233)
// at cuchaz.enigma.command.DecompileCommand.run(DecompileCommand.java:35)
// at cuchaz.enigma.CommandMain.main(CommandMain.java:43)
//
throw new IllegalStateException("An error occurred while decompiling this method.");
}
private void writeColumn(final ChunkPos bje) {
final Dynamic<Tag> dynamic3 = this.<Tag>writeColumn(bje, (com.mojang.datafixers.types.DynamicOps<Tag>)NbtOps.INSTANCE);
final Tag kj4 = (Tag)dynamic3.getValue();
if (kj4 instanceof CompoundTag) {
this.worker.store(bje, (CompoundTag)kj4);
}
else {
SectionStorage.LOGGER.error("Expected compound tag, got {}", kj4);
}
}
private <T> Dynamic<T> writeColumn(final ChunkPos bje, final DynamicOps<T> dynamicOps) {
final Map<T, T> map4 = Maps.newHashMap();
for (int integer5 = 0; integer5 < 16; ++integer5) {
final long long6 = SectionPos.of(bje, integer5).asLong();
this.dirty.remove(long6);
final Optional<R> optional8 = (Optional<R>)this.storage.get(long6);
if (optional8 != null) {
if (optional8.isPresent()) {
map4.put((T)dynamicOps.createString(Integer.toString(integer5)), optional8.get().<T>serialize(dynamicOps));
}
}
}
return (Dynamic<T>)new Dynamic((DynamicOps)dynamicOps, dynamicOps.createMap((Map)ImmutableMap.of(dynamicOps.createString("Sections"), dynamicOps.createMap((Map)map4), dynamicOps.createString("DataVersion"), dynamicOps.createInt(SharedConstants.getCurrentVersion().getWorldVersion()))));
}
protected void onSectionLoad(final long long1) {
}
protected void setDirty(final long long1) {
final Optional<R> optional4 = (Optional<R>)this.storage.get(long1);
if (optional4 == null || !optional4.isPresent()) {
SectionStorage.LOGGER.warn("No data for position: {}", SectionPos.of(long1));
return;
}
this.dirty.add(long1);
}
private static int getVersion(final Dynamic<?> dynamic) {
return dynamic.get("DataVersion").asNumber().orElse(1945).intValue();
}
public void flush(final ChunkPos bje) {
if (!this.dirty.isEmpty()) {
for (int integer3 = 0; integer3 < 16; ++integer3) {
final long long4 = SectionPos.of(bje, integer3).asLong();
if (this.dirty.contains(long4)) {
this.writeColumn(bje);
return;
}
}
}
}
@Override
public void close() throws IOException {
this.worker.close();
}
static {
LOGGER = LogManager.getLogger();
}
}