317 lines
16 KiB
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();
|
|
}
|
|
}
|