PrefabSnapshotUtil class
Пакет: com.hypixel.hytale.builtin.adventure.worldevents.util
Файл: com/hypixel/hytale/builtin/adventure/worldevents/util/PrefabSnapshotUtil.java
Поля (35)
| Модификаторы | Тип | Имя |
|---|---|---|
final |
String |
SNAPSHOT_DIRECTORY |
|
|
return |
|
Path |
var1 |
|
String |
var1 |
|
int |
var10 |
|
int |
var11 |
|
PrefabBuffer.Builder |
var12 |
|
BlockTypeAssetMap |
var13 |
|
PrefabUtil.PasteRegion.Column |
var16 |
|
PrefabBufferBlockEntry[] |
var17 |
|
int |
var18 |
|
Path |
var2 |
|
Path |
var2 |
|
Path |
var2 |
|
ObjectOpenHashSet |
var2 |
|
PrefabUtil.PasteRegion.Section |
var20 |
|
int |
var21 |
|
int |
var22 |
|
BlockType |
var23 |
|
UUID |
var24 |
|
Path |
var3 |
|
Path |
var3 |
|
String |
var3 |
|
Path |
var3 |
|
Path |
var3 |
|
PrefabBuffer |
var4 |
|
Path |
var4 |
|
Path |
var4 |
|
int |
var5 |
|
String |
var5 |
|
int |
var6 |
|
Path |
var6 |
|
int |
var7 |
|
int |
var8 |
|
int |
var9 |
Методы (12)
| Модификаторы | Возврат | Сигнатура |
|---|---|---|
static |
void |
deleteSnapshotvoid deleteSnapshot(@Nonnull World var0, @Nonnull UUID var1) |
|
|
for for(int var14 = var9; var14 <= var11; var14++) |
|
|
for for(int var15 = var8; var15 <= var10; var15++) |
|
|
for for(int var19 = 0; var18 <= var6; var19++) |
|
|
for for(Path var4 : var2) |
|
|
if if(var1 == null) |
|
|
if if(var2 == null) |
|
|
if if(var4 != null) |
|
|
if if(var23 == null) |
|
|
if if(var3 > 1) |
static |
void |
saveWithRetryvoid saveWithRetry(@Nonnull Path var0, @Nonnull Path var1, @Nonnull PrefabBuffer var2, int var3) |
static |
void |
writeSnapshotAsyncvoid writeSnapshotAsync(@Nonnull World var0, @Nonnull UUID var1, @Nonnull PrefabBuffer var2) |
Исходный код
Показать/скрыть
class="kw">package com.hypixel.hytale.builtin.adventure.worldevents.util;
class="kw">import com.hypixel.hytale.assetstore.map.BlockTypeAssetMap;
class="kw">import com.hypixel.hytale.builtin.adventure.worldevents.WorldEventManager;
class="kw">import com.hypixel.hytale.builtin.adventure.worldevents.context.PrefabRemoveContext;
class="kw">import com.hypixel.hytale.logger.HytaleLogger;
class="kw">import com.hypixel.hytale.logger.sentry.SkipSentryException;
class="kw">import com.hypixel.hytale.math.util.ChunkUtil;
class="kw">import com.hypixel.hytale.server.core.asset.type.blocktype.config.BlockType;
class="kw">import com.hypixel.hytale.server.core.asset.util.AssetPackPathUtil;
class="kw">import com.hypixel.hytale.server.core.prefab.PrefabRotation;
class="kw">import com.hypixel.hytale.server.core.prefab.selection.buffer.PrefabBufferUtil;
class="kw">import com.hypixel.hytale.server.core.prefab.selection.buffer.impl.IPrefabBuffer;
class="kw">import com.hypixel.hytale.server.core.prefab.selection.buffer.impl.PrefabBuffer;
class="kw">import com.hypixel.hytale.server.core.prefab.selection.buffer.impl.PrefabBufferBlockEntry;
class="kw">import com.hypixel.hytale.server.core.universe.world.World;
class="kw">import com.hypixel.hytale.server.core.util.PrefabUtil;
class="kw">import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet;
class="kw">import java.io.IOException;
class="kw">import java.nio.file.DirectoryStream;
class="kw">import java.nio.file.Files;
class="kw">import java.nio.file.Path;
class="kw">import java.util.Map;
class="kw">import java.util.UUID;
class="kw">import java.util.concurrent.CompletableFuture;
class="kw">import java.util.concurrent.ConcurrentHashMap;
class="kw">import java.util.concurrent.TimeUnit;
class="kw">import java.util.logging.Level;
class="kw">import javax.annotation.Nonnull;
class="kw">import javax.annotation.Nullable;
class="kw">import org.joml.Vector3ic;
class="kw">public class PrefabSnapshotUtil {
class="kw">public class="kw">static class="kw">final String SNAPSHOT_DIRECTORY = "snapshots";
class="kw">private class="kw">static class="kw">final HytaleLogger LOGGER = HytaleLogger.forEnclosingClass();
class="kw">private class="kw">static class="kw">final int MAX_WRITE_ATTEMPTS = 3;
class="kw">private class="kw">static class="kw">final long WRITE_RETRY_BACKOFF_MS = 250L;
class="kw">private class="kw">static class="kw">final Map<Path, PrefabBuffer> PENDING_SNAPSHOTS = new ConcurrentHashMap<>();
class="kw">private class="kw">static class="kw">final String[] MATCH_EXTENSIONS = new String[]{".prefab.json.lpf", ".lpf", ".prefab.json"};
class="kw">public PrefabSnapshotUtil() {
}
@Nullable
class="kw">public class="kw">static IPrefabBuffer getAssetPrefabOrNull(@Nonnull Path var0) {
Path var1 = resolveAssetPath(var0);
if (var1 == null) {
class="kw">return null;
}
Path var2 = resolveAssetReferencePath(var1);
if (var2 == null) {
class="kw">return null;
}
try {
class="kw">return PrefabBufferUtil.getCached(var2);
} catch (Throwable var4) {
PrefabBufferUtil.removeCached(var2);
((HytaleLogger.Api)((HytaleLogger.Api)LOGGER.atWarning()).withCause(var4)).log("Failed to get prefab buffer with error");
class="kw">return null;
}
}
@Nullable
class="kw">public class="kw">static IPrefabBuffer getSnapshotPrefabOrNull(@Nonnull World var0, @Nonnull UUID var1) {
Path var2 = var0.getSavePath().resolve("snapshots");
Path var3 = var2.resolve(var1.toString());
PrefabBuffer var4 = PENDING_SNAPSHOTS.get(var3);
if (var4 != null) {
class="kw">return var4.newAccess();
}
try {
class="kw">return PrefabBufferUtil.getCached(var3);
} catch (Throwable var6) {
class="kw">return null;
}
}
@Nonnull
class="kw">public class="kw">static UUID createSnapshot(
@Nonnull World var0, @Nonnull PrefabUtil.PasteRegion var1, @Nonnull IPrefabBuffer var2, @Nonnull Vector3ic var3, @Nonnull PrefabRotation var4
) {
assert var1.isFullyLoaded();
int var5 = var3.y() + var2.getMinY();
int var6 = var3.y() + var2.getMaxY();
int var7 = 1 + var6 - var5;
int var8 = var3.x() + var2.getMinX(var4);
int var9 = var3.z() + var2.getMinZ(var4);
int var10 = var3.x() + var2.getMaxX(var4);
int var11 = var3.z() + var2.getMaxZ(var4);
PrefabBuffer.Builder var12 = PrefabBuffer.newBuilder();
BlockTypeAssetMap var13 = BlockType.getAssetMap();
for (int var14 = var9; var14 <= var11; var14++) {
for (int var15 = var8; var15 <= var10; var15++) {
PrefabUtil.PasteRegion.Column var16 = var1.getColumnAtBlock(var15, var14);
PrefabBufferBlockEntry[] var17 = new PrefabBufferBlockEntry[var7];
int var18 = var5;
for (int var19 = 0; var18 <= var6; var19++) {
PrefabUtil.PasteRegion.Section var20 = var1.getSectionAtBlock(var15, var18, var14);
int var21 = ChunkUtil.indexBlock(var15, var18, var14);
int var22 = var20.getBlock(var21);
BlockType var23 = var13.getAsset(var22);
if (var23 == null) {
var17[var19] = new PrefabBufferBlockEntry(var18 - var3.y(), 0, "Empty");
} else {
var17[var19] = new PrefabBufferBlockEntry(
var18 - var3.y(),
var22,
var23.getId(),
1.0F,
var20.getState(var21),
var20.getFluid(var21),
var20.getFluidLevel(var21),
var20.getSupport(var21),
var20.getRotation(var21),
var20.getFiller(var21)
);
}
var18++;
}
var12.addColumn(var15 - var3.x(), var14 - var3.z(), var17, null);
}
}
UUID var24 = UUID.randomUUID();
writeSnapshotAsync(var0, var24, var12.build());
class="kw">return var24;
}
class="kw">public class="kw">static void deleteSnapshot(@Nonnull World var0, @Nonnull UUID var1) {
Path var2 = var0.getSavePath().resolve("snapshots");
Path var3 = var2.resolve(var1.toString());
PENDING_SNAPSHOTS.remove(var3);
Path var4 = resolveSnapshotPath(var2, var1);
CompletableFuture.completedFuture(var4).thenAcceptAsync(var1x -> {
try {
Files.deleteIfExists(var1x);
} catch (IOException var6) {
((HytaleLogger.Api)LOGGER.at(Level.WARNING).withCause(new SkipSentryException(var6))).log("Failed to delete world event snapshot %s", var1x);
} class="kw">finally {
PrefabBufferUtil.removeCached(var3);
}
});
}
@Nonnull
class="kw">public class="kw">static CompletableFuture<Void> cleanSnapshotsDir(@Nonnull World var0, @Nonnull WorldEventManager var1) {
ObjectOpenHashSet var2 = new ObjectOpenHashSet();
var1.forEach(var2, (var0x, var1x) -> var0x.context.forEach(PrefabRemoveContext.class, var1x, null, (var0xx, var1xx, var2x) -> {
String var3 = var0xx.snapshot().toString();
var1xx.add(var3);
}));
Path var3 = var0.getSavePath().resolve("snapshots");
class="kw">return CompletableFuture.runAsync(() -> {
if (Files.exists(var3)) {
try (DirectoryStream var2 = Files.newDirectoryStream(var3)) {
for (Path var4 : var2) {
String var5 = var4.getFileName().toString().replace(".lpf", "");
if (!var2.contains(var5)) {
Path var6 = var4.resolveSibling(var5);
PENDING_SNAPSHOTS.remove(var6);
PrefabBufferUtil.removeCached(var6);
try {
Files.deleteIfExists(var4);
} catch (IOException var9) {
((HytaleLogger.Api)((HytaleLogger.Api)LOGGER.atWarning()).withCause(var9)).log("Failed to remove snapshot prefab: %s", var4);
}
}
}
} catch (IOException var11) {
((HytaleLogger.Api)((HytaleLogger.Api)LOGGER.atWarning()).withCause(var11)).log("An error occurred whilst cleaning snapshots in: %s", var3);
}
}
});
}
@Nullable
class="kw">public class="kw">static Path resolveAssetPath(@Nonnull Path var0) {
if (var0.isAbsolute()) {
class="kw">return AssetPackPathUtil.relativizeAssetPath(var0) == null ? null : var0;
} else {
class="kw">return AssetPackPathUtil.resolveAssetPath(var0, MATCH_EXTENSIONS);
}
}
@Nonnull
class="kw">public class="kw">static Path resolveSnapshotPath(@Nonnull Path var0, @Nonnull UUID var1) {
class="kw">return var0.resolve(var1 + ".lpf");
}
@Nullable
class="kw">public class="kw">static Path resolveAssetReferencePath(@Nonnull Path var0) {
if (var0.getFileName() == null) {
class="kw">return null;
} else {
String var1 = var0.getFileName().toString();
if (var1.endsWith(".prefab.json.lpf")) {
class="kw">return var0.resolveSibling(var1.substring(0, var1.length() - ".prefab.json.lpf".length()));
} else if (var1.endsWith(".prefab.json")) {
class="kw">return var0.resolveSibling(var1.substring(0, var1.length() - ".prefab.json".length()));
} else {
class="kw">return var1.endsWith(".lpf") ? var0.resolveSibling(var1.substring(0, var1.length() - ".lpf".length())) : var0;
}
}
}
class="kw">protected class="kw">static void writeSnapshotAsync(@Nonnull World var0, @Nonnull UUID var1, @Nonnull PrefabBuffer var2) {
Path var3 = var0.getSavePath().resolve("snapshots");
Path var4 = var3.resolve(var1.toString());
PENDING_SNAPSHOTS.put(var4, var2);
try {
Files.createDirectories(var3);
} catch (IOException var6) {
((HytaleLogger.Api)((HytaleLogger.Api)LOGGER.atWarning()).withCause(new SkipSentryException(var6)))
.log("Failed to create world event snapshot directory %s", var3);
class="kw">return;
}
saveWithRetry(resolveSnapshotPath(var3, var1), var4, var2, 3);
}
class="kw">private class="kw">static void saveWithRetry(@Nonnull Path var0, @Nonnull Path var1, @Nonnull PrefabBuffer var2, int var3) {
PrefabBufferUtil.writeToFileAsync(var2, var0)
.thenRun(() -> PENDING_SNAPSHOTS.remove(var1))
.exceptionally(
var4 -> {
if (var3 > 1) {
CompletableFuture.delayedExecutor(250L, TimeUnit.MILLISECONDS).execute(() -> saveWithRetry(var0, var1, var2, var3 - 1));
} else {
((HytaleLogger.Api)LOGGER.at(Level.WARNING).withCause(var4))
.log("Failed to write world event snapshot %s, keeping it in memory for this session", var0);
}
class="kw">return null;
}
);
}
}