AssetEditorPlugin class

Пакет: com.hypixel.hytale.builtin.asseteditor

Файл: com/hypixel/hytale/builtin/asseteditor/AssetEditorPlugin.java

extends: JavaPlugin

Поля (288)

МодификаторыТипИмя
NOT_INITIALIZED, INITIALIZING, INITIALIZED
FAILED, SUCCEEDED, SUCCEEDED_COMMON_ASSETS_CHANGED
break
break
break
break
break
static AssetEditorPlugin instance
instance
public final Instant lastModificationDate
public final AssetPath path
return
return
return
return
return
return
return
return
return
return
return
return
return
return
return
return
return
return
return
return
return
return
return
return
return
return
return
return
return
return
return
return
return
return
return
return
return
return
return
return
return
return
return
return
EventRegistry var1
Message var1
long var1
List var1
AssetPackManifest var1
AssetEditorLastModifiedAssets var1
List var1
List var10
long var10
JsonUpdateCommand var10
JsonUpdateCommand var10
Object2ObjectOpenHashMap var10
HashSet var10
byte[] var10
Schema var10
BsonValue var10
AssetEditorAssetUpdated var11
DataSource var11
AuthorInfo var11
AssetEditorAsset var11
AssetStore var11
byte[] var11
var11
AssetUpdateQuery.RebuildCacheBuilder var11
AssetUndoRedoInfo var11
AssetEditorFileEntry var11
AssetInheritanceTreeNode[] var11
var11
var11
Path var12
PluginManifest var12
AuthorInfo var12
Path var12
AssetEditorAsset var12
AssetMap var12
BsonDocument var12
var12
BsonDocument var12
var12
AssetEditorFileEntry var12
AssetEditorAssetListUpdate var12
AssetInheritanceTreeNode var12
AssetEditorFileEntry var13
List var13
AssetModule var13
HytaleServerConfig var13
AssetEditorAsset var13
String var13
AssetUpdateQuery.RebuildCacheBuilder var13
String var13
AssetEditorFileEntry var13
IEventDispatcher var13
Instant var14
Object var14
String var14
AssetEditorAssetListUpdate var14
String[] var15
Path var15
BsonValue var15
String var16
Path var17
String var17
AssetUpdateQuery.RebuildCache var17
PluginIdentifier var18
List var18
String var19
Path var19
PluginManifest var2
List var2
DataSource var2
DataSource var2
I18nModule var2
AssetStore var2
AssetStore var2
AssetEditorAssetListUpdate var2
long var2
long var2
DataSource var2
List var2
long var2
var2
Path var20
String var20
long var20
HytaleServerConfig var21
Path var21
Map var22
Path var22
String var26
long var27
long var28
byte[] var28
var28
StandardDataSource var3
AssetTree var3
Map var3
long var3
long var3
ObjectArrayList var3
PlayerRef var3
boolean var3
IEventDispatcher var3
DataSource var3
AssetPackManifest var3
ObjectArrayList var3
DataSource var3
DataSource var3
DataSource var3
String var3
AssetTree var30
AssetUpdateQuery.RebuildCacheBuilder var30
long var31
BsonDocument var31
var31
String var32
AssetUndoRedoInfo var33
long var4
Map var4
DataSource var4
Path var4
String var4
Map var4
boolean var4
Path var4
var4
DataSource var4
String var4
var4
AssetEditorLastModifiedAssets var4
DataSource var4
DataSource var4
DataSource var4
DataSource var4
DataSource var4
DataSource var4
DataSource var4
byte[] var4
AssetEditorAssetUpdated var4
AssetEditorJsonAssetUpdated var4
DataSource var4
Path var4
Map var5
ObjectArrayList var5
long var5
Path var5
long var5
AssetEditorSetupSchemas var5
boolean var5
boolean var5
var5
var5
PluginManifest var5
PluginManifest var5
com.hypixel.hytale.protocol.packets.asseteditor.AuthorInfo var5
AssetPath var5
DataSource var5
AssetTypeHandler var5
AssetTypeHandler var5
long var5
DataSource var5
AssetTypeHandler var5
DataSource var5
long var5
long var5
BsonDocument var5
var5
Path var5
AssetEditorFileEntry var6
int var6
boolean var6
boolean var6
var6
var6
List var6
DataSource var6
AssetTypeHandler var6
AssetTypeHandler var6
long var6
long var6
long var6
AssetStore var6
long var6
AssetTypeHandler var6
String var6
AssetPath var7
boolean var7
List var7
byte[] var7
String var7
var7
long var7
AssetTypeHandler var7
byte[] var7
AssetMap var7
String var7
AssetEditorFileEntry var7
Path var7
DataSource var7
String var8
Path var8
long var8
AssetEditorAssetPackSetup var8
byte[][] var8
AssetTypeHandler var8
AssetUndoRedoInfo var8
AssetUndoRedoInfo var8
byte[] var8
Object var8
AssetEditorFileEntry var8
long var8
AssetEditorAssetListUpdate var8
AssetEditorFileEntry var8
AssetTypeHandler var8
byte[] var8
UpdateTranslations[] var9
var9
AssetEditorFileEntry var9
String var9
ToClientPacket[] var9
IEventDispatcher var9
DataSource var9
var9
var9
JsonUpdateCommand var9
byte[] var9
var9
BsonDocument var9
Set var9
AssetEditorAssetListUpdate var9
AssetEditorAssetListUpdate var9
long var9
BsonDocument var9
var9

Методы (152)

МодификаторыВозвратСигнатура
public AssetToDiscardpublic AssetToDiscard(AssetPath var1, @Nullable String var2)
DiscardResult DiscardResult()
InitState InitState()
abstract throw new RuntimeExceptionthrow new RuntimeException("Failed to resolve the real path for asset pack directory while deleting asset pack '" + var2 + "'.", var11)
abstract new SchemaContextnew SchemaContext()
private BsonDocument applyCommandsToAssetBsonDocument applyCommandsToAsset(@Nonnull byte[] var1, AssetPath var2, @Nonnull JsonUpdateCommand[] var3, @Nonnull AssetUpdateQuery.RebuildCacheBuilder var4)
private void broadcastPackAddedOrUpdatedvoid broadcastPackAddedOrUpdated(@Nonnull String var1, @Nonnull PluginManifest var2)
for for(EditorClient var5 : var3)
for for(EditorClient var4 : var2)
for for(EditorClient var9 : var7)
for for(EditorClient var6 : var4)
for for(EditorClient var13 : var10)
for for(com.hypixel.hytale.protocol.packets.asseteditor.AuthorInfo var11 : var3.authors)
for for(com.hypixel.hytale.protocol.packets.asseteditor.AuthorInfo var10 : var2.authors)
for for(EditorClient var7 : var5)
for for(AssetPath var5 : var2)
for for(int var10 = 0; var10 < var8.length; var10++)
for for(JsonUpdateCommand var20 : var5)
for for(Object var12 : var9)
for for(JsonUpdateCommand var9 : var3)
for for(JsonUpdateCommand var14 : var3)
for for(EditorClient var3 : this.clientsSubscribedToModifiedAssetsChanges)
abstract for for(int var17 = 0; var17 < var13.size()
static AssetEditorPlugin getAssetEditorPlugin get()
public void handleAssetUpdatevoid handleAssetUpdate(@Nonnull EditorClient var1, @Nonnull AssetPath var2, @Nonnull byte[] var3, int var4)
public void handleCreateAssetvoid handleCreateAsset(@Nonnull EditorClient var1, @Nonnull AssetPath var2, @Nonnull byte[] var3, @Nonnull AssetEditorRebuildCaches var4, String var5, int var6)
public void handleCreateAssetPackvoid handleCreateAssetPack(@Nonnull EditorClient var1, @Nonnull AssetPackManifest var2, int var3, int var4)
public void handleCreateDirectoryvoid handleCreateDirectory(@Nonnull EditorClient var1, @Nonnull AssetPath var2, int var3)
public void handleDeleteAssetvoid handleDeleteAsset(@Nonnull EditorClient var1, @Nonnull AssetPath var2, int var3)
public void handleDeleteAssetPackvoid handleDeleteAssetPack(@Nonnull EditorClient var1, @Nonnull String var2)
public void handleDeleteDirectoryvoid handleDeleteDirectory(@Nonnull EditorClient var1, @Nonnull AssetPath var2, int var3)
public void handleEditorClientDisconnectedvoid handleEditorClientDisconnected(@Nonnull EditorClient var1, @Nonnull PacketHandler.DisconnectReason var2)
public void handleExportAssetsvoid handleExportAssets(@Nonnull EditorClient var1, @Nonnull List<AssetPath> var2)
public void handleFetchAssetvoid handleFetchAsset(@Nonnull EditorClient var1, @Nonnull AssetPath var2, int var3)
public void handleFetchJsonAssetWithParentsvoid handleFetchJsonAssetWithParents(@Nonnull EditorClient var1, @Nonnull AssetPath var2, boolean var3, int var4)
public void handleFetchLastModifiedAssetsvoid handleFetchLastModifiedAssets(@Nonnull EditorClient var1)
public void handleInitializeClientvoid handleInitializeClient(@Nonnull EditorClient var1)
public void handleInitializeEditorvoid handleInitializeEditor(@Nonnull Ref<EntityStore> var1, @Nonnull ComponentAccessor<EntityStore> var2)
public void handleJsonAssetUpdatevoid handleJsonAssetUpdate(@Nonnull EditorClient var1, AssetPath var2, @Nonnull String var3, int var4, @Nonnull JsonUpdateCommand[] var5, int var6)
public void handleRedovoid handleRedo(@Nonnull EditorClient var1, @Nonnull AssetPath var2, int var3)
public void handleRenameAssetvoid handleRenameAsset(@Nonnull EditorClient var1, @Nonnull AssetPath var2, @Nonnull AssetPath var3, int var4)
public void handleRenameDirectoryvoid handleRenameDirectory(@Nonnull EditorClient var1, AssetPath var2, AssetPath var3, int var4)
public void handleRequestAssetInheritancevoid handleRequestAssetInheritance(@Nonnull EditorClient var1, @Nonnull AssetPath var2, int var3)
public void handleRequestChildIdsvoid handleRequestChildIds(@Nonnull EditorClient var1, @Nonnull AssetPath var2)
public void handleSelectAssetvoid handleSelectAsset(@Nonnull EditorClient var1, @Nullable AssetPath var2)
public void handleSubscribeToModifiedAssetsChangesvoid handleSubscribeToModifiedAssetsChanges(@Nonnull EditorClient var1)
public void handleUndovoid handleUndo(@Nonnull EditorClient var1, @Nonnull AssetPath var2, int var3)
public void handleUnsubscribeFromModifiedAssetsChangesvoid handleUnsubscribeFromModifiedAssetsChanges(@Nonnull EditorClient var1)
public void handleUpdateAssetPackvoid handleUpdateAssetPack(@Nonnull EditorClient var1, @Nonnull String var2, @Nonnull AssetPackManifest var3)
if if(var2 == null)
if if(this.pingClientsTask != null)
if if(var2 != null)
if if(var9 == null)
if if(var9.length != 0)
if if(this.initState != AssetEditorPlugin.InitState.NOT_INITIALIZED)
if if(this.scheduledReinitFuture != null)
if if(this.initState != AssetEditorPlugin.InitState.NOT_INITIALIZED)
if if(this.scheduledReinitFuture != null)
if if(var4 != null)
if if(var9 != null)
if if(var13 != null)
if if(var6 != null)
if if(var2.deletions != null || var2.additions != null)
if if(this.initState == AssetEditorPlugin.InitState.NOT_INITIALIZED)
if if(var1)
if if(var6)
if if(var2x == null)
if if(var3 == null)
if if(!var5)
if if(!var5)
if if(var4 == null)
if if(var5 == null)
if if(var3.description != null)
if if(var3.website != null)
if if(var3.authors != null)
if if(var3.serverVersion != null)
if if(var6)
if if(var2.description != null)
if if(var2.website != null)
if if(var2.authors != null)
if if(var6 == null)
if if(var7 == null)
if if(var2 != null)
if if(var3 == null)
if if(var6 != null)
if if(var2 != null)
if if(var8 == null)
if if(var5 == null)
if if(var6 != null)
if if(var4 > -1 && var7 instanceof AssetStoreTypeHandler var10)
if if(var15 == null || var16 == null)
if if(var9 == null)
if if(var9 == null)
if if(var28 == null)
if if(var4 == null)
if if(var5 != null)
if if(var9.firstCreatedProperty != null)
if if(var11 == null)
if if(var4 == null)
if if(var5 != null)
if if(var9 == null)
if if(var4 != null)
if if(var7 != null)
if if(var5 != null)
if if(var8 != null)
if if(var3 == null)
if if(var9 != null)
if if(var4 == null)
if if(var5 != null)
if if(var5 == null)
if if(var6 != null)
if if(var10 == null)
if if(var11 != null)
if if(var4 == null)
if if(var8 != null)
if if(var7 == null)
if if(var8 != null)
if if(var11 != null)
if if(var4 != null)
if if(var8 == null)
if if(var9.path.length > 0)
if if(var14.rebuildCaches != null)
if if(var14.rebuildCaches.blockTextures)
if if(var14.rebuildCaches.modelTextures)
if if(var14.rebuildCaches.models)
if if(var14.rebuildCaches.mapGeometry)
if if(var14.rebuildCaches.itemIcons)
if if(var4 == null)
if if(var2 != null)
private void initializeAssetEditorvoid initializeAssetEditor(boolean var1)
private void initializeClientvoid initializeClient(@Nonnull EditorClient var1)
boolean isValidPathboolean isValidPath(@Nonnull DataSource var1, @Nonnull AssetPath var2)
private void onAssetMonitorvoid onAssetMonitor(@Nonnull AssetMonitorEvent<Void> var1)
private void onI18nMessagesUpdatedvoid onI18nMessagesUpdated(@Nonnull MessagesUpdated var1)
private void onRegisterAssetPackvoid onRegisterAssetPack(@Nonnull AssetPackRegisterEvent var1)
private void onRegisterAssetStorevoid onRegisterAssetStore(@Nonnull RegisterAssetStoreEvent var1)
private void onUnregisterAssetPackvoid onUnregisterAssetPack(@Nonnull AssetPackUnregisterEvent var1)
private void onUnregisterAssetStorevoid onUnregisterAssetStore(@Nonnull RemoveAssetStoreEvent var1)
private void sendModifiedAssetsUpdateToConnectedUsersvoid sendModifiedAssetsUpdateToConnectedUsers()
private void sendPacketToAllEditorUsersvoid sendPacketToAllEditorUsers(@Nonnull ToClientPacket var1)
private void sendPacketToAllEditorUsersExceptvoid sendPacketToAllEditorUsersExcept(@Nonnull ToClientPacket var1, EditorClient var2)
private void sendPingPacketsvoid sendPingPackets()
abstract super super(var1)
switch switch(this.initState)
switch switch(this.initState)
switch switch(var9.type)
private void tryReinitializeAssetEditorvoid tryReinitializeAssetEditor()
private void updateAssetForConnectedClientsvoid updateAssetForConnectedClients(@Nonnull AssetPath var1)
private void updateAssetForConnectedClientsvoid updateAssetForConnectedClients(@Nonnull AssetPath var1, @Nullable EditorClient var2)
private void updateAssetForConnectedClientsvoid updateAssetForConnectedClients(@Nonnull AssetPath var1, byte[] var2, @Nullable EditorClient var3)
private void updateJsonAssetForConnectedClientsvoid updateJsonAssetForConnectedClients(@Nonnull AssetPath var1, @Nonnull JsonUpdateCommand[] var2)
private void updateJsonAssetForConnectedClientsvoid updateJsonAssetForConnectedClients(@Nonnull AssetPath var1, @Nonnull JsonUpdateCommand[] var2, @Nullable EditorClient var3)

Исходный код

Показать/скрыть
class="kw">package com.hypixel.hytale.builtin.asseteditor;

class="kw">import com.hypixel.hytale.assetstore.AssetMap;
class="kw">import com.hypixel.hytale.assetstore.AssetPack;
class="kw">import com.hypixel.hytale.assetstore.AssetRegistry;
class="kw">import com.hypixel.hytale.assetstore.AssetStore;
class="kw">import com.hypixel.hytale.assetstore.AssetUpdateQuery;
class="kw">import com.hypixel.hytale.assetstore.event.AssetMonitorEvent;
class="kw">import com.hypixel.hytale.assetstore.event.AssetStoreMonitorEvent;
class="kw">import com.hypixel.hytale.assetstore.event.RegisterAssetStoreEvent;
class="kw">import com.hypixel.hytale.assetstore.event.RemoveAssetStoreEvent;
class="kw">import com.hypixel.hytale.assetstore.map.JsonAssetWithMap;
class="kw">import com.hypixel.hytale.builtin.asseteditor.assettypehandler.AssetStoreTypeHandler;
class="kw">import com.hypixel.hytale.builtin.asseteditor.assettypehandler.AssetTypeHandler;
class="kw">import com.hypixel.hytale.builtin.asseteditor.assettypehandler.CommonAssetTypeHandler;
class="kw">import com.hypixel.hytale.builtin.asseteditor.assettypehandler.JsonTypeHandler;
class="kw">import com.hypixel.hytale.builtin.asseteditor.data.AssetUndoRedoInfo;
class="kw">import com.hypixel.hytale.builtin.asseteditor.data.ModifiedAsset;
class="kw">import com.hypixel.hytale.builtin.asseteditor.datasource.DataSource;
class="kw">import com.hypixel.hytale.builtin.asseteditor.datasource.StandardDataSource;
class="kw">import com.hypixel.hytale.builtin.asseteditor.event.AssetEditorAssetCreatedEvent;
class="kw">import com.hypixel.hytale.builtin.asseteditor.event.AssetEditorClientDisconnectEvent;
class="kw">import com.hypixel.hytale.builtin.asseteditor.event.AssetEditorSelectAssetEvent;
class="kw">import com.hypixel.hytale.builtin.asseteditor.util.AssetPathUtil;
class="kw">import com.hypixel.hytale.builtin.asseteditor.util.AssetStoreUtil;
class="kw">import com.hypixel.hytale.builtin.asseteditor.util.BsonTransformationUtil;
class="kw">import com.hypixel.hytale.codec.EmptyExtraInfo;
class="kw">import com.hypixel.hytale.codec.schema.SchemaContext;
class="kw">import com.hypixel.hytale.codec.schema.config.Schema;
class="kw">import com.hypixel.hytale.common.plugin.AuthorInfo;
class="kw">import com.hypixel.hytale.common.plugin.PluginIdentifier;
class="kw">import com.hypixel.hytale.common.plugin.PluginManifest;
class="kw">import com.hypixel.hytale.common.semver.Semver;
class="kw">import com.hypixel.hytale.common.semver.SemverRange;
class="kw">import com.hypixel.hytale.common.util.ArrayUtil;
class="kw">import com.hypixel.hytale.common.util.FormatUtil;
class="kw">import com.hypixel.hytale.common.util.PathUtil;
class="kw">import com.hypixel.hytale.component.ComponentAccessor;
class="kw">import com.hypixel.hytale.component.Ref;
class="kw">import com.hypixel.hytale.event.EventRegistry;
class="kw">import com.hypixel.hytale.event.IEventDispatcher;
class="kw">import com.hypixel.hytale.logger.HytaleLogger;
class="kw">import com.hypixel.hytale.protocol.ToClientPacket;
class="kw">import com.hypixel.hytale.protocol.packets.asseteditor.AssetEditorAsset;
class="kw">import com.hypixel.hytale.protocol.packets.asseteditor.AssetEditorAssetListUpdate;
class="kw">import com.hypixel.hytale.protocol.packets.asseteditor.AssetEditorAssetPackSetup;
class="kw">import com.hypixel.hytale.protocol.packets.asseteditor.AssetEditorAssetUpdated;
class="kw">import com.hypixel.hytale.protocol.packets.asseteditor.AssetEditorCapabilities;
class="kw">import com.hypixel.hytale.protocol.packets.asseteditor.AssetEditorDeleteAssetPack;
class="kw">import com.hypixel.hytale.protocol.packets.asseteditor.AssetEditorEditorType;
class="kw">import com.hypixel.hytale.protocol.packets.asseteditor.AssetEditorExportAssetFinalize;
class="kw">import com.hypixel.hytale.protocol.packets.asseteditor.AssetEditorExportAssetInitialize;
class="kw">import com.hypixel.hytale.protocol.packets.asseteditor.AssetEditorExportAssetPart;
class="kw">import com.hypixel.hytale.protocol.packets.asseteditor.AssetEditorExportComplete;
class="kw">import com.hypixel.hytale.protocol.packets.asseteditor.AssetEditorExportDeleteAssets;
class="kw">import com.hypixel.hytale.protocol.packets.asseteditor.AssetEditorFetchAssetReply;
class="kw">import com.hypixel.hytale.protocol.packets.asseteditor.AssetEditorFetchJsonAssetWithParentsReply;
class="kw">import com.hypixel.hytale.protocol.packets.asseteditor.AssetEditorFileEntry;
class="kw">import com.hypixel.hytale.protocol.packets.asseteditor.AssetEditorJsonAssetUpdated;
class="kw">import com.hypixel.hytale.protocol.packets.asseteditor.AssetEditorLastModifiedAssets;
class="kw">import com.hypixel.hytale.protocol.packets.asseteditor.AssetEditorModsDirectories;
class="kw">import com.hypixel.hytale.protocol.packets.asseteditor.AssetEditorPopupNotificationType;
class="kw">import com.hypixel.hytale.protocol.packets.asseteditor.AssetEditorRebuildCaches;
class="kw">import com.hypixel.hytale.protocol.packets.asseteditor.AssetEditorRequestAssetInheritanceReply;
class="kw">import com.hypixel.hytale.protocol.packets.asseteditor.AssetEditorRequestChildrenListReply;
class="kw">import com.hypixel.hytale.protocol.packets.asseteditor.AssetEditorSetupSchemas;
class="kw">import com.hypixel.hytale.protocol.packets.asseteditor.AssetEditorUndoRedoReply;
class="kw">import com.hypixel.hytale.protocol.packets.asseteditor.AssetEditorUpdateAssetPack;
class="kw">import com.hypixel.hytale.protocol.packets.asseteditor.AssetInfo;
class="kw">import com.hypixel.hytale.protocol.packets.asseteditor.AssetInheritanceTreeNode;
class="kw">import com.hypixel.hytale.protocol.packets.asseteditor.AssetPackManifest;
class="kw">import com.hypixel.hytale.protocol.packets.asseteditor.JsonUpdateCommand;
class="kw">import com.hypixel.hytale.protocol.packets.asseteditor.JsonUpdateType;
class="kw">import com.hypixel.hytale.protocol.packets.asseteditor.SchemaFile;
class="kw">import com.hypixel.hytale.protocol.packets.asseteditor.TimestampedAssetReference;
class="kw">import com.hypixel.hytale.protocol.packets.assets.UpdateTranslations;
class="kw">import com.hypixel.hytale.server.core.HytaleServer;
class="kw">import com.hypixel.hytale.server.core.HytaleServerConfig;
class="kw">import com.hypixel.hytale.server.core.Message;
class="kw">import com.hypixel.hytale.server.core.Options;
class="kw">import com.hypixel.hytale.server.core.asset.AssetModule;
class="kw">import com.hypixel.hytale.server.core.asset.AssetPackRegisterEvent;
class="kw">import com.hypixel.hytale.server.core.asset.AssetPackUnregisterEvent;
class="kw">import com.hypixel.hytale.server.core.asset.common.events.CommonAssetMonitorEvent;
class="kw">import com.hypixel.hytale.server.core.config.ModConfig;
class="kw">import com.hypixel.hytale.server.core.io.PacketHandler;
class="kw">import com.hypixel.hytale.server.core.io.ServerManager;
class="kw">import com.hypixel.hytale.server.core.io.handlers.InitialPacketHandler;
class="kw">import com.hypixel.hytale.server.core.modules.i18n.I18nModule;
class="kw">import com.hypixel.hytale.server.core.modules.i18n.event.MessagesUpdated;
class="kw">import com.hypixel.hytale.server.core.permissions.HytalePermissions;
class="kw">import com.hypixel.hytale.server.core.plugin.JavaPlugin;
class="kw">import com.hypixel.hytale.server.core.plugin.JavaPluginInit;
class="kw">import com.hypixel.hytale.server.core.plugin.PluginManager;
class="kw">import com.hypixel.hytale.server.core.plugin.PluginState;
class="kw">import com.hypixel.hytale.server.core.schema.SchemaGenerator;
class="kw">import com.hypixel.hytale.server.core.universe.PlayerRef;
class="kw">import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
class="kw">import com.hypixel.hytale.server.core.util.BsonUtil;
class="kw">import com.hypixel.hytale.server.core.util.io.FileUtil;
class="kw">import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
class="kw">import it.unimi.dsi.fastutil.objects.ObjectArrayList;
class="kw">import java.io.IOException;
class="kw">import java.nio.charset.StandardCharsets;
class="kw">import java.nio.file.Files;
class="kw">import java.nio.file.Path;
class="kw">import java.time.Instant;
class="kw">import java.util.Collection;
class="kw">import java.util.Collections;
class="kw">import java.util.HashSet;
class="kw">import java.util.List;
class="kw">import java.util.Map;
class="kw">import java.util.Set;
class="kw">import java.util.UUID;
class="kw">import java.util.Map.Entry;
class="kw">import java.util.concurrent.ConcurrentHashMap;
class="kw">import java.util.concurrent.ForkJoinPool;
class="kw">import java.util.concurrent.ScheduledFuture;
class="kw">import java.util.concurrent.TimeUnit;
class="kw">import java.util.concurrent.locks.StampedLock;
class="kw">import java.util.logging.Level;
class="kw">import javax.annotation.Nonnull;
class="kw">import javax.annotation.Nullable;
class="kw">import org.bson.BsonDocument;
class="kw">import org.bson.BsonValue;

class="kw">public class AssetEditorPlugin class="kw">extends JavaPlugin {
   class="kw">private class="kw">static AssetEditorPlugin instance;
   @Nonnull
   class="kw">private class="kw">final StampedLock globalEditLock = new StampedLock();
   @Nonnull
   class="kw">private class="kw">final Map<UUID, Set<EditorClient>> uuidToEditorClients = new ConcurrentHashMap<>();
   @Nonnull
   class="kw">private class="kw">final Map<EditorClient, AssetPath> clientOpenAssetPathMapping = new ConcurrentHashMap<>();
   @Nonnull
   class="kw">private class="kw">final Set<EditorClient> clientsSubscribedToModifiedAssetsChanges = ConcurrentHashMap.newKeySet();
   @Nonnull
   class="kw">private Map<String, Schema> schemas = new Object2ObjectOpenHashMap();
   class="kw">private AssetEditorSetupSchemas setupSchemasPacket;
   @Nonnull
   class="kw">private class="kw">final StampedLock initLock = new StampedLock();
   @Nonnull
   class="kw">private class="kw">final Set<EditorClient> initQueue = new HashSet<>();
   @Nonnull
   class="kw">private AssetEditorPlugin.InitState initState = AssetEditorPlugin.InitState.NOT_INITIALIZED;
   @Nullable
   class="kw">private ScheduledFuture<?> scheduledReinitFuture;
   @Nonnull
   class="kw">private class="kw">final Map<String, DataSource> assetPackDataSources = new ConcurrentHashMap<>();
   @Nonnull
   class="kw">private class="kw">final AssetTypeRegistry assetTypeRegistry = new AssetTypeRegistry();
   @Nonnull
   class="kw">private class="kw">final UndoRedoManager undoRedoManager = new UndoRedoManager();
   @Nonnull
   class="kw">private class="kw">final AssetInheritanceResolver inheritanceResolver = new AssetInheritanceResolver(
      () -> AssetModule.get().getAssetPacks(), this::getDataSourceForPack
   );
   @Nullable
   class="kw">private ScheduledFuture<?> pingClientsTask;

   class="kw">public class="kw">static AssetEditorPlugin get() {
      class="kw">return instance;
   }

   class="kw">public AssetEditorPlugin(@Nonnull JavaPluginInit var1) {
      super(var1);
   }

   @Nullable
   DataSource registerDataSourceForPack(@Nonnull AssetPack var1) {
      PluginManifest var2 = var1.getManifest();
      if (var2 == null) {
         this.getLogger().at(Level.SEVERE).log("Could not load asset pack manifest for %s", var1.getName());
         class="kw">return null;
      } else {
         StandardDataSource var3 = new StandardDataSource(var1.getName(), var1.getRoot(), var1.isImmutable(), var2);
         this.assetPackDataSources.put(var1.getName(), var3);
         class="kw">return var3;
      }
   }

   @Override
   class="kw">protected void setup() {
      instance = this;
      EventRegistry var1 = this.getEventRegistry();

      for (AssetPack var3 : AssetModule.get().getAssetPacks()) {
         this.registerDataSourceForPack(var3);
      }

      ServerManager.get().registerSubPacketHandlers(AssetEditorGamePacketHandler::new);
      InitialPacketHandler.EDITOR_PACKET_HANDLER_SUPPLIER = AssetEditorPacketHandler::new;

      for (AssetStore var5 : AssetRegistry.getStoreMap().values()) {
         if (var5.getPath() != null && !var5.getPath().startsWith("../")) {
            this.assetTypeRegistry.registerAssetType(new AssetStoreTypeHandler(var5));
         }
      }

      this.assetTypeRegistry.registerAssetType(new CommonAssetTypeHandler("Texture", "Texture.png", ".png", AssetEditorEditorType.Texture));
      this.assetTypeRegistry.registerAssetType(new CommonAssetTypeHandler("Model", "Model.png", ".blockymodel", AssetEditorEditorType.JsonSource));
      this.assetTypeRegistry.registerAssetType(new CommonAssetTypeHandler("Animation", "Animation.png", ".blockyanim", AssetEditorEditorType.JsonSource));
      this.assetTypeRegistry.registerAssetType(new CommonAssetTypeHandler("Sound", null, ".ogg", AssetEditorEditorType.None));
      this.assetTypeRegistry.registerAssetType(new CommonAssetTypeHandler("UI", null, ".ui", AssetEditorEditorType.Text));
      this.assetTypeRegistry.registerAssetType(new CommonAssetTypeHandler("Language", null, ".lang", AssetEditorEditorType.Text));
      var1.register(RegisterAssetStoreEvent.class, this::onRegisterAssetStore);
      var1.register(RemoveAssetStoreEvent.class, this::onUnregisterAssetStore);
      var1.register(AssetPackRegisterEvent.class, this::onRegisterAssetPack);
      var1.register(AssetPackUnregisterEvent.class, this::onUnregisterAssetPack);
      var1.register(AssetStoreMonitorEvent.class, this::onAssetMonitor);
      var1.register(CommonAssetMonitorEvent.class, this::onAssetMonitor);
      var1.register(MessagesUpdated.class, this::onI18nMessagesUpdated);
      AssetSpecificFunctionality.setup();
   }

   @Override
   class="kw">protected void start() {
      for (DataSource var2 : this.assetPackDataSources.values()) {
         var2.start();
      }

      this.pingClientsTask = HytaleServer.SCHEDULED_EXECUTOR.scheduleAtFixedRate(this::sendPingPackets, 1L, 1L, PacketHandler.PingInfo.PING_FREQUENCY_UNIT);
   }

   @Override
   class="kw">protected void shutdown() {
      InitialPacketHandler.EDITOR_PACKET_HANDLER_SUPPLIER = null;
      Message var1 = HytaleServer.get().isShuttingDown()
         ? Message.translation("server.general.disconnect.stoppingServer")
         : Message.translation("server.general.disconnect.assetEditorDisabled");

      for (Set var3 : this.uuidToEditorClients.values()) {
         for (EditorClient var5 : var3) {
            var5.getPacketHandler().disconnect(var1);
         }
      }

      if (this.pingClientsTask != null) {
         this.pingClientsTask.cancel(false);
      } else {
         this.getLogger().at(Level.WARNING).log("Failed to cancel ping clients task as it was null");
      }

      for (DataSource var7 : this.assetPackDataSources.values()) {
         var7.shutdown();
      }
   }

   @Nullable
   class="kw">public DataSource getDataSourceForPath(@Nonnull AssetPath var1) {
      class="kw">return this.getDataSourceForPack(var1.packId());
   }

   @Nullable
   class="kw">public DataSource getDataSourceForPack(@Nonnull String var1) {
      class="kw">return this.assetPackDataSources.get(var1);
   }

   @Nonnull
   class="kw">public Collection<DataSource> getDataSources() {
      class="kw">return this.assetPackDataSources.values();
   }

   @Nonnull
   class="kw">public AssetTypeRegistry getAssetTypeRegistry() {
      class="kw">return this.assetTypeRegistry;
   }

   @Nullable
   class="kw">public Schema getSchema(@Nonnull String var1) {
      class="kw">return this.schemas.get(var1);
   }

   @Nonnull
   class="kw">public Map<EditorClient, AssetPath> getClientOpenAssetPathMapping() {
      class="kw">return this.clientOpenAssetPathMapping;
   }

   @Nullable
   class="kw">public Set<EditorClient> getEditorClients(@Nonnull UUID var1) {
      class="kw">return this.uuidToEditorClients.get(var1);
   }

   class="kw">private void sendPingPackets() {
      for (Set var2 : this.uuidToEditorClients.values()) {
         for (EditorClient var4 : var2) {
            try {
               var4.getPacketHandler().sendPing();
            } catch (Exception var6) {
               ((HytaleLogger.Api)this.getLogger().at(Level.SEVERE).withCause(var6)).log("Failed to send ping to %s", var4);
               var4.getPacketHandler().disconnect(Message.translation("server.general.disconnect.pingException"));
            }
         }
      }
   }

   @Nonnull
   class="kw">private List<EditorClient> getClientsWithOpenAssetPath(@Nonnull AssetPath var1) {
      if (this.clientOpenAssetPathMapping.isEmpty()) {
         class="kw">return Collections.emptyList();
      }

      List var2 = new ObjectArrayList();

      for (Entry var4 : this.clientOpenAssetPathMapping.entrySet()) {
         if (var4.getValue().equals(var1)) {
            var2.add(var4.getKey());
         }
      }

      class="kw">return var2;
   }

   @Nullable
   class="kw">public AssetPath getOpenAssetPath(@Nonnull EditorClient var1) {
      class="kw">return this.clientOpenAssetPathMapping.get(var1);
   }

   class="kw">private void onRegisterAssetPack(@Nonnull AssetPackRegisterEvent var1) {
      if (!this.assetPackDataSources.containsKey(var1.getAssetPack().getName())) {
         DataSource var2 = this.registerDataSourceForPack(var1.getAssetPack());
         if (var2 != null) {
            if (this.getState() == PluginState.ENABLED) {
               var2.start();
            }

            AssetTree var3 = var2.loadAssetTree(this.assetTypeRegistry.getRegisteredAssetTypeHandlers().values());
            long var4 = this.globalEditLock.writeLock();

            try {
               var2.getAssetTree().replaceAssetTree(var3);
            } class="kw">finally {
               this.globalEditLock.unlockWrite(var4);
            }

            this.broadcastPackAddedOrUpdated(var1.getAssetPack().getName(), var2.getManifest());

            for (Set var7 : this.uuidToEditorClients.values()) {
               for (EditorClient var9 : var7) {
                  var2.getAssetTree().sendPackets(var9);
               }
            }
         }
      }
   }

   class="kw">private void onUnregisterAssetPack(@Nonnull AssetPackUnregisterEvent var1) {
      if (this.assetPackDataSources.containsKey(var1.getAssetPack().getName())) {
         DataSource var2 = this.assetPackDataSources.remove(var1.getAssetPack().getName());
         var2.shutdown();

         for (Set var4 : this.uuidToEditorClients.values()) {
            for (EditorClient var6 : var4) {
               var6.getPacketHandler().write(new AssetEditorDeleteAssetPack(var1.getAssetPack().getName()));
            }
         }
      }
   }

   class="kw">private void onI18nMessagesUpdated(@Nonnull MessagesUpdated var1) {
      if (!this.clientOpenAssetPathMapping.isEmpty()) {
         I18nModule var2 = I18nModule.get();
         Map var3 = var1.getChangedMessages();
         Map var4 = var1.getRemovedMessages();
         Map var5 = new Object2ObjectOpenHashMap();

         for (EditorClient var7 : this.clientOpenAssetPathMapping.keySet()) {
            String var8 = var7.getLanguage();
            UpdateTranslations[] var9 = var5.get(var8);
            if (var9 == null) {
               var9 = var2.getUpdatePacketsForChanges(var8, var3, var4);
               var5.put(var8, var9);
            }

            if (var9.length != 0) {
               var7.getPacketHandler().write(var9);
            }
         }
      }
   }

   class="kw">private void onRegisterAssetStore(@Nonnull RegisterAssetStoreEvent var1) {
      AssetStore var2 = (AssetStore<?, ? class="kw">extends JsonAssetWithMap<?, ? class="kw">extends AssetMap<?, ?>>, ? class="kw">extends AssetMap<?, ? class="kw">extends JsonAssetWithMap<?, ?>>>)var1.getAssetStore();
      if (var2.getPath() != null && !var2.getPath().startsWith("../")) {
         this.assetTypeRegistry.registerAssetType(new AssetStoreTypeHandler(var2));
         long var3 = this.initLock.readLock();

         try {
            if (this.initState != AssetEditorPlugin.InitState.NOT_INITIALIZED) {
               if (this.scheduledReinitFuture != null) {
                  this.scheduledReinitFuture.cancel(false);
               }

               this.scheduledReinitFuture = HytaleServer.SCHEDULED_EXECUTOR.schedule(this::tryReinitializeAssetEditor, 1L, TimeUnit.SECONDS);
            }
         } class="kw">finally {
            this.initLock.unlockRead(var3);
         }
      }
   }

   class="kw">private void onUnregisterAssetStore(@Nonnull RemoveAssetStoreEvent var1) {
      AssetStore var2 = (AssetStore<?, ? class="kw">extends JsonAssetWithMap<?, ? class="kw">extends AssetMap<?, ?>>, ? class="kw">extends AssetMap<?, ? class="kw">extends JsonAssetWithMap<?, ?>>>)var1.getAssetStore();
      if (var2.getPath() != null && !var2.getPath().startsWith("../")) {
         this.assetTypeRegistry.unregisterAssetType(new AssetStoreTypeHandler(var2));
         long var3 = this.initLock.readLock();

         try {
            if (this.initState != AssetEditorPlugin.InitState.NOT_INITIALIZED) {
               if (this.scheduledReinitFuture != null) {
                  this.scheduledReinitFuture.cancel(false);
               }

               this.scheduledReinitFuture = HytaleServer.SCHEDULED_EXECUTOR.schedule(this::tryReinitializeAssetEditor, 1L, TimeUnit.SECONDS);
            }
         } class="kw">finally {
            this.initLock.unlockRead(var3);
         }
      }
   }

   class="kw">private void tryReinitializeAssetEditor() {
      long var1 = this.initLock.writeLock();

      try {
         class="kw">switch (this.initState) {
            case NOT_INITIALIZED:
            class="kw">default:
               break;
            case INITIALIZING:
               this.scheduledReinitFuture = HytaleServer.SCHEDULED_EXECUTOR.schedule(this::tryReinitializeAssetEditor, 1L, TimeUnit.SECONDS);
               break;
            case INITIALIZED:
               this.initState = AssetEditorPlugin.InitState.INITIALIZING;
               this.scheduledReinitFuture = null;
               this.getLogger().at(Level.INFO).log("Starting asset editor re-initialization");
               ForkJoinPool.commonPool().execute(() -> this.initializeAssetEditor(true));
         }
      } class="kw">finally {
         this.initLock.unlockWrite(var1);
      }
   }

   class="kw">private void onAssetMonitor(@Nonnull AssetMonitorEvent<Void> var1) {
      AssetEditorAssetListUpdate var2 = new AssetEditorAssetListUpdate();
      var2.pack = var1.getAssetPack();
      ObjectArrayList var3 = new ObjectArrayList();
      DataSource var4 = this.getDataSourceForPack(var1.getAssetPack());
      if (var4 != null) {
         if (!var1.getRemovedFilesAndDirectories().isEmpty()) {
            ObjectArrayList var5 = new ObjectArrayList();

            for (Path var7 : var1.getRemovedFilesAndDirectories()) {
               Path var8 = PathUtil.relativizePretty(var4.getRootPath(), var7);
               AssetEditorFileEntry var9 = var4.getAssetTree().removeAsset(var8);
               if (var9 != null) {
                  var5.add(var9);
               }
            }

            var2.deletions = (AssetEditorFileEntry[])var5.toArray(AssetEditorFileEntry[]::new);
         }

         if (!var1.getRemovedFilesToUnload().isEmpty()) {
            var1.getRemovedFilesToUnload()
               .removeIf(
                  var3x -> {
                     Path var4 = PathUtil.relativizePretty(var4.getRootPath(), var3x);
                     if (!var4.shouldReloadAssetFromDisk(var4)) {
                        this.getLogger()
                           .at(Level.INFO)
                           .log("Skipping reloading %s from file monitor event because there is changes made via the asset editor", var3x);
                        class="kw">return true;
                     }

                     long var5 = this.globalEditLock.writeLock();

                     try {
                        this.undoRedoManager.clearUndoRedoStack(new AssetPath(var1.getAssetPack(), var4));
                     } class="kw">finally {
                        this.globalEditLock.unlockWrite(var5);
                     }

                     class="kw">return false;
                  }
               );
         }

         if (!var1.getCreatedOrModifiedDirectories().isEmpty()) {
            for (Path var11 : var1.getCreatedOrModifiedDirectories()) {
               Path var12 = PathUtil.relativizePretty(var4.getRootPath(), var11);
               AssetEditorFileEntry var13 = var4.getAssetTree().ensureAsset(var12, true);
               if (var13 != null) {
                  var3.add(var13);
               }
            }
         }

         if (!var1.getCreatedOrModifiedFilesToLoad().isEmpty()) {
            var1.getCreatedOrModifiedFilesToLoad()
               .removeIf(
                  var4x -> {
                     Path var5 = PathUtil.relativizePretty(var4.getRootPath(), var4x);
                     AssetEditorFileEntry var6 = var4.getAssetTree().ensureAsset(var5, false);
                     if (var6 != null) {
                        var3.add(var6);
                        class="kw">return false;
                     }

                     if (!var4.shouldReloadAssetFromDisk(var5)) {
                        this.getLogger()
                           .at(Level.INFO)
                           .log("Skipping reloading %s from file monitor event because there is changes made via the asset editor", var4x);
                        class="kw">return true;
                     }

                     AssetPath var7 = new AssetPath(var1.getAssetPack(), var5);
                     long var8 = this.globalEditLock.writeLock();

                     try {
                        this.undoRedoManager.clearUndoRedoStack(var7);
                     } class="kw">finally {
                        this.globalEditLock.unlockWrite(var8);
                     }

                     List var10 = this.getClientsWithOpenAssetPath(var7);
                     if (!var10.isEmpty()) {
                        AssetEditorAssetUpdated var11 = new AssetEditorAssetUpdated(var7.toPacket(), var4.getAssetBytes(var5));

                        for (EditorClient var13 : var10) {
                           var13.getPacketHandler().write(var11);
                        }
                     }

                     class="kw">return false;
                  }
               );
            if (!var3.isEmpty()) {
               var2.additions = (AssetEditorFileEntry[])var3.toArray(AssetEditorFileEntry[]::new);
            }
         }

         if (!var3.isEmpty()) {
            var2.additions = (AssetEditorFileEntry[])var3.toArray(AssetEditorFileEntry[]::new);
         }

         if (var2.deletions != null || var2.additions != null) {
            this.sendPacketToAllEditorUsers(var2);
         }
      }
   }

   class="kw">public void handleInitializeEditor(@Nonnull Ref<EntityStore> var1, @Nonnull ComponentAccessor<EntityStore> var2) {
      PlayerRef var3 = var2.getComponent(var1, PlayerRef.getComponentType());
      assert var3 != null;
      String var4 = var3.getUsername();
      this.getLogger().at(Level.INFO).log("%s is attempting to initialize asset editor", var4);
      long var5 = this.initLock.writeLock();

      try {
         if (this.initState == AssetEditorPlugin.InitState.NOT_INITIALIZED) {
            this.initState = AssetEditorPlugin.InitState.INITIALIZING;
            ForkJoinPool.commonPool().execute(() -> this.initializeAssetEditor(false));
            this.getLogger().at(Level.INFO).log("%s starting asset editor initialization", var4);
         }
      } class="kw">finally {
         this.initLock.unlockWrite(var5);
      }
   }

   class="kw">public void handleInitializeClient(@Nonnull EditorClient var1) {
      this.getLogger().at(Level.INFO).log("Initializing %s", var1.getUsername());
      this.uuidToEditorClients.computeIfAbsent(var1.getUuid(), var0 -> ConcurrentHashMap.newKeySet()).add(var1);
      this.clientOpenAssetPathMapping.put(var1, new AssetPath("", Path.of("")));
      I18nModule.get().sendTranslations(var1.getPacketHandler(), var1.getLanguage());
      long var2 = this.initLock.writeLock();

      try {
         class="kw">switch (this.initState) {
            case NOT_INITIALIZED:
               this.initState = AssetEditorPlugin.InitState.INITIALIZING;
               this.initQueue.add(var1);
               ForkJoinPool.commonPool().execute(() -> this.initializeAssetEditor(false));
               this.getLogger().at(Level.INFO).log("%s starting asset editor initialization", var1.getUsername());
               class="kw">return;
            case INITIALIZING:
               this.getLogger().at(Level.INFO).log("%s waiting for asset editor initialization to complete", var1.getUsername());
               this.initQueue.add(var1);
               class="kw">return;
            case INITIALIZED:
         }
      } class="kw">finally {
         this.initLock.unlockWrite(var2);
      }

      this.initializeClient(var1);
   }

   class="kw">private void initializeAssetEditor(boolean var1) {
      long var2 = System.nanoTime();
      Map var4 = SchemaGenerator.generateAssetSchemas();
      var4.remove("NPCRole.json");
      var4.remove("other.json");
      AssetEditorSetupSchemas var5 = new AssetEditorSetupSchemas(new SchemaFile[var4.size()]);
      int var6 = 0;

      for (Schema var8 : var4.values()) {
         String var9 = Schema.CODEC.encode(var8, EmptyExtraInfo.EMPTY).asDocument().toJson();
         var5.schemas[var6++] = new SchemaFile(var9);
      }

      for (DataSource var29 : this.assetPackDataSources.values()) {
         AssetTree var30 = var29.loadAssetTree(this.assetTypeRegistry.getRegisteredAssetTypeHandlers().values());
         long var10 = this.globalEditLock.writeLock();

         try {
            var29.getAssetTree().replaceAssetTree(var30);
            this.assetTypeRegistry.setupPacket();
            if (var1) {
               var29.updateRuntimeAssets();
            }
         } class="kw">finally {
            this.globalEditLock.unlockWrite(var10);
         }
      }

      long var28 = this.globalEditLock.writeLock();

      try {
         this.schemas = var4;
         this.setupSchemasPacket = var5;
         this.assetTypeRegistry.setupPacket();
      } class="kw">finally {
         this.globalEditLock.unlockWrite(var28);
      }

      long var31 = this.initLock.writeLock();

      try {
         this.initState = AssetEditorPlugin.InitState.INITIALIZED;
         this.getLogger().at(Level.INFO).log("Asset editor initialization complete! Took: %s", FormatUtil.nanosToString(System.nanoTime() - var2));

         for (EditorClient var12 : this.clientOpenAssetPathMapping.keySet()) {
            this.initializeClient(var12);
         }

         this.initQueue.clear();
      } class="kw">finally {
         this.initLock.unlockWrite(var31);
      }
   }

   class="kw">private void initializeClient(@Nonnull EditorClient var1) {
      DataSource var2 = this.assetPackDataSources.get("Hytale:Hytale");
      boolean var3 = false;
      boolean var4 = var1.hasPermission(HytalePermissions.ASSET_EDITOR);
      boolean var5 = var1.hasPermission(HytalePermissions.ASSET_EDITOR_PACKS_EDIT);
      boolean var6 = var1.hasPermission(HytalePermissions.ASSET_EDITOR_PACKS_CREATE);
      boolean var7 = var1.hasPermission(HytalePermissions.ASSET_EDITOR_PACKS_DELETE);
      var1.getPacketHandler().write(new AssetEditorCapabilities(false, var4, var6, var5, var7));
      var1.getPacketHandler().write(this.setupSchemasPacket);
      this.assetTypeRegistry.sendPacket(var1);
      AssetEditorAssetPackSetup var8 = new AssetEditorAssetPackSetup();
      var8.packs = new Object2ObjectOpenHashMap();

      for (Entry var10 : this.assetPackDataSources.entrySet()) {
         DataSource var11 = var10.getValue();
         PluginManifest var12 = var11.getManifest();
         var8.packs.put(var10.getKey(), toManifestPacket(var12));
      }

      var1.getPacketHandler().write(var8);
      if (var6) {
         List var13 = this.getModsDirectories();
         String[] var15 = new String[var13.size()];

         for (int var17 = 0; var17 < var13.size(); var17++) {
            var15[var17] = var13.get(var17).toString();
         }

         var1.getPacketHandler().write(new AssetEditorModsDirectories(var15));
      }

      for (DataSource var16 : this.assetPackDataSources.values()) {
         var16.getAssetTree().sendPackets(var1);
      }

      this.getLogger().at(Level.INFO).log("Done Initializing %s", var1.getUsername());
   }

   class="kw">public void handleEditorClientDisconnected(@Nonnull EditorClient var1, @Nonnull PacketHandler.DisconnectReason var2) {
      IEventDispatcher var3 = HytaleServer.get().getEventBus().dispatchFor(AssetEditorClientDisconnectEvent.class);
      if (var3.hasListener()) {
         var3.dispatch(new AssetEditorClientDisconnectEvent(var1, var2));
      }

      this.uuidToEditorClients.compute(var1.getUuid(), (var1x, var2x) -> {
         if (var2x == null) {
            class="kw">return null;
         }

         var2x.remove(var1);
         class="kw">return var2x.isEmpty() ? null : var2x;
      });
      this.clientOpenAssetPathMapping.remove(var1);
      this.clientsSubscribedToModifiedAssetsChanges.remove(var1);
   }

   class="kw">public void handleDeleteAssetPack(@Nonnull EditorClient var1, @Nonnull String var2) {
      if (var2.equalsIgnoreCase("Hytale:Hytale")) {
         var1.sendPopupNotification(AssetEditorPopupNotificationType.Error, Messages.UNKNOWN_ASSET_PACK);
      } else {
         DataSource var3 = this.getDataSourceForPack(var2);
         if (var3 == null) {
            var1.sendPopupNotification(AssetEditorPopupNotificationType.Error, Messages.UNKNOWN_ASSET_PACK);
         } else {
            AssetModule.get().unregisterPack(var2);

            Path var4;
            try {
               var4 = var3.getRootPath().toRealPath();
            } catch (IOException var11) {
               throw new RuntimeException("Failed to resolve the real path for asset pack directory while deleting asset pack '" + var2 + "'.", var11);
            }

            boolean var5 = false;

            try {
               if (var4.startsWith(PluginManager.MODS_PATH.toRealPath())) {
                  var5 = true;
               }
            } catch (IOException var10) {
            }

            if (!var5) {
               for (Path var7 : Options.getOptionSet().valuesOf(Options.MODS_DIRECTORIES)) {
                  try {
                     if (var4.startsWith(var7.toRealPath())) {
                        var5 = true;
                        break;
                     }
                  } catch (IOException var12) {
                  }
               }
            }

            if (!var5) {
               var1.sendPopupNotification(AssetEditorPopupNotificationType.Error, Messages.PACK_OUTSIDE_DIRECTORY);
            } else {
               try {
                  FileUtil.deleteDirectory(var4);
                  var1.sendPopupNotification(AssetEditorPopupNotificationType.Success, Messages.PACK_DELETED);
               } catch (Exception var9) {
                  ((HytaleLogger.Api)this.getLogger().at(Level.SEVERE).withCause(var9)).log("Failed to delete asset pack %s from disk", var2);
                  var1.sendPopupNotification(AssetEditorPopupNotificationType.Error, Messages.PACK_DELETION_FAILED);
               }
            }
         }
      }
   }

   class="kw">public void handleUpdateAssetPack(@Nonnull EditorClient var1, @Nonnull String var2, @Nonnull AssetPackManifest var3) {
      if (var2.equals("Hytale:Hytale")) {
         var1.sendPopupNotification(AssetEditorPopupNotificationType.Error, Messages.UNKNOWN_ASSET_PACK);
      } else {
         DataSource var4 = this.getDataSourceForPack(var2);
         if (var4 == null) {
            var1.sendPopupNotification(AssetEditorPopupNotificationType.Error, Messages.UNKNOWN_ASSET_PACK);
         } else if (var4.isImmutable()) {
            var1.sendPopupNotification(AssetEditorPopupNotificationType.Error, Messages.ASSETS_READ_ONLY);
         } else {
            PluginManifest var5 = var4.getManifest();
            if (var5 == null) {
               var1.sendPopupNotification(AssetEditorPopupNotificationType.Error, Messages.MANIFEST_NOT_FOUND);
            } else {
               boolean var6 = false;
               if (var3.name != null && !var3.name.isEmpty() && !var5.getName().equals(var3.name)) {
                  var5.setName(var3.name);
                  var6 = true;
               }

               if (var3.group != null && !var3.group.isEmpty() && !var5.getGroup().equals(var3.group)) {
                  var5.setGroup(var3.group);
                  var6 = true;
               }

               if (var3.description != null) {
                  var5.setDescription(var3.description);
               }

               if (var3.website != null) {
                  var5.setWebsite(var3.website);
               }

               if (var3.version != null && !var3.version.isEmpty()) {
                  try {
                     var5.setVersion(Semver.fromString(var3.version));
                  } catch (IllegalArgumentException var16) {
                     ((HytaleLogger.Api)this.getLogger().at(Level.WARNING).withCause(var16)).log("Invalid version format: %s", var3.version);
                     var1.sendPopupNotification(AssetEditorPopupNotificationType.Error, Messages.INVALID_VERSION_FORMAT);
                     class="kw">return;
                  }
               }

               if (var3.authors != null) {
                  List var7 = new ObjectArrayList();

                  for (com.hypixel.hytale.protocol.packets.asseteditor.AuthorInfo var11 : var3.authors) {
                     AuthorInfo var12 = new AuthorInfo();
                     var12.setName(var11.name);
                     var12.setEmail(var11.email);
                     var12.setUrl(var11.url);
                     var7.add(var12);
                  }

                  var5.setAuthors(var7);
               }

               if (var3.serverVersion != null) {
                  if (var3.serverVersion.isBlank()) {
                     var5.setServerVersion(SemverRange.WILDCARD);
                  } else {
                     try {
                        var5.setServerVersion(SemverRange.fromString(var3.serverVersion));
                     } catch (IllegalArgumentException var15) {
                        ((HytaleLogger.Api)this.getLogger().at(Level.WARNING).withCause(var15))
                           .log("Rejected manifest update for pack %s: invalid ServerVersion range '%s'", var2, var3.serverVersion);
                        var1.sendPopupNotification(AssetEditorPopupNotificationType.Error, Messages.INVALID_SERVER_VERSION);
                        class="kw">return;
                     }
                  }
               }

               Path var17 = var4.getRootPath().resolve("manifest.json");

               try {
                  BsonUtil.writeSync(var17, PluginManifest.CODEC, var5, this.getLogger());
                  this.getLogger().at(Level.INFO).log("Saved manifest for pack %s", var2);
                  var1.sendPopupNotification(AssetEditorPopupNotificationType.Success, Messages.MANIFEST_SAVED);
               } catch (IOException var14) {
                  ((HytaleLogger.Api)this.getLogger().at(Level.SEVERE).withCause(var14)).log("Failed to save manifest for pack %s", var2);
                  var1.sendPopupNotification(AssetEditorPopupNotificationType.Error, Messages.MANIFEST_SAVE_FAILED);
               }

               this.broadcastPackAddedOrUpdated(var2, var5);
               if (var6) {
                  PluginIdentifier var18 = new PluginIdentifier(var5);
                  String var19 = var18.toString();
                  Path var20 = var4.getRootPath();
                  HytaleServerConfig var21 = HytaleServer.get().getConfig();
                  HytaleServerConfig.setBoot(var21, var18, true);
                  Map var22 = var21.getModConfig();
                  var22.remove(PluginIdentifier.fromString(var2));
                  var21.markChanged();
                  if (var21.consumeHasChanged()) {
                     HytaleServerConfig.save(var21).join();
                  }

                  AssetModule var13 = AssetModule.get();
                  var13.unregisterPack(var2);
                  if (!var13.registerPack(var19, var20, var5, AssetPack.PackSource.RUNTIME)) {
                     this.getLogger().at(Level.SEVERE).log("Failed to re-register asset pack '%s' after update", var19);
                  }
               }
            }
         }
      }
   }

   @Nonnull
   class="kw">private List<Path> getModsDirectories() {
      List var1 = new ObjectArrayList();
      var1.add(PluginManager.MODS_PATH.toAbsolutePath());

      for (Path var3 : Options.getOptionSet().valuesOf(Options.MODS_DIRECTORIES)) {
         var1.add(var3.toAbsolutePath());
      }

      class="kw">return var1;
   }

   class="kw">public void handleCreateAssetPack(@Nonnull EditorClient var1, @Nonnull AssetPackManifest var2, int var3, int var4) {
      if (var2.name == null || var2.name.isEmpty()) {
         var1.sendFailureReply(var3, Messages.PACK_NAME_REQUIRED);
      } else if (var2.group != null && !var2.group.isEmpty()) {
         PluginManifest var5 = new PluginManifest();
         var5.setName(var2.name);
         var5.setGroup(var2.group);
         if (var2.description != null) {
            var5.setDescription(var2.description);
         }

         if (var2.website != null) {
            var5.setWebsite(var2.website);
         }

         if (var2.version != null && !var2.version.isEmpty()) {
            try {
               var5.setVersion(Semver.fromString(var2.version));
            } catch (IllegalArgumentException var16) {
               ((HytaleLogger.Api)this.getLogger().at(Level.WARNING).withCause(var16)).log("Invalid version format: %s", var2.version);
               var1.sendFailureReply(var3, Messages.INVALID_VERSION_FORMAT);
               class="kw">return;
            }
         }

         if (var2.authors != null) {
            List var6 = new ObjectArrayList();

            for (com.hypixel.hytale.protocol.packets.asseteditor.AuthorInfo var10 : var2.authors) {
               AuthorInfo var11 = new AuthorInfo();
               var11.setName(var10.name);
               var11.setEmail(var10.email);
               var11.setUrl(var10.url);
               var6.add(var11);
            }

            var5.setAuthors(var6);
         }

         if (var2.serverVersion != null && !var2.serverVersion.isBlank()) {
            try {
               var5.setServerVersion(SemverRange.fromString(var2.serverVersion));
            } catch (IllegalArgumentException var15) {
               ((HytaleLogger.Api)this.getLogger().at(Level.WARNING).withCause(var15))
                  .log("Rejected pack creation: invalid ServerVersion range '%s'", var2.serverVersion);
               var1.sendFailureReply(var3, Messages.INVALID_SERVER_VERSION);
               class="kw">return;
            }
         } else {
            var5.setServerVersion(SemverRange.WILDCARD);
         }

         String var17 = new PluginIdentifier(var5).toString();
         if (this.assetPackDataSources.containsKey(var17)) {
            var1.sendFailureReply(var3, Messages.PACK_ALREADY_EXISTS);
         } else {
            List var18 = this.getModsDirectories();
            if (var4 >= 0 && var4 < var18.size()) {
               Path var19 = var18.get(var4);
               String var20 = AssetPathUtil.removeInvalidFileNameChars(var2.group != null ? var2.group + "." + var2.name : var2.name);
               Path var21 = Path.of(var20).normalize();
               if (AssetPathUtil.isInvalidFileName(var21)) {
                  var1.sendFailureReply(var3, Messages.INVALID_FILE_NAME);
               } else {
                  Path var22 = var19.resolve(var21).normalize();
                  if (!var22.startsWith(var19)) {
                     var1.sendFailureReply(var3, Messages.PACK_OUTSIDE_DIRECTORY);
                  } else if (Files.exists(var22)) {
                     var1.sendFailureReply(var3, Messages.PACK_ALREADY_EXISTS_AT_PATH);
                  } else {
                     try {
                        Files.createDirectories(var22);
                        Path var12 = var22.resolve("manifest.json");
                        BsonUtil.writeSync(var12, PluginManifest.CODEC, var5, this.getLogger());
                        HytaleServerConfig var13 = HytaleServer.get().getConfig();
                        HytaleServerConfig.setBoot(var13, new PluginIdentifier(var5), true);
                        var13.markChanged();
                        if (var13.consumeHasChanged()) {
                           HytaleServerConfig.save(var13).join();
                        }

                        if (!AssetModule.get().registerPack(var17, var22, var5, AssetPack.PackSource.RUNTIME)) {
                           var1.sendFailureReply(var3, Messages.PACK_CREATION_FAILED);
                           class="kw">return;
                        }

                        var1.sendSuccessReply(var3, Messages.PACK_CREATED);
                        this.getLogger().at(Level.INFO).log("Created new pack: %s at %s", var17, var22);
                     } catch (IOException var14) {
                        ((HytaleLogger.Api)this.getLogger().at(Level.SEVERE).withCause(var14)).log("Failed to create pack %s", var17);
                        var1.sendFailureReply(var3, Messages.PACK_CREATION_FAILED);
                     }
                  }
               }
            } else {
               var1.sendFailureReply(var3, Messages.INVALID_TARGET_DIRECTORY);
            }
         }
      } else {
         var1.sendFailureReply(var3, Messages.PACK_GROUP_REQUIRED);
      }
   }

   @Nonnull
   class="kw">private class="kw">static AssetPackManifest toManifestPacket(@Nonnull PluginManifest var0) {
      AssetPackManifest var1 = new AssetPackManifest();
      var1.name = var0.getName();
      var1.description = var0.getDescription() != null ? var0.getDescription() : "";
      var1.group = var0.getGroup();
      var1.version = var0.getVersion() != null ? var0.getVersion().toString() : "";
      var1.website = var0.getWebsite() != null ? var0.getWebsite() : "";
      var1.serverVersion = var0.getServerVersion() != null ? var0.getServerVersion().toString() : "";
      List var2 = new ObjectArrayList();

      for (AuthorInfo var4 : var0.getAuthors()) {
         com.hypixel.hytale.protocol.packets.asseteditor.AuthorInfo var5 = new com.hypixel.hytale.protocol.packets.asseteditor.AuthorInfo(
            var4.getName(), var4.getEmail(), var4.getUrl()
         );
         var2.add(var5);
      }

      var1.authors = var2.toArray(new com.hypixel.hytale.protocol.packets.asseteditor.AuthorInfo[0]);
      class="kw">return var1;
   }

   class="kw">private void broadcastPackAddedOrUpdated(@Nonnull String var1, @Nonnull PluginManifest var2) {
      AssetPackManifest var3 = toManifestPacket(var2);

      for (Set var5 : this.uuidToEditorClients.values()) {
         for (EditorClient var7 : var5) {
            var7.getPacketHandler().write(new AssetEditorUpdateAssetPack(var1, var3));
         }
      }
   }

   class="kw">public void handleExportAssets(@Nonnull EditorClient var1, @Nonnull List<AssetPath> var2) {
      ObjectArrayList var3 = new ObjectArrayList();

      for (AssetPath var5 : var2) {
         DataSource var6 = this.getDataSourceForPath(var5);
         if (var6 == null) {
            this.getLogger().at(Level.WARNING).log("%s has no valid data source", var5);
            AssetEditorAsset var13 = new AssetEditorAsset(null, var5.toPacket());
            var1.getPacketHandler().write(new AssetEditorExportAssetInitialize(var13, null, 0, true));
         } else if (!this.isValidPath(var6, var5)) {
            this.getLogger().at(Level.WARNING).log("%s is an invalid path", var5);
            AssetEditorAsset var12 = new AssetEditorAsset(null, var5.toPacket());
            var1.getPacketHandler().write(new AssetEditorExportAssetInitialize(var12, null, 0, true));
         } else if (this.assetTypeRegistry.getAssetTypeHandlerForPath(var5.path()) == null) {
            this.getLogger().at(Level.WARNING).log("%s is not a valid asset type", var5);
            AssetEditorAsset var11 = new AssetEditorAsset(null, var5.toPacket());
            var1.getPacketHandler().write(new AssetEditorExportAssetInitialize(var11, null, 0, true));
         } else if (!var6.doesAssetExist(var5.path())) {
            var1.getPacketHandler().write(new AssetEditorExportDeleteAssets(new AssetEditorAsset[]{new AssetEditorAsset(null, var5.toPacket())}));
         } else {
            byte[] var7 = var6.getAssetBytes(var5.path());
            if (var7 == null) {
               this.getLogger().at(Level.WARNING).log("Tried to load %s for export but failed", var5);
               var1.getPacketHandler().write(new AssetEditorExportAssetInitialize(new AssetEditorAsset(null, var5.toPacket()), null, 0, false));
            } else {
               byte[][] var8 = ArrayUtil.split(var7, 2621440);
               ToClientPacket[] var9 = new ToClientPacket[2 + var8.length];
               var9[0] = new AssetEditorExportAssetInitialize(new AssetEditorAsset(null, var5.toPacket()), null, var7.length, false);

               for (int var10 = 0; var10 < var8.length; var10++) {
                  var9[1 + var10] = new AssetEditorExportAssetPart(var8[var10]);
               }

               var9[var9.length - 1] = new AssetEditorExportAssetFinalize();
               var1.getPacketHandler().write(var9);
               Instant var14 = var6.getLastModificationTimestamp(var5.path());
               var3.add(new TimestampedAssetReference(var5.toPacket(), var14 != null ? var14.toString() : null));
            }
         }
      }

      var1.getPacketHandler().write(new AssetEditorExportComplete((TimestampedAssetReference[])var3.toArray(TimestampedAssetReference[]::new)));
   }

   class="kw">public void handleSelectAsset(@Nonnull EditorClient var1, @Nullable AssetPath var2) {
      if (var2 != null) {
         DataSource var3 = this.getDataSourceForPath(var2);
         if (var3 == null) {
            class="kw">return;
         }
      }

      String var7 = null;
      String var4 = null;
      AssetPath var5 = this.clientOpenAssetPathMapping.get(var1);
      if (var5 != null && !var5.equals(AssetPath.EMPTY_PATH)) {
         AssetTypeHandler var6 = this.assetTypeRegistry.tryGetAssetTypeHandler(var5.path(), var1, -1);
         if (var6 != null) {
            var4 = var6.getConfig().id;
         }
      }

      if (var2 != null) {
         AssetTypeHandler var8 = this.assetTypeRegistry.tryGetAssetTypeHandler(var2.path(), var1, -1);
         if (var8 == null) {
            class="kw">return;
         }

         var7 = var8.getConfig().id;
         this.clientOpenAssetPathMapping.put(var1, var2);
      } else {
         this.clientOpenAssetPathMapping.put(var1, AssetPath.EMPTY_PATH);
      }

      IEventDispatcher var9 = HytaleServer.get().getEventBus().dispatchFor(AssetEditorSelectAssetEvent.class);
      if (var9.hasListener()) {
         var9.dispatch(new AssetEditorSelectAssetEvent(var1, var7, var2, var4, var5));
      }
   }

   class="kw">public void handleFetchLastModifiedAssets(@Nonnull EditorClient var1) {
      long var2 = this.globalEditLock.readLock();

      try {
         AssetEditorLastModifiedAssets var4 = this.buildAssetEditorLastModifiedAssetsPacket();
         var1.getPacketHandler().write(var4);
      } class="kw">finally {
         this.globalEditLock.unlockRead(var2);
      }
   }

   class="kw">public void handleAssetUpdate(@Nonnull EditorClient var1, @Nonnull AssetPath var2, @Nonnull byte[] var3, int var4) {
      DataSource var5 = this.getDataSourceForPath(var2);
      if (var5 == null) {
         var1.sendFailureReply(var4, Messages.UNKNOWN_ASSET_PACK);
      } else if (var5.isImmutable()) {
         var1.sendFailureReply(var4, Messages.ASSETS_READ_ONLY);
      } else if (!this.isValidPath(var5, var2)) {
         var1.sendFailureReply(var4, Messages.DIRECTORY_OUTSIDE_ASSET_TYPE_ROOT);
      } else {
         AssetTypeHandler var6 = this.assetTypeRegistry.tryGetAssetTypeHandler(var2.path(), var1, var4);
         if (var6 != null) {
            long var7 = this.globalEditLock.writeLock();

            label79: {
               try {
                  if (!var5.doesAssetExist(var2.path())) {
                     this.getLogger().at(Level.WARNING).log("%s does not exist", var2);
                     var1.sendFailureReply(var4, Messages.UPDATE_DOESNT_EXIST);
                     class="kw">return;
                  }

                  if (!var6.isValidData(var3)) {
                     this.getLogger().at(Level.WARNING).log("Failed to validate data for %s", var2);
                     var1.sendFailureReply(var4, Messages.CREATE_ASSET_FAILED);
                     class="kw">return;
                  }

                  if (var5.updateAsset(var2.path(), var3, var1)) {
                     this.updateAssetForConnectedClients(var2, var3, var1);
                     this.sendModifiedAssetsUpdateToConnectedUsers();
                     var1.sendSuccessReply(var4);
                     var6.loadAsset(var2, var5.getFullPathToAssetData(var2.path()), var3, var1);
                     break label79;
                  }

                  this.getLogger().at(Level.WARNING).log("Failed to update asset %s in data source!", var2);
                  var1.sendFailureReply(var4, Messages.UPDATE_FAILED);
               } class="kw">finally {
                  this.globalEditLock.unlockWrite(var7);
               }

               class="kw">return;
            }

            this.getLogger().at(Level.INFO).log("Updated asset at %s", var2);
         }
      }
   }

   class="kw">public void handleJsonAssetUpdate(@Nonnull EditorClient var1, AssetPath var2, @Nonnull String var3, int var4, @Nonnull JsonUpdateCommand[] var5, int var6) {
      AssetTypeHandler var7 = this.assetTypeRegistry.getAssetTypeHandler(var3);
      if (!(var7 class="kw">instanceof JsonTypeHandler var8)) {
         this.getLogger().at(Level.WARNING).log("Invalid asset type %s", var3);
         var1.sendFailureReply(var6, Message.translation("server.assetEditor.messages.unknownAssetType").param("assetType", var3));
      } else {
         DataSource var9;
         if (var4 > -1 && var7 class="kw">instanceof AssetStoreTypeHandler var10) {
            AssetStore var11 = var10.getAssetStore();
            AssetMap var12 = var11.getAssetMap();
            String var13 = AssetStoreUtil.getIdFromIndex(var11, var4);
            Object var14 = var11.decodeStringKey(var13);
            Path var15 = var12.getPath(var14);
            String var16 = var12.getAssetPack(var14);
            if (var15 == null || var16 == null) {
               var1.sendFailureReply(var6, Messages.UNKNOWN_ASSET_INDEX);
               class="kw">return;
            }

            var9 = this.getDataSourceForPack(var16);
            if (var9 == null) {
               var1.sendFailureReply(var6, Messages.UNKNOWN_ASSET_PACK);
               class="kw">return;
            }

            var2 = new AssetPath(var16, PathUtil.relativizePretty(var9.getRootPath(), var15));
         } else {
            var9 = this.getDataSourceForPath(var2);
            if (var9 == null) {
               var1.sendFailureReply(var6, Messages.UNKNOWN_ASSET_PACK);
               class="kw">return;
            }
         }

         if (var9.isImmutable()) {
            var1.sendFailureReply(var6, Messages.ASSETS_READ_ONLY);
         } else if (!this.isValidPath(var9, var2)) {
            var1.sendFailureReply(var6, Messages.DIRECTORY_OUTSIDE_ASSET_TYPE_ROOT);
         } else if (!var2.path().startsWith(var7.getRootPath())) {
            this.getLogger().at(Level.WARNING).log("%s is not within valid asset directory", var2);
            var1.sendFailureReply(var6, Messages.DIRECTORY_OUTSIDE_ROOT);
         } else {
            String var26 = PathUtil.getFileExtension(var2.path());
            if (!var26.equalsIgnoreCase(var7.getConfig().fileExtension)) {
               this.getLogger().at(Level.WARNING).log("File extension not matching. Expected %s, got %s", var7.getConfig().fileExtension, var26);
               this.getLogger().at(Level.WARNING).log("File extension not matching. Expected %s, got %s", var7.getConfig().fileExtension, var26);
               var1.sendFailureReply(
                  var6, Message.translation("server.assetEditor.messages.fileExtensionMismatch").param("fileExtension", var7.getConfig().fileExtension)
               );
            } else {
               long var27 = this.globalEditLock.writeLock();

               try {
                  byte[] var28 = var9.getAssetBytes(var2.path());
                  if (var28 == null) {
                     this.getLogger().at(Level.WARNING).log("%s does not exist", var2);
                     var1.sendFailureReply(var6, Messages.UPDATE_DOESNT_EXIST);
                     class="kw">return;
                  }

                  AssetUpdateQuery.RebuildCacheBuilder var30 = AssetUpdateQuery.RebuildCache.builder();

                  BsonDocument var31;
                  try {
                     var31 = this.applyCommandsToAsset(var28, var2, var5, var30);
                     String var32 = BsonUtil.toJson(var31) + "\n";
                     var28 = var32.getBytes(StandardCharsets.UTF_8);
                  } catch (Exception var24) {
                     ((HytaleLogger.Api)this.getLogger().at(Level.WARNING).withCause(var24)).log("Failed to apply commands to %s", var2);
                     var1.sendFailureReply(var6, Messages.UPDATE_FAILED);
                     class="kw">return;
                  }

                  if (var9.updateAsset(var2.path(), var28, var1)) {
                     AssetUndoRedoInfo var33 = this.undoRedoManager.getOrCreateUndoRedoStack(var2);
                     var33.redoStack.clear();

                     for (JsonUpdateCommand var20 : var5) {
                        var33.undoStack.push(var20);
                     }

                     this.updateJsonAssetForConnectedClients(var2, var5, var1);
                     var1.sendSuccessReply(var6);
                     this.sendModifiedAssetsUpdateToConnectedUsers();
                     var8.loadAssetFromDocument(var2, var9.getFullPathToAssetData(var2.path()), var31.clone(), new AssetUpdateQuery(var30.build()), var1);
                     class="kw">return;
                  }

                  var1.sendFailureReply(var6, Messages.UPDATE_FAILED);
               } class="kw">finally {
                  this.globalEditLock.unlockWrite(var27);
               }
            }
         }
      }
   }

   class="kw">public void handleUndo(@Nonnull EditorClient var1, @Nonnull AssetPath var2, int var3) {
      DataSource var4 = this.getDataSourceForPath(var2);
      if (var4 == null) {
         var1.sendFailureReply(var3, Messages.UNKNOWN_ASSET_PACK);
      } else if (var4.isImmutable()) {
         var1.sendFailureReply(var3, Messages.ASSETS_READ_ONLY);
      } else if (!this.isValidPath(var4, var2)) {
         var1.sendFailureReply(var3, Messages.DIRECTORY_OUTSIDE_ASSET_TYPE_ROOT);
      } else {
         AssetTypeHandler var5 = this.assetTypeRegistry.tryGetAssetTypeHandler(var2.path(), var1, var3);
         if (var5 != null) {
            if (!(var5 class="kw">instanceof JsonTypeHandler)) {
               this.getLogger().at(Level.WARNING).log("Undo can only be applied to an instance of JsonTypeHandler");
               var1.sendFailureReply(var3, Messages.INVALID_ASSET_TYPE);
            } else {
               long var6 = this.globalEditLock.writeLock();

               try {
                  AssetUndoRedoInfo var8 = this.undoRedoManager.getUndoRedoStack(var2);
                  if (var8 == null || var8.undoStack.isEmpty()) {
                     this.getLogger().at(Level.INFO).log("Nothing to undo");
                     var1.sendFailureReply(var3, Messages.UNDO_EMPTY);
                     class="kw">return;
                  }

                  JsonUpdateCommand var9 = var8.undoStack.peek();
                  JsonUpdateCommand var10 = new JsonUpdateCommand();
                  var10.rebuildCaches = var9.rebuildCaches;
                  if (var9.firstCreatedProperty != null) {
                     var10.type = JsonUpdateType.RemoveProperty;
                     var10.path = var9.firstCreatedProperty;
                  } else {
                     var10.type = var9.type == JsonUpdateType.RemoveProperty ? JsonUpdateType.InsertProperty : JsonUpdateType.SetProperty;
                     var10.path = var9.path;
                     var10.value = var9.previousValue;
                  }

                  byte[] var11 = var4.getAssetBytes(var2.path());
                  if (var11 == null) {
                     this.getLogger().at(Level.WARNING).log("%s does not exist", var2);
                     var1.sendFailureReply(var3, Messages.UPDATE_DOESNT_EXIST);
                     class="kw">return;
                  }

                  AssetUpdateQuery.RebuildCacheBuilder var13 = AssetUpdateQuery.RebuildCache.builder();

                  BsonDocument var12;
                  try {
                     var12 = this.applyCommandsToAsset(var11, var2, new JsonUpdateCommand[]{var10}, var13);
                     String var14 = BsonUtil.toJson(var12) + "\n";
                     var11 = var14.getBytes(StandardCharsets.UTF_8);
                  } catch (Exception var18) {
                     ((HytaleLogger.Api)this.getLogger().at(Level.WARNING).withCause(var18)).log("Failed to undo for %s", var2);
                     var1.sendFailureReply(var3, Messages.UNDO_FAILED);
                     class="kw">return;
                  }

                  if (var4.updateAsset(var2.path(), var11, var1)) {
                     var8.undoStack.poll();
                     var8.redoStack.push(var9);
                     this.updateJsonAssetForConnectedClients(var2, new JsonUpdateCommand[]{var10}, var1);
                     var1.getPacketHandler().write(new AssetEditorUndoRedoReply(var3, var10));
                     this.sendModifiedAssetsUpdateToConnectedUsers();
                     ((JsonTypeHandler)var5)
                        .loadAssetFromDocument(var2, var4.getFullPathToAssetData(var2.path()), var12.clone(), new AssetUpdateQuery(var13.build()), var1);
                     class="kw">return;
                  }

                  var1.sendFailureReply(var3, Messages.UNDO_FAILED);
               } class="kw">finally {
                  this.globalEditLock.unlockWrite(var6);
               }
            }
         }
      }
   }

   class="kw">public void handleRedo(@Nonnull EditorClient var1, @Nonnull AssetPath var2, int var3) {
      DataSource var4 = this.getDataSourceForPath(var2);
      if (var4 == null) {
         var1.sendFailureReply(var3, Messages.UNKNOWN_ASSET_PACK);
      } else if (var4.isImmutable()) {
         var1.sendFailureReply(var3, Messages.ASSETS_READ_ONLY);
      } else if (!this.isValidPath(var4, var2)) {
         var1.sendFailureReply(var3, Messages.DIRECTORY_OUTSIDE_ASSET_TYPE_ROOT);
      } else {
         AssetTypeHandler var5 = this.assetTypeRegistry.tryGetAssetTypeHandler(var2.path(), var1, var3);
         if (var5 != null) {
            if (!(var5 class="kw">instanceof JsonTypeHandler)) {
               this.getLogger().at(Level.WARNING).log("Redo can only be applied to an instance of JsonTypeHandler");
               var1.sendFailureReply(var3, Messages.INVALID_ASSET_TYPE);
            } else {
               long var6 = this.globalEditLock.writeLock();

               try {
                  AssetUndoRedoInfo var8 = this.undoRedoManager.getUndoRedoStack(var2);
                  if (var8 == null || var8.redoStack.isEmpty()) {
                     this.getLogger().at(Level.WARNING).log("Nothing to redo");
                     var1.sendFailureReply(var3, Messages.REDO_EMPTY);
                     class="kw">return;
                  }

                  byte[] var9 = var4.getAssetBytes(var2.path());
                  if (var9 == null) {
                     this.getLogger().at(Level.WARNING).log("%s does not exist", var2);
                     var1.sendFailureReply(var3, Messages.UPDATE_DOESNT_EXIST);
                     class="kw">return;
                  }

                  JsonUpdateCommand var10 = var8.redoStack.peek();
                  AssetUpdateQuery.RebuildCacheBuilder var11 = AssetUpdateQuery.RebuildCache.builder();

                  BsonDocument var12;
                  try {
                     var12 = this.applyCommandsToAsset(var9, var2, new JsonUpdateCommand[]{var10}, var11);
                     String var13 = BsonUtil.toJson(var12) + "\n";
                     var9 = var13.getBytes(StandardCharsets.UTF_8);
                  } catch (Exception var17) {
                     ((HytaleLogger.Api)this.getLogger().at(Level.WARNING).withCause(var17)).log("Failed to redo for %s", var2);
                     var1.sendFailureReply(var3, Messages.REDO_FAILED);
                     class="kw">return;
                  }

                  if (var4.updateAsset(var2.path(), var9, var1)) {
                     var8.redoStack.poll();
                     var8.undoStack.push(var10);
                     this.updateJsonAssetForConnectedClients(var2, new JsonUpdateCommand[]{var10}, var1);
                     var1.getPacketHandler().write(new AssetEditorUndoRedoReply(var3, var10));
                     this.sendModifiedAssetsUpdateToConnectedUsers();
                     ((JsonTypeHandler)var5)
                        .loadAssetFromDocument(var2, var4.getFullPathToAssetData(var2.path()), var12.clone(), new AssetUpdateQuery(var11.build()), var1);
                     class="kw">return;
                  }

                  var1.sendFailureReply(var3, Messages.REDO_FAILED);
               } class="kw">finally {
                  this.globalEditLock.unlockWrite(var6);
               }
            }
         }
      }
   }

   class="kw">public void handleFetchAsset(@Nonnull EditorClient var1, @Nonnull AssetPath var2, int var3) {
      DataSource var4 = this.getValidatedDataSource(var1, var2, var3);
      if (var4 != null) {
         long var5 = this.globalEditLock.readLock();

         try {
            if (!var4.doesAssetExist(var2.path())) {
               this.getLogger().at(Level.WARNING).log("%s is not a regular file", var2);
               var1.sendFailureReply(var3, Messages.FETCH_ASSET_DOESNT_EXIST);
               class="kw">return;
            }

            byte[] var7 = var4.getAssetBytes(var2.path());
            if (var7 != null) {
               this.getLogger().at(Level.INFO).log("Got '%s'", var2);
               var1.getPacketHandler().write(new AssetEditorFetchAssetReply(var3, var7));
               class="kw">return;
            }

            this.getLogger().at(Level.INFO).log("Failed to get '%s'", var2);
            var1.sendFailureReply(var3, Messages.FETCH_ASSET_FAILED);
         } class="kw">finally {
            this.globalEditLock.unlockRead(var5);
         }
      }
   }

   class="kw">public void handleFetchJsonAssetWithParents(@Nonnull EditorClient var1, @Nonnull AssetPath var2, boolean var3, int var4) {
      DataSource var5 = this.getValidatedDataSource(var1, var2, var4);
      if (var5 != null) {
         long var6 = this.globalEditLock.readLock();

         try {
            byte[] var8 = var5.getAssetBytes(var2.path());
            if (var8 != null) {
               this.getLogger().at(Level.INFO).log("Got '%s'", var2);
               BsonDocument var9 = BsonDocument.parse(new String(var8, StandardCharsets.UTF_8));
               Object2ObjectOpenHashMap var10 = new Object2ObjectOpenHashMap();
               var10.put(var2.toPacket(), BsonUtil.toJson(var9));
               var1.getPacketHandler().write(new AssetEditorFetchJsonAssetWithParentsReply(var4, var10));
               class="kw">return;
            }

            this.getLogger().at(Level.INFO).log("Failed to get '%s'", var2);
            var1.sendFailureReply(var4, Messages.FETCH_ASSET_FAILED);
         } class="kw">finally {
            this.globalEditLock.unlockRead(var6);
         }
      }
   }

   class="kw">public void handleRequestChildIds(@Nonnull EditorClient var1, @Nonnull AssetPath var2) {
      DataSource var3 = this.getDataSourceForPath(var2);
      if (var3 == null) {
         var1.sendPopupNotification(AssetEditorPopupNotificationType.Error, Messages.UNKNOWN_ASSET_PACK);
      } else if (!this.isValidPath(var3, var2)) {
         var1.sendPopupNotification(AssetEditorPopupNotificationType.Error, Messages.DIRECTORY_OUTSIDE_ASSET_TYPE_ROOT);
      } else if (!(this.assetTypeRegistry.getAssetTypeHandlerForPath(var2.path()) class="kw">instanceof AssetStoreTypeHandler var5)) {
         this.getLogger().at(Level.WARNING).log("Invalid asset type for %s", var2);
         var1.sendPopupNotification(AssetEditorPopupNotificationType.Error, Messages.REQUEST_CHILD_IDS_ASSET_TYPE_MISSING);
      } else {
         AssetStore var6 = var5.getAssetStore();
         AssetMap var7 = var6.getAssetMap();
         Object var8 = var6.decodeFilePathKey(var2.path());
         Set var9 = var7.getChildren(var8);
         HashSet var10 = new HashSet();
         if (var9 != null) {
            for (Object var12 : var9) {
               if (var7.getPath(var12) != null) {
                  var10.add(var12.toString());
               }
            }
         }

         this.getLogger().at(Level.INFO).log("Children ids for '%s': %s", var8.toString(), var10);
         var1.getPacketHandler().write(new AssetEditorRequestChildrenListReply(var2.toPacket(), var10.toArray(String[]::new)));
      }
   }

   class="kw">public void handleDeleteAsset(@Nonnull EditorClient var1, @Nonnull AssetPath var2, int var3) {
      DataSource var4 = this.getDataSourceForPath(var2);
      if (var4 == null) {
         var1.sendFailureReply(var3, Messages.UNKNOWN_ASSET_PACK);
      } else if (var4.isImmutable()) {
         var1.sendFailureReply(var3, Messages.ASSETS_READ_ONLY);
      } else if (!this.isValidPath(var4, var2)) {
         var1.sendFailureReply(var3, Messages.DIRECTORY_OUTSIDE_ASSET_TYPE_ROOT);
      } else {
         AssetTypeHandler var5 = this.assetTypeRegistry.tryGetAssetTypeHandler(var2.path(), var1, var3);
         if (var5 != null) {
            long var6 = this.globalEditLock.writeLock();

            label68: {
               try {
                  if (!var4.doesAssetExist(var2.path())) {
                     this.getLogger().at(Level.WARNING).log("%s does not exist", var2);
                     var1.sendFailureReply(var3, Messages.DELETE_ASSET_ALREADY_DELETED);
                     class="kw">return;
                  }

                  if (var4.deleteAsset(var2.path(), var1)) {
                     this.undoRedoManager.clearUndoRedoStack(var2);
                     AssetEditorFileEntry var8 = var4.getAssetTree().removeAsset(var2.path());
                     AssetEditorAssetListUpdate var9 = new AssetEditorAssetListUpdate(var2.packId(), null, new AssetEditorFileEntry[]{var8});
                     var1.sendSuccessReply(var3);
                     this.sendPacketToAllEditorUsersExcept(var9, var1);
                     this.sendModifiedAssetsUpdateToConnectedUsers();
                     var5.unloadAsset(var2);
                     break label68;
                  }

                  this.getLogger().at(Level.WARNING).log("Failed to delete %s from data source", var2);
                  var1.sendFailureReply(var3, Messages.FAILED_TO_DELETE_ASSET);
               } class="kw">finally {
                  this.globalEditLock.unlockWrite(var6);
               }

               class="kw">return;
            }

            this.getLogger().at(Level.INFO).log("Deleted asset %s", var2);
         }
      }
   }

   class="kw">public void handleSubscribeToModifiedAssetsChanges(@Nonnull EditorClient var1) {
      this.clientsSubscribedToModifiedAssetsChanges.add(var1);
   }

   class="kw">public void handleUnsubscribeFromModifiedAssetsChanges(@Nonnull EditorClient var1) {
      this.clientsSubscribedToModifiedAssetsChanges.remove(var1);
   }

   class="kw">public void handleRenameAsset(@Nonnull EditorClient var1, @Nonnull AssetPath var2, @Nonnull AssetPath var3, int var4) {
      if (!var2.packId().equals(var3.packId())) {
         this.getLogger().at(Level.WARNING).log("Rejected cross-pack asset rename from %s to %s", var2, var3);
         var1.sendFailureReply(var4, Messages.RENAME_ASSET_CROSS_PACK_UNSUPPORTED);
      } else {
         DataSource var5 = this.getDataSourceForPath(var2);
         if (var5 == null) {
            var1.sendFailureReply(var4, Messages.UNKNOWN_ASSET_PACK);
         } else if (var5.isImmutable()) {
            var1.sendFailureReply(var4, Messages.ASSETS_READ_ONLY);
         } else if (!this.isValidPath(var5, var2)) {
            var1.sendFailureReply(var4, Messages.DIRECTORY_OUTSIDE_ASSET_TYPE_ROOT);
         } else if (!this.isValidPath(var5, var3)) {
            var1.sendFailureReply(var4, Messages.DIRECTORY_OUTSIDE_ASSET_TYPE_ROOT);
         } else {
            AssetTypeHandler var6 = this.assetTypeRegistry.tryGetAssetTypeHandler(var2.path(), var1, var4);
            if (var6 != null) {
               String var7 = PathUtil.getFileExtension(var3.path());
               if (!var7.equalsIgnoreCase(var6.getConfig().fileExtension)) {
                  this.getLogger().at(Level.WARNING).log("File extension not matching. Expected %s, got %s", var6.getConfig().fileExtension, var7);
                  var1.sendFailureReply(
                     var4, Message.translation("server.assetEditor.messages.fileExtensionMismatch").param("fileExtension", var6.getConfig().fileExtension)
                  );
               } else if (!var3.path().startsWith(var6.getRootPath())) {
                  this.getLogger().at(Level.WARNING).log("%s is not within valid asset directory", var3);
                  var1.sendFailureReply(var4, Messages.DIRECTORY_OUTSIDE_ROOT);
               } else {
                  long var8 = this.globalEditLock.writeLock();

                  try {
                     if (var5.doesAssetExist(var3.path())) {
                        this.getLogger().at(Level.WARNING).log("%s already exists", var3);
                        var1.sendFailureReply(var4, Messages.RENAME_ASSET_ALREADY_EXISTS);
                        class="kw">return;
                     }

                     byte[] var10 = var5.getAssetBytes(var2.path());
                     if (var10 == null) {
                        this.getLogger().at(Level.WARNING).log("%s is not a regular file", var2);
                        var1.sendFailureReply(var4, Messages.RENAME_ASSET_DOESNT_EXIST);
                        class="kw">return;
                     }

                     if (var5.moveAsset(var2.path(), var3.path(), var1)) {
                        AssetUndoRedoInfo var11 = this.undoRedoManager.clearUndoRedoStack(var2);
                        if (var11 != null) {
                           this.undoRedoManager.putUndoRedoStack(var3, var11);
                        }

                        this.getLogger().at(Level.WARNING).log("Moved %s to %s", var2, var3);
                        AssetEditorFileEntry var12 = var5.getAssetTree().removeAsset(var2.path());
                        AssetEditorFileEntry var13 = var5.getAssetTree().ensureAsset(var3.path(), false);
                        AssetEditorAssetListUpdate var14 = new AssetEditorAssetListUpdate(
                           var2.packId(), new AssetEditorFileEntry[]{var13}, new AssetEditorFileEntry[]{var12}
                        );
                        this.sendPacketToAllEditorUsersExcept(var14, var1);
                        var1.sendSuccessReply(var4);
                        var6.unloadAsset(var2);
                        var6.loadAsset(var3, var5.getFullPathToAssetData(var3.path()), var10, var1);
                        class="kw">return;
                     }

                     this.getLogger().at(Level.WARNING).log("Failed to move file %s to %s", var2, var3);
                     var1.sendFailureReply(var4, Messages.RENAME_ASSET_FAILED);
                  } class="kw">finally {
                     this.globalEditLock.unlockWrite(var8);
                  }
               }
            }
         }
      }
   }

   class="kw">public void handleDeleteDirectory(@Nonnull EditorClient var1, @Nonnull AssetPath var2, int var3) {
      DataSource var4 = this.getDataSourceForPath(var2);
      if (var4.isImmutable()) {
         var1.sendFailureReply(var3, Messages.ASSETS_READ_ONLY);
      } else if (!this.isValidPath(var4, var2)) {
         var1.sendFailureReply(var3, Messages.DIRECTORY_OUTSIDE_ROOT);
      } else if (!this.getAssetTypeRegistry().isPathInAssetTypeFolder(var2.path())) {
         var1.sendFailureReply(var3, Messages.DIRECTORY_OUTSIDE_ASSET_TYPE_ROOT);
      } else {
         long var5 = this.globalEditLock.writeLock();

         try {
            if (!var4.doesDirectoryExist(var2.path())) {
               this.getLogger().at(Level.WARNING).log("Directory doesn't exist %s", var2);
               var1.sendFailureReply(var3, Messages.CREATE_DIRECTORY_ALREADY_EXISTS);
               class="kw">return;
            }

            if (!var4.getAssetTree().isDirectoryEmpty(var2.path())) {
               this.getLogger().at(Level.WARNING).log("%s must be empty", var2);
               var1.sendFailureReply(var3, Messages.DELETE_DIRECTORY_NOT_EMPTY);
               class="kw">return;
            }

            if (var4.deleteDirectory(var2.path())) {
               AssetEditorFileEntry var7 = var4.getAssetTree().removeAsset(var2.path());
               AssetEditorAssetListUpdate var8 = new AssetEditorAssetListUpdate(var2.packId(), null, new AssetEditorFileEntry[]{var7});
               this.sendPacketToAllEditorUsersExcept(var8, var1);
               var1.sendSuccessReply(var3);
               this.getLogger().at(Level.INFO).log("Deleted directory %s", var2);
               class="kw">return;
            }

            this.getLogger().at(Level.WARNING).log("Directory %s could not be deleted!", var2);
            var1.sendFailureReply(var3, Messages.DELETE_DIRECTORY_FAILED);
         } class="kw">finally {
            this.globalEditLock.unlockWrite(var5);
         }
      }
   }

   class="kw">public void handleRenameDirectory(@Nonnull EditorClient var1, AssetPath var2, AssetPath var3, int var4) {
      var1.sendFailureReply(var4, Messages.RENAME_DIRECTORY_UNSUPPORTED);
   }

   class="kw">public void handleCreateDirectory(@Nonnull EditorClient var1, @Nonnull AssetPath var2, int var3) {
      DataSource var4 = this.getDataSourceForPath(var2);
      if (var4 == null) {
         var1.sendFailureReply(var3, Messages.CREATE_DIRECTORY_NO_DATA_SOURCE);
      } else if (var4.isImmutable()) {
         var1.sendFailureReply(var3, Messages.ASSETS_READ_ONLY);
      } else if (!this.isValidPath(var4, var2)) {
         var1.sendFailureReply(var3, Messages.CREATE_DIRECTORY_NO_PATH);
      } else {
         long var5 = this.globalEditLock.writeLock();

         try {
            if (var4.doesDirectoryExist(var2.path())) {
               this.getLogger().at(Level.WARNING).log("Directory already exists at %s", var2);
               var1.sendFailureReply(var3, Messages.CREATE_DIRECTORY_ALREADY_EXISTS);
               class="kw">return;
            }

            Path var7 = var2.path().getParent();
            if (!var4.doesDirectoryExist(var7)) {
               this.getLogger().at(Level.WARNING).log("Parent directory is missing for %s", var2);
               var1.sendFailureReply(var3, Messages.PARENT_DIRECTORY_MISSING);
               class="kw">return;
            }

            if (var4.createDirectory(var2.path(), var1)) {
               AssetEditorFileEntry var8 = var4.getAssetTree().ensureAsset(var2.path(), true);
               if (var8 != null) {
                  AssetEditorAssetListUpdate var9 = new AssetEditorAssetListUpdate(var2.packId(), new AssetEditorFileEntry[]{var8}, null);
                  this.sendPacketToAllEditorUsersExcept(var9, var1);
               }

               var1.sendSuccessReply(var3);
               this.getLogger().at(Level.WARNING).log("Created directory %s", var2);
               class="kw">return;
            }

            this.getLogger().at(Level.WARNING).log("Failed to create directory %s", var2);
            var1.sendFailureReply(var3, Messages.FAILED_TO_CREATE_DIRECTORY);
         } class="kw">finally {
            this.globalEditLock.unlockWrite(var5);
         }
      }
   }

   class="kw">public void handleCreateAsset(
      @Nonnull EditorClient var1, @Nonnull AssetPath var2, @Nonnull byte[] var3, @Nonnull AssetEditorRebuildCaches var4, String var5, int var6
   ) {
      DataSource var7 = this.getDataSourceForPath(var2);
      if (var7 == null) {
         var1.sendFailureReply(var6, Messages.UNKNOWN_ASSET_PACK);
      } else if (var7.isImmutable()) {
         var1.sendFailureReply(var6, Messages.ASSETS_READ_ONLY);
      } else if (!this.isValidPath(var7, var2)) {
         var1.sendFailureReply(var6, Messages.DIRECTORY_OUTSIDE_ASSET_TYPE_ROOT);
      } else {
         AssetTypeHandler var8 = this.assetTypeRegistry.tryGetAssetTypeHandler(var2.path(), var1, var6);
         if (var8 != null) {
            long var9 = this.globalEditLock.writeLock();

            try {
               if (var7.doesAssetExist(var2.path())) {
                  this.getLogger().at(Level.WARNING).log("%s already exists", var2);
                  var1.sendFailureReply(var6, Messages.CREATE_ASSET_ID_ALREADY_EXISTS);
                  class="kw">return;
               }

               if (!var8.isValidData(var3)) {
                  this.getLogger().at(Level.WARNING).log("Failed to validate data for %s", var2);
                  var1.sendFailureReply(var6, Messages.CREATE_ASSET_FAILED);
                  class="kw">return;
               }

               if (var7.createAsset(var2.path(), var3, var1)) {
                  this.getLogger().at(Level.INFO).log("Created asset %s", var2);
                  AssetEditorFileEntry var11 = var7.getAssetTree().ensureAsset(var2.path(), false);
                  if (var11 != null) {
                     AssetEditorAssetListUpdate var12 = new AssetEditorAssetListUpdate(var2.packId(), new AssetEditorFileEntry[]{var11}, null);
                     this.sendPacketToAllEditorUsersExcept(var12, var1);
                  }

                  this.sendModifiedAssetsUpdateToConnectedUsers();
                  AssetUpdateQuery.RebuildCache var17 = new AssetUpdateQuery.RebuildCache(
                     var4.blockTextures,
                     var4.models,
                     var4.modelTextures,
                     var4.mapGeometry,
                     var4.itemIcons,
                     var2.path().startsWith(AssetPathUtil.PATH_DIR_COMMON)
                  );
                  var8.loadAsset(var2, var7.getFullPathToAssetData(var2.path()), var3, new AssetUpdateQuery(var17), var1);
                  IEventDispatcher var13 = HytaleServer.get().getEventBus().dispatchFor(AssetEditorAssetCreatedEvent.class, var8.getConfig().id);
                  if (var13.hasListener()) {
                     var13.dispatch(new AssetEditorAssetCreatedEvent(var1, var8.getConfig().id, var2.path(), var3, var5));
                  }

                  var1.sendSuccessReply(var6);
                  class="kw">return;
               }

               this.getLogger().at(Level.WARNING).log("Failed to create asset %s", var2);
               var1.sendFailureReply(var6, Messages.CREATE_ASSET_FAILED);
            } class="kw">finally {
               this.globalEditLock.unlockWrite(var9);
            }
         }
      }
   }

   class="kw">public void handleRequestAssetInheritance(@Nonnull EditorClient var1, @Nonnull AssetPath var2, int var3) {
      DataSource var4 = this.getValidatedDataSource(var1, var2, var3);
      if (var4 != null) {
         if (this.assetTypeRegistry.getAssetTypeHandlerForPath(var2.path()) class="kw">instanceof AssetStoreTypeHandler var5) {
            long var20 = this.globalEditLock.readLock();

            try {
               byte[] var8 = var4.getAssetBytes(var2.path());
               if (var8 == null) {
                  this.getLogger().at(Level.INFO).log("Failed to get '%s'", var2);
                  var1.sendFailureReply(var3, Messages.FETCH_ASSET_FAILED);
               } else {
                  BsonDocument var9;
                  try {
                     var9 = BsonDocument.parse(new String(var8, StandardCharsets.UTF_8));
                  } catch (RuntimeException var18) {
                     this.getLogger().at(Level.WARNING).log("Failed to parse asset '%s': %s", var2, var18.getMessage());
                     var1.sendFailureReply(var3, Messages.FETCH_ASSET_FAILED);
                     class="kw">return;
                  }

                  Schema var10 = this.getSchemaById(var5.getConfig().id);

                  AssetInheritanceTreeNode[] var11;
                  try {
                     var11 = var10 == null ? null : this.inheritanceResolver.resolveAncestors(var9, var10, var5.getAssetStore(), var2);
                  } catch (AssetInheritanceResolver.InheritanceResolutionException var17) {
                     this.getLogger().at(Level.WARNING).log("Failed to build inheritance chain for '%s': %s", var2, var17.getMessage());
                     var11 = null;
                  }

                  AssetInheritanceTreeNode var12 = new AssetInheritanceTreeNode(var2.toPacket(), BsonUtil.toJson(var9), var11);
                  var1.getPacketHandler().write(new AssetEditorRequestAssetInheritanceReply(var3, var12));
               }
            } class="kw">finally {
               this.globalEditLock.unlockRead(var20);
            }
         } else {
            var1.sendFailureReply(var3, Messages.FETCH_ASSET_FAILED);
         }
      }
   }

   class="kw">private BsonDocument applyCommandsToAsset(
      @Nonnull byte[] var1, AssetPath var2, @Nonnull JsonUpdateCommand[] var3, @Nonnull AssetUpdateQuery.RebuildCacheBuilder var4
   ) {
      BsonDocument var5 = BsonUtil.parseWithMaxDepth(new String(var1, StandardCharsets.UTF_8));
      this.getLogger().at(Level.INFO).log("Applying commands to %s with %s", var2, var5);

      for (JsonUpdateCommand var9 : var3) {
         class="kw">switch (var9.type) {
            case SetProperty: {
               BsonValue var15 = BsonUtil.parseWithMaxDepth(var9.value).get("value");
               this.getLogger().at(Level.INFO).log("Setting property %s to %s", String.join(".", var9.path), var15);
               if (var9.path.length > 0) {
                  BsonTransformationUtil.setProperty(var5, var9.path, var15);
               } else {
                  var5 = (BsonDocument)var15;
               }
               break;
            }
            case InsertProperty: {
               BsonValue var10 = BsonDocument.parse(var9.value).get("value");
               this.getLogger().at(Level.INFO).log("Inserting property %s with %s", String.join(".", var9.path), var10);
               BsonTransformationUtil.insertProperty(var5, var9.path, var10);
               break;
            }
            case RemoveProperty:
               this.getLogger().at(Level.INFO).log("Removing property %s", String.join(".", var9.path));
               BsonTransformationUtil.removeProperty(var5, var9.path);
         }
      }

      this.getLogger().at(Level.INFO).log("Updated %s resulting: %s", var2, var5);

      for (JsonUpdateCommand var14 : var3) {
         if (var14.rebuildCaches != null) {
            if (var14.rebuildCaches.blockTextures) {
               var4.setBlockTextures(true);
            }

            if (var14.rebuildCaches.modelTextures) {
               var4.setModelTextures(true);
            }

            if (var14.rebuildCaches.models) {
               var4.setModels(true);
            }

            if (var14.rebuildCaches.mapGeometry) {
               var4.setMapGeometry(true);
            }

            if (var14.rebuildCaches.itemIcons) {
               var4.setItemIcons(true);
            }
         }
      }

      class="kw">return var5;
   }

   class="kw">private void sendModifiedAssetsUpdateToConnectedUsers() {
      if (!this.clientOpenAssetPathMapping.isEmpty()) {
         if (!this.clientsSubscribedToModifiedAssetsChanges.isEmpty()) {
            AssetEditorLastModifiedAssets var1 = this.buildAssetEditorLastModifiedAssetsPacket();

            for (EditorClient var3 : this.clientsSubscribedToModifiedAssetsChanges) {
               var3.getPacketHandler().write(var1);
            }
         }
      }
   }

   class="kw">private void sendPacketToAllEditorUsers(@Nonnull ToClientPacket var1) {
      for (EditorClient var3 : this.clientOpenAssetPathMapping.keySet()) {
         var3.getPacketHandler().write(var1);
      }
   }

   class="kw">private void sendPacketToAllEditorUsersExcept(@Nonnull ToClientPacket var1, EditorClient var2) {
      for (EditorClient var4 : this.clientOpenAssetPathMapping.keySet()) {
         if (!var4.equals(var2)) {
            var4.getPacketHandler().write(var1);
         }
      }
   }

   class="kw">private void updateAssetForConnectedClients(@Nonnull AssetPath var1) {
      this.updateAssetForConnectedClients(var1, null);
   }

   class="kw">private void updateAssetForConnectedClients(@Nonnull AssetPath var1, @Nullable EditorClient var2) {
      DataSource var3 = this.getDataSourceForPath(var1);
      byte[] var4 = var3.getAssetBytes(var1.path());
      this.updateAssetForConnectedClients(var1, var4, var2);
   }

   class="kw">private void updateAssetForConnectedClients(@Nonnull AssetPath var1, byte[] var2, @Nullable EditorClient var3) {
      AssetEditorAssetUpdated var4 = new AssetEditorAssetUpdated(var1.toPacket(), var2);

      for (Entry var6 : this.clientOpenAssetPathMapping.entrySet()) {
         if (!var6.getKey().equals(var3) && var1.equals(var6.getValue())) {
            var6.getKey().getPacketHandler().write(var4);
         }
      }
   }

   class="kw">private void updateJsonAssetForConnectedClients(@Nonnull AssetPath var1, @Nonnull JsonUpdateCommand[] var2) {
      this.updateJsonAssetForConnectedClients(var1, var2, null);
   }

   class="kw">private void updateJsonAssetForConnectedClients(@Nonnull AssetPath var1, @Nonnull JsonUpdateCommand[] var2, @Nullable EditorClient var3) {
      AssetEditorJsonAssetUpdated var4 = new AssetEditorJsonAssetUpdated(var1.toPacket(), var2);

      for (Entry var6 : this.clientOpenAssetPathMapping.entrySet()) {
         if (!var6.getKey().equals(var3) && var1.equals(var6.getValue())) {
            var6.getKey().getPacketHandler().write(var4);
         }
      }
   }

   @Nonnull
   class="kw">private AssetEditorLastModifiedAssets buildAssetEditorLastModifiedAssetsPacket() {
      List var1 = new ObjectArrayList();

      for (Entry var3 : this.assetPackDataSources.entrySet()) {
         if (var3.getValue() class="kw">instanceof StandardDataSource var4) {
            for (ModifiedAsset var6 : var4.getRecentlyModifiedAssets().values()) {
               var1.add(var6.toAssetInfoPacket(var3.getKey()));
            }
         }
      }

      class="kw">return new AssetEditorLastModifiedAssets(var1.toArray(new AssetInfo[0]));
   }

   @Nullable
   class="kw">private DataSource getValidatedDataSource(@Nonnull EditorClient var1, @Nonnull AssetPath var2, int var3) {
      DataSource var4 = this.getDataSourceForPath(var2);
      if (var4 == null) {
         var1.sendFailureReply(var3, Messages.UNKNOWN_ASSET_PACK);
         class="kw">return null;
      } else if (!this.isValidPath(var4, var2)) {
         var1.sendFailureReply(var3, Messages.DIRECTORY_OUTSIDE_ASSET_TYPE_ROOT);
         class="kw">return null;
      } else {
         class="kw">return this.assetTypeRegistry.tryGetAssetTypeHandler(var2.path(), var1, var3) == null ? null : var4;
      }
   }

   @Nullable
   class="kw">private Schema getSchemaById(@Nullable String var1) {
      class="kw">return this.getSchema(var1 + ".json");
   }

   boolean isValidPath(@Nonnull DataSource var1, @Nonnull AssetPath var2) {
      String var3 = PathUtil.toUnixPathString(var2.path());
      Path var4 = var1.getRootPath();
      Path var5 = var4.resolve(var3).toAbsolutePath().normalize();
      if (!var5.startsWith(var4)) {
         class="kw">return false;
      }

      String var6 = PathUtil.toUnixPathString(var4.relativize(var5));
      class="kw">return var6.equals(var3);
   }

   class="kw">static {
      new SchemaContext();
   }

   class="kw">public class="kw">static class AssetToDiscard {
      class="kw">public class="kw">final AssetPath path;
      @Nullable
      class="kw">public class="kw">final Instant lastModificationDate;

      class="kw">public AssetToDiscard(AssetPath var1, @Nullable String var2) {
         this.path = var1;
         if (var2 != null) {
            this.lastModificationDate = Instant.parse(var2);
         } else {
            this.lastModificationDate = null;
         }
      }
   }

   enum DiscardResult {
      FAILED,
      SUCCEEDED,
      SUCCEEDED_COMMON_ASSETS_CHANGED;

      DiscardResult() {
      }
   }

   enum InitState {
      NOT_INITIALIZED,
      INITIALIZING,
      INITIALIZED;

      InitState() {
      }
   }
}