Universe class
Пакет: com.hypixel.hytale.server.core.universe
Файл: com/hypixel/hytale/server/core/universe/Universe.java
extends: JavaPlugin
implements: IMessageReceiver, MetricProvider
Поля (126)
| Модификаторы | Тип | Имя |
|---|---|---|
|
|
LEGACY_BLOCK_ID_MAP |
|
|
instance |
|
|
return |
|
|
return |
|
|
return |
|
|
return |
|
Path |
var0 |
|
|
var0 |
|
|
var0 |
|
Path |
var1 |
|
Store |
var1 |
|
int |
var1 |
|
EventRegistry |
var1 |
|
HytaleServerConfig |
var1 |
|
ShutdownReason |
var1 |
|
Iterator |
var1 |
|
HytaleServerConfig |
var1 |
|
Player |
var1 |
|
OptionSet |
var1 |
|
DateTimeFormatter |
var10 |
|
long |
var10 |
|
PlayerConfigData |
var10 |
|
CompletableFuture |
var10 |
|
BsonDocument |
var11 |
|
AtomicInteger |
var11 |
|
EntityTrackerSystems.EntityViewer |
var11 |
|
|
var11 |
|
String |
var12 |
|
List |
var12 |
|
int |
var12 |
|
PlayerRef |
var12 |
|
AtomicReference |
var13 |
|
AtomicInteger |
var13 |
|
int |
var13 |
|
String |
var13 |
|
String |
var14 |
|
int |
var14 |
|
Options.RecoveryMode |
var14 |
|
World |
var14 |
|
PlayerConnectEvent |
var15 |
|
World |
var16 |
|
CompletableFuture |
var17 |
|
BackupConfig |
var2 |
|
Void |
var2 |
|
UniverseResources |
var2 |
|
UniverseResources |
var2 |
|
ComponentRegistryProxy |
var2 |
|
UniverseResources |
var2 |
|
String |
var2 |
|
|
var2 |
|
FormattedMessage |
var2 |
|
World |
var2 |
|
Path |
var2 |
|
Path |
var2 |
|
Path |
var2 |
|
String |
var2 |
|
String |
var2 |
|
IEventDispatcher |
var2 |
|
WorldConfigProvider.Default |
var23 |
|
ObjectArrayList |
var24 |
|
boolean |
var26 |
|
int |
var3 |
|
ComponentRegistryProxy |
var3 |
|
AtomicBoolean |
var3 |
|
String |
var3 |
|
ChunkStore |
var3 |
|
World |
var3 |
|
String |
var3 |
|
Ref |
var3 |
|
String |
var31 |
|
Path |
var33 |
|
IntIntPair |
var34 |
|
CommandRegistry |
var4 |
|
PrepareUniverseEvent |
var4 |
|
IChunkLoader |
var4 |
|
Path |
var4 |
|
World |
var4 |
|
String |
var4 |
|
RemoveWorldEvent |
var4 |
|
World |
var4 |
|
World |
var4 |
|
ResourceType |
var5 |
|
WorldConfigProvider |
var5 |
|
|
var5 |
|
WorldConfig |
var5 |
|
IChunkSaver |
var5 |
|
Map |
var5 |
|
AddWorldEvent |
var5 |
|
Player |
var5 |
|
UUID |
var5 |
|
Path |
var6 |
|
LongList |
var6 |
|
int |
var6 |
|
BuilderCodec |
var6 |
|
PluginManager |
var6 |
|
World |
var6 |
|
GamePacketHandler |
var6 |
|
Player |
var6 |
|
EntityTrackerSystems.EntityViewer |
var6 |
|
|
var6 |
|
Path |
var7 |
|
IChunkLoader |
var7 |
|
|
var7 |
|
|
var7 |
|
String |
var7 |
|
IWorldGenProvider |
var7 |
|
World |
var7 |
|
CompletableFuture |
var7 |
|
ChunkTracker |
var7 |
|
World |
var7 |
|
|
var7 |
|
|
var7 |
|
Map |
var8 |
|
Path |
var8 |
|
|
var8 |
|
String |
var8 |
|
BuilderCodec |
var8 |
|
PlayerRef |
var8 |
|
GamePacketHandler |
var8 |
|
Path |
var9 |
|
CompletableFuture |
var9 |
|
double |
var9 |
|
IChunkStorageProvider |
var9 |
|
Player |
var9 |
|
CompletableFuture |
var9 |
|
Player |
var9 |
Методы (103)
| Модификаторы | Возврат | Сигнатура |
|---|---|---|
abstract |
throw new |
CompletionExceptionthrow new CompletionException(var2xx) |
abstract |
throw new |
ConcurrentModificationExceptionthrow new ConcurrentModificationException("World with name " + var1 + " already exists but didn't before! Looks like you have a race condition.") |
abstract |
throw new |
IllegalArgumentExceptionthrow new IllegalArgumentException("World " + var1 + " already exists!") |
abstract |
throw new |
IllegalArgumentExceptionthrow new IllegalArgumentException("World " + var1 + " already exists on disk!") |
abstract |
throw new |
IllegalArgumentExceptionthrow new IllegalArgumentException("Unknown generatorType '" + var2 + "'") |
abstract |
throw new |
IllegalArgumentExceptionthrow new IllegalArgumentException("Unknown chunkStorageType '" + var3 + "'") |
abstract |
throw new |
IllegalArgumentExceptionthrow new IllegalArgumentException("World " + var1 + " contains invalid characters!") |
abstract |
throw new |
IllegalArgumentExceptionthrow new IllegalArgumentException("Invalid path") |
abstract |
throw new |
IllegalArgumentExceptionthrow new IllegalArgumentException("World " + var1 + " already loaded!") |
abstract |
throw new |
IllegalArgumentExceptionthrow new IllegalArgumentException("World " + var1 + " does not exist!") |
abstract |
throw new |
IllegalStateExceptionthrow new IllegalStateException("Universe resources are not loaded yet") |
abstract |
throw new |
IllegalStateExceptionthrow new IllegalStateException("Server config is not loaded!") |
abstract |
throw new |
IllegalStateExceptionthrow new IllegalStateException("Missing plugin") |
abstract |
throw new |
NullPointerExceptionthrow new NullPointerException("World " + var1 + " doesn't exist!") |
abstract |
throw new |
RuntimeExceptionthrow new RuntimeException("Failed to create universe directory", var4) |
abstract |
throw new |
RuntimeExceptionthrow new RuntimeException("Failed to load Worlds", var21) |
abstract |
throw new |
RuntimeExceptionthrow new RuntimeException("Error deleting world directory on universe start", var4) |
abstract |
throw new |
RuntimeExceptionthrow new RuntimeException("Exception when adding player to universe:", var0) |
abstract |
throw new |
RuntimeExceptionthrow new RuntimeException("Exception when adding player to universe:", var4x) |
abstract |
throw new |
UnsupportedOperationExceptionthrow new UnsupportedOperationException() |
abstract |
throw new |
WorldLoadCancelledExceptionthrow new WorldLoadCancelledException() |
public |
void |
broadcastPacketvoid broadcastPacket(@Nonnull ToClientPacket var1) |
public |
void |
broadcastPacketvoid broadcastPacket(@Nonnull ToClientPacket... var1) |
public |
void |
broadcastPacketNoCachevoid broadcastPacketNoCache(@Nonnull ToClientPacket var1) |
static |
void |
collectBackupZipsvoid collectBackupZips(@Nonnull Path var0, @Nonnull DateTimeFormatter var1, @Nonnull List<Path> var2) |
abstract |
|
collectBackupZips collectBackupZips(var8, var10, var12) |
public |
void |
disconnectAllPLayersvoid disconnectAllPLayers() |
private |
void |
finalizePlayerRemovalvoid finalizePlayerRemoval(@Nonnull PlayerRef var1) |
private |
void |
flushUniverseResourcesForShutdownvoid flushUniverseResourcesForShutdown() |
|
|
for for(Path var32 : var28) |
|
|
for for(Path var29 : var25) |
static |
Universe |
getUniverse get() |
public |
int |
getPlayerCountint getPlayerCount() |
public |
PlayerStorage |
getPlayerStoragePlayerStorage getPlayerStorage() |
public |
StorageManager |
getStorageManagerStorageManager getStorageManager() |
public |
CompletableFuture<Void> |
getUniverseReadyCompletableFuture<Void> getUniverseReady() |
public |
WorldConfigProvider |
getWorldConfigProviderWorldConfigProvider getWorldConfigProvider() |
static |
Path |
getWorldGenPathPath getWorldGenPath() |
public |
ResourceType<ChunkStore, WorldMarkersResource> |
getWorldMarkersResourceTypeResourceType<ChunkStore, WorldMarkersResource> getWorldMarkersResourceType() |
public |
Path |
getWorldsDeletedPathPath getWorldsDeletedPath() |
public |
Path |
getWorldsPathPath getWorldsPath() |
|
|
if if(var2x != null) |
|
|
if if(var1 == null) |
|
|
if if(var2xx != null) |
|
|
if if(var1 == 0) |
|
|
if if(var2 == null) |
|
|
if if(var2 == null) |
|
|
if if(var1 == null) |
|
|
if if(var3x != null) |
|
|
if if(var5 == null) |
|
|
if if(var33 != null) |
|
|
if if(var33 != null) |
|
|
if if(var33 != null && var5 != null) |
|
|
if if(var4x == null) |
|
|
if if(var4 != null && var5 != null) |
|
|
if if(var8 == null) |
|
|
if if(var2 != null) |
|
|
if if(var7 != null) |
|
|
if if(var14 == null) |
|
|
if if(var4x == null) |
|
|
if if(var6 % 100 == 0 || var6 == var9) |
|
|
if if(var11 != null) |
|
|
if if(this.universeResourcesFlushTask != null) |
|
|
if if(this.universeResources != null) |
|
|
if if(var6 == null) |
|
|
if if(var8 == null) |
|
|
if if(var2 == null) |
|
|
if if(var5 != null) |
|
|
if if(var6 != null) |
|
|
if if(var7 != null) |
|
|
if if(var3x != null) |
|
|
if if(var1 == null) |
|
|
if if(var3 == null) |
|
|
if if(var4 == null) |
|
|
if if(var11 != null) |
|
|
if if(var12 != null) |
|
|
if if(var16 == null) |
|
|
if if(var13 != null && var14 == null) |
|
|
if if(var17 == null) |
|
|
if if(var5x != null) |
|
|
if if(var5 != null) |
|
|
if if(var1 != null) |
|
|
if if(var2x != null) |
|
|
if if(var3x != null) |
|
|
if if(Constants.SINGLEPLAYER) |
|
|
if if(var3 == null) |
|
|
if if(var6 != null) |
public |
boolean |
isSavingLockedboolean isSavingLocked() |
public |
boolean |
isWorldLoadableboolean isWorldLoadable(@Nonnull String var1) |
private |
CompletableFuture<Void> |
loadWorldFromStartCompletableFuture<Void> loadWorldFromStart(@Nonnull Path var1, @Nonnull String var2) |
public |
void |
lockSavingvoid lockSaving() |
public |
void |
removePlayervoid removePlayer(@Nonnull PlayerRef var1) |
public |
boolean |
removeWorldboolean removeWorld(@Nonnull String var1) |
public |
void |
removeWorldExceptionallyvoid removeWorldExceptionally(@Nonnull String var1, Map<UUID, PlayerRef> var2) |
public |
void |
setPlayerStoragevoid setPlayerStorage(@Nonnull PlayerStorage var1) |
public |
void |
shutdownAllWorldsvoid shutdownAllWorlds() |
abstract |
|
super super(var1) |
|
return |
switchreturn switch(var14) |
public |
void |
unlockSavingvoid unlockSaving() |
public |
Path |
validateWorldPathPath validateWorldPath(@Nonnull String var1) |
private |
CompletableFuture<Void> |
verifyAllChunksCompletableFuture<Void> verifyAllChunks(@Nonnull World var1,
@Nonnull IChunkLoader var2,
@Nonnull IChunkSaver var3,
@Nullable IChunkLoader var4,
@Nonnull LongIterator var5,
@Nonnull AtomicInteger var6,
@Nonnull AtomicInteger var7,
int var8) |
private |
void |
verifyNextChunkvoid verifyNextChunk(@Nonnull CompletableFuture<Void> var1,
@Nonnull World var2,
@Nonnull IChunkLoader var3,
@Nonnull IChunkSaver var4,
@Nullable IChunkLoader var5,
@Nonnull LongIterator var6,
@Nonnull AtomicInteger var7,
@Nonnull AtomicInteger var8,
int var9) |
private |
CompletableFuture<IntIntPair> |
verifyWorldCompletableFuture<IntIntPair> verifyWorld(World var1, @Nullable Path var2) |
Исходный код
Показать/скрыть
class="kw">package com.hypixel.hytale.server.core.universe;
class="kw">import com.hypixel.hytale.assetstore.AssetRegistry;
class="kw">import com.hypixel.hytale.codec.Codec;
class="kw">import com.hypixel.hytale.codec.builder.BuilderCodec;
class="kw">import com.hypixel.hytale.codec.codecs.array.ArrayCodec;
class="kw">import com.hypixel.hytale.codec.lookup.Priority;
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.SemverRange;
class="kw">import com.hypixel.hytale.common.util.CompletableFutureUtil;
class="kw">import com.hypixel.hytale.common.util.PathUtil;
class="kw">import com.hypixel.hytale.component.ComponentRegistryProxy;
class="kw">import com.hypixel.hytale.component.ComponentType;
class="kw">import com.hypixel.hytale.component.Holder;
class="kw">import com.hypixel.hytale.component.Ref;
class="kw">import com.hypixel.hytale.component.ResourceType;
class="kw">import com.hypixel.hytale.component.Store;
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.math.util.ChunkUtil;
class="kw">import com.hypixel.hytale.math.util.MathUtil;
class="kw">import com.hypixel.hytale.math.vector.Transform;
class="kw">import com.hypixel.hytale.metrics.MetricProvider;
class="kw">import com.hypixel.hytale.metrics.MetricResults;
class="kw">import com.hypixel.hytale.metrics.MetricsRegistry;
class="kw">import com.hypixel.hytale.protocol.FormattedMessage;
class="kw">import com.hypixel.hytale.protocol.ToClientPacket;
class="kw">import com.hypixel.hytale.protocol.io.ChannelConnection;
class="kw">import com.hypixel.hytale.protocol.packets.setup.ServerTags;
class="kw">import com.hypixel.hytale.server.core.Constants;
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.NameMatching;
class="kw">import com.hypixel.hytale.server.core.Options;
class="kw">import com.hypixel.hytale.server.core.ShutdownReason;
class="kw">import com.hypixel.hytale.server.core.auth.PlayerAuthentication;
class="kw">import com.hypixel.hytale.server.core.command.system.CommandManager;
class="kw">import com.hypixel.hytale.server.core.command.system.CommandRegistry;
class="kw">import com.hypixel.hytale.server.core.config.BackupConfig;
class="kw">import com.hypixel.hytale.server.core.cosmetics.CosmeticsModule;
class="kw">import com.hypixel.hytale.server.core.entity.UUIDComponent;
class="kw">import com.hypixel.hytale.server.core.entity.entities.Player;
class="kw">import com.hypixel.hytale.server.core.entity.entities.player.data.PlayerConfigData;
class="kw">import com.hypixel.hytale.server.core.event.events.PrepareUniverseEvent;
class="kw">import com.hypixel.hytale.server.core.event.events.ShutdownEvent;
class="kw">import com.hypixel.hytale.server.core.event.events.player.PlayerConnectEvent;
class="kw">import com.hypixel.hytale.server.core.event.events.player.PlayerDisconnectEvent;
class="kw">import com.hypixel.hytale.server.core.io.ProtocolVersion;
class="kw">import com.hypixel.hytale.server.core.io.handlers.game.GamePacketHandler;
class="kw">import com.hypixel.hytale.server.core.modules.entity.component.ModelComponent;
class="kw">import com.hypixel.hytale.server.core.modules.entity.component.MovementAudioComponent;
class="kw">import com.hypixel.hytale.server.core.modules.entity.component.PositionDataComponent;
class="kw">import com.hypixel.hytale.server.core.modules.entity.player.ChunkTracker;
class="kw">import com.hypixel.hytale.server.core.modules.entity.player.NetworkTickResource;
class="kw">import com.hypixel.hytale.server.core.modules.entity.player.NetworkTickSystem;
class="kw">import com.hypixel.hytale.server.core.modules.entity.player.PlayerConnectionFlushSystem;
class="kw">import com.hypixel.hytale.server.core.modules.entity.player.PlayerPingSystem;
class="kw">import com.hypixel.hytale.server.core.modules.entity.player.PlayerSkinComponent;
class="kw">import com.hypixel.hytale.server.core.modules.entity.tracker.EntityTrackerSystems;
class="kw">import com.hypixel.hytale.server.core.modules.singleplayer.SingleplayerModule;
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.receiver.IMessageReceiver;
class="kw">import com.hypixel.hytale.server.core.universe.playerdata.PlayerStorage;
class="kw">import com.hypixel.hytale.server.core.universe.resources.UniverseResourceType;
class="kw">import com.hypixel.hytale.server.core.universe.resources.UniverseResources;
class="kw">import com.hypixel.hytale.server.core.universe.system.PlayerRefAddedSystem;
class="kw">import com.hypixel.hytale.server.core.universe.system.WorldConfigSaveSystem;
class="kw">import com.hypixel.hytale.server.core.universe.world.World;
class="kw">import com.hypixel.hytale.server.core.universe.world.WorldConfig;
class="kw">import com.hypixel.hytale.server.core.universe.world.WorldConfigProvider;
class="kw">import com.hypixel.hytale.server.core.universe.world.commands.SetTickingCommand;
class="kw">import com.hypixel.hytale.server.core.universe.world.commands.block.BlockCommand;
class="kw">import com.hypixel.hytale.server.core.universe.world.commands.block.BlockSelectCommand;
class="kw">import com.hypixel.hytale.server.core.universe.world.commands.world.WorldCommand;
class="kw">import com.hypixel.hytale.server.core.universe.world.events.AddWorldEvent;
class="kw">import com.hypixel.hytale.server.core.universe.world.events.AllWorldsLoadedEvent;
class="kw">import com.hypixel.hytale.server.core.universe.world.events.RemoveWorldEvent;
class="kw">import com.hypixel.hytale.server.core.universe.world.spawn.FitToHeightMapSpawnProvider;
class="kw">import com.hypixel.hytale.server.core.universe.world.spawn.GlobalSpawnProvider;
class="kw">import com.hypixel.hytale.server.core.universe.world.spawn.ISpawnProvider;
class="kw">import com.hypixel.hytale.server.core.universe.world.spawn.IndividualSpawnProvider;
class="kw">import com.hypixel.hytale.server.core.universe.world.storage.ChunkStore;
class="kw">import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
class="kw">import com.hypixel.hytale.server.core.universe.world.storage.IChunkLoader;
class="kw">import com.hypixel.hytale.server.core.universe.world.storage.IChunkSaver;
class="kw">import com.hypixel.hytale.server.core.universe.world.storage.component.ChunkSavingSystems;
class="kw">import com.hypixel.hytale.server.core.universe.world.storage.provider.BackupChunkLoader;
class="kw">import com.hypixel.hytale.server.core.universe.world.storage.provider.DefaultChunkStorageProvider;
class="kw">import com.hypixel.hytale.server.core.universe.world.storage.provider.EmptyChunkStorageProvider;
class="kw">import com.hypixel.hytale.server.core.universe.world.storage.provider.IChunkStorageProvider;
class="kw">import com.hypixel.hytale.server.core.universe.world.storage.provider.IndexedStorageChunkStorageProvider;
class="kw">import com.hypixel.hytale.server.core.universe.world.storage.provider.MigrationChunkStorageProvider;
class="kw">import com.hypixel.hytale.server.core.universe.world.storage.provider.RocksDbChunkStorageProvider;
class="kw">import com.hypixel.hytale.server.core.universe.world.storage.resources.DefaultResourceStorageProvider;
class="kw">import com.hypixel.hytale.server.core.universe.world.storage.resources.DiskResourceStorageProvider;
class="kw">import com.hypixel.hytale.server.core.universe.world.storage.resources.EmptyResourceStorageProvider;
class="kw">import com.hypixel.hytale.server.core.universe.world.storage.resources.IResourceStorageProvider;
class="kw">import com.hypixel.hytale.server.core.universe.world.system.WorldPregenerateSystem;
class="kw">import com.hypixel.hytale.server.core.universe.world.worldgen.provider.CubicTestWorldGenProvider;
class="kw">import com.hypixel.hytale.server.core.universe.world.worldgen.provider.DummyWorldGenProvider;
class="kw">import com.hypixel.hytale.server.core.universe.world.worldgen.provider.FlatWorldGenProvider;
class="kw">import com.hypixel.hytale.server.core.universe.world.worldgen.provider.IWorldGenProvider;
class="kw">import com.hypixel.hytale.server.core.universe.world.worldgen.provider.VoidWorldGenProvider;
class="kw">import com.hypixel.hytale.server.core.universe.world.worldmap.markers.worldstore.WorldMarkersResource;
class="kw">import com.hypixel.hytale.server.core.universe.world.worldmap.provider.DisabledWorldMapProvider;
class="kw">import com.hypixel.hytale.server.core.universe.world.worldmap.provider.IWorldMapProvider;
class="kw">import com.hypixel.hytale.server.core.universe.world.worldmap.provider.chunk.WorldGenWorldMapProvider;
class="kw">import com.hypixel.hytale.server.core.util.AssetUtil;
class="kw">import com.hypixel.hytale.server.core.util.BsonUtil;
class="kw">import com.hypixel.hytale.server.core.util.backup.BackupTask;
class="kw">import com.hypixel.hytale.server.core.util.io.FileUtil;
class="kw">import com.hypixel.hytale.sneakythrow.SneakyThrow;
class="kw">import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
class="kw">import it.unimi.dsi.fastutil.ints.IntIntPair;
class="kw">import it.unimi.dsi.fastutil.longs.LongIterator;
class="kw">import it.unimi.dsi.fastutil.longs.LongList;
class="kw">import it.unimi.dsi.fastutil.objects.ObjectArrayList;
class="kw">import java.io.IOException;
class="kw">import java.nio.file.DirectoryStream;
class="kw">import java.nio.file.Files;
class="kw">import java.nio.file.Path;
class="kw">import java.nio.file.StandardCopyOption;
class="kw">import java.time.LocalDateTime;
class="kw">import java.time.format.DateTimeFormatter;
class="kw">import java.time.format.DateTimeParseException;
class="kw">import java.util.ArrayList;
class="kw">import java.util.Collection;
class="kw">import java.util.Collections;
class="kw">import java.util.Comparator;
class="kw">import java.util.ConcurrentModificationException;
class="kw">import java.util.Iterator;
class="kw">import java.util.List;
class="kw">import java.util.Locale;
class="kw">import java.util.Map;
class="kw">import java.util.Objects;
class="kw">import java.util.UUID;
class="kw">import java.util.Map.Entry;
class="kw">import java.util.concurrent.CompletableFuture;
class="kw">import java.util.concurrent.CompletionException;
class="kw">import java.util.concurrent.CompletionStage;
class="kw">import java.util.concurrent.ConcurrentHashMap;
class="kw">import java.util.concurrent.ScheduledFuture;
class="kw">import java.util.concurrent.TimeUnit;
class="kw">import java.util.concurrent.TimeoutException;
class="kw">import java.util.concurrent.atomic.AtomicBoolean;
class="kw">import java.util.concurrent.atomic.AtomicInteger;
class="kw">import java.util.concurrent.atomic.AtomicReference;
class="kw">import java.util.function.BiPredicate;
class="kw">import java.util.function.Function;
class="kw">import java.util.logging.Level;
class="kw">import java.util.stream.Stream;
class="kw">import javax.annotation.CheckReturnValue;
class="kw">import javax.annotation.Nonnull;
class="kw">import javax.annotation.Nullable;
class="kw">import joptsimple.OptionSet;
class="kw">import org.bson.BsonDocument;
class="kw">import org.bson.BsonValue;
class="kw">public class Universe class="kw">extends JavaPlugin class="kw">implements IMessageReceiver, MetricProvider {
@Nonnull
class="kw">public class="kw">static class="kw">final PluginManifest MANIFEST = PluginManifest.corePlugin(Universe.class).build();
@Nonnull
class="kw">private class="kw">static Map<Integer, String> LEGACY_BLOCK_ID_MAP = Collections.emptyMap();
@Nonnull
class="kw">public class="kw">static class="kw">final MetricsRegistry<Universe> METRICS_REGISTRY = new MetricsRegistry<Universe>()
.register("Worlds", var0 -> var0.getWorlds().values().toArray(World[]::new), new ArrayCodec<>(World.METRICS_REGISTRY, World[]::new))
.register("PlayerCount", Universe::getPlayerCount, Codec.INTEGER);
class="kw">private class="kw">static Universe instance;
class="kw">private ComponentType<EntityStore, PlayerRef> playerRefComponentType;
@Nonnull
class="kw">private class="kw">final Path path = Constants.UNIVERSE_PATH;
class="kw">private class="kw">final Path worldsPath = this.path.resolve("worlds");
class="kw">private class="kw">final Path worldsDeletedPath = this.worldsPath.resolveSibling("worlds-deleted");
@Nonnull
class="kw">private class="kw">final Map<UUID, PlayerRef> playersByUuid = new ConcurrentHashMap<>();
@Nonnull
class="kw">private class="kw">final Collection<PlayerRef> players = Collections.unmodifiableCollection(this.playersByUuid.values());
@Nonnull
class="kw">private class="kw">final Map<String, World> worlds = new ConcurrentHashMap<>();
@Nonnull
class="kw">private class="kw">final Map<UUID, World> worldsByUuid = new ConcurrentHashMap<>();
@Nonnull
class="kw">private class="kw">final Map<String, World> unmodifiableWorlds = Collections.unmodifiableMap(this.worlds);
class="kw">private PlayerStorage playerStorage;
class="kw">private WorldConfigProvider worldConfigProvider;
class="kw">private ResourceType<ChunkStore, WorldMarkersResource> worldMarkersResourceType;
class="kw">private CompletableFuture<Void> universeReady;
class="kw">private class="kw">final AtomicBoolean isBackingUp = new AtomicBoolean(false);
class="kw">private class="kw">final StorageManager storageManager = new StorageManager(this::isSavingLocked);
class="kw">private class="kw">final WorldCrashRecoveryHandler worldCrashRecoveryHandler = new WorldCrashRecoveryHandler(this);
class="kw">private class="kw">final AtomicInteger savingLocks = new AtomicInteger(0);
class="kw">private class="kw">volatile UniverseResources universeResources;
class="kw">private class="kw">static class="kw">final long RESOURCE_FLUSH_INTERVAL_SECONDS = 10L;
class="kw">private class="kw">static class="kw">final long RESOURCE_FLUSH_SHUTDOWN_TIMEOUT_SECONDS = 30L;
class="kw">private ScheduledFuture<?> universeResourcesFlushTask;
class="kw">public class="kw">static Universe get() {
class="kw">return instance;
}
@Nonnull
class="kw">public class="kw">static <T> UniverseResourceType<T> registerResource(@Nonnull Class<T> var0, @Nonnull String var1, @Nonnull BuilderCodec<T> var2) {
class="kw">return UniverseResources.register(var0, var1, var2);
}
class="kw">public Universe(@Nonnull JavaPluginInit var1) {
super(var1);
instance = this;
if (!Files.isDirectory(this.path) && !Options.isBare()) {
try {
Files.createDirectories(this.path);
} catch (IOException var4) {
throw new RuntimeException("Failed to create universe directory", var4);
}
}
BackupConfig var2 = HytaleServer.get().getConfig().getBackupConfig();
if (var2.isConfigured()) {
int var3 = var2.getFrequencyMinutes();
this.getLogger().at(Level.INFO).log("Scheduled backup to run every %d minute(s)", var3);
HytaleServer.SCHEDULED_EXECUTOR.scheduleWithFixedDelay(() -> {
if (!this.isBackingUp.compareAndSet(false, true)) {
this.getLogger().at(Level.WARNING).log("Skipping scheduled backup: previous backup still in progress");
} else {
try {
this.getLogger().at(Level.INFO).log("Backing up universe...");
this.runBackup().whenComplete((var1x, var2x) -> {
this.isBackingUp.set(false);
if (var2x != null) {
((HytaleLogger.Api)this.getLogger().at(Level.SEVERE).withCause(var2x)).log("Scheduled backup failed");
} else {
this.getLogger().at(Level.INFO).log("Completed scheduled backup.");
}
});
} catch (Exception var2) {
this.isBackingUp.set(false);
((HytaleLogger.Api)this.getLogger().at(Level.SEVERE).withCause(var2)).log("Error backing up universe");
}
}
}, var3, var3, TimeUnit.MINUTES);
}
}
@Nonnull
class="kw">public CompletableFuture<Void> runBackup() {
Path var1 = HytaleServer.get().getConfig().getBackupConfig().getDirectory();
if (var1 == null) {
class="kw">return CompletableFuture.failedFuture(new IllegalStateException("Backup directory not configured"));
} else {
class="kw">return this.universeResources == null ? this.runLockedBackup(var1) : this.universeResources.flushAll().exceptionally(var1x -> {
((HytaleLogger.Api)this.getLogger().at(Level.SEVERE).withCause(var1x)).log("Failed to flush universe resources before the backup");
class="kw">return null;
}).thenCompose(var2 -> this.runLockedBackup(var1));
}
}
@Nonnull
class="kw">private CompletableFuture<Void> runLockedBackup(@Nonnull Path var1) {
this.lockSaving();
class="kw">return this.storageManager
.pendingOperations()
.thenCompose(
var2 -> CompletableFuture.allOf(this.worlds.values().stream().map(var0 -> CompletableFuture.<ChunkSavingSystems.Data>supplyAsync(() -> {
Store var1 = var0.getChunkStore().getStore();
Void var2 = var1.getResource(ChunkStore.SAVE_RESOURCE);
var0.getChunkStore().pauseBackgroundSaving(var2);
var0.lockSaving();
class="kw">return var2;
}, var0).thenCompose(ChunkSavingSystems.Data::waitForSavingChunks)).toArray(CompletableFuture[]::new))
.thenCompose(
var2x -> BackupTask.start(this.path, var1)
.handle(
(var1x, var2xx) -> CompletableFuture.allOf(
this.worlds
.values()
.stream()
.map(
var0 -> CompletableFuture.<CompletableFuture<Void>>supplyAsync(() -> var0.getChunkStore().resumeBackgroundSaving(), var0)
.thenCompose(var0x -> (CompletionStage<Void>)var0x)
.whenCompleteAsync((var1xx, var2xxx) -> var0.unlockSaving(), var0)
)
.toArray(CompletableFuture[]::new)
)
.thenApply(var1xx -> {
if (var2xx != null) {
throw new CompletionException(var2xx);
} else {
class="kw">return null;
}
})
)
.thenCompose(var0 -> (CompletionStage<Void>)var0)
)
)
.whenComplete((var1x, var2) -> this.unlockSaving());
}
class="kw">public boolean isSavingLocked() {
class="kw">return this.savingLocks.get() > 0;
}
class="kw">public void lockSaving() {
this.savingLocks.incrementAndGet();
}
class="kw">public void unlockSaving() {
int var1 = this.savingLocks.decrementAndGet();
assert var1 >= 0 : "savingLocks underflow";
if (var1 == 0) {
this.storageManager.onSavingRelease();
}
}
@Nonnull
class="kw">public <T> T getResource(@Nonnull UniverseResourceType<T> var1) {
UniverseResources var2 = this.universeResources;
if (var2 == null) {
throw new IllegalStateException("Universe resources are not loaded yet");
} else {
class="kw">return var2.get(var1);
}
}
@Nonnull
class="kw">public CompletableFuture<Void> flushResource(@Nonnull UniverseResourceType<?> var1) {
UniverseResources var2 = this.universeResources;
if (var2 == null) {
throw new IllegalStateException("Universe resources are not loaded yet");
} else {
class="kw">return var2.flush(var1);
}
}
@Override
class="kw">protected void setup() {
EventRegistry var1 = this.getEventRegistry();
ComponentRegistryProxy var2 = this.getChunkStoreRegistry();
ComponentRegistryProxy var3 = this.getEntityStoreRegistry();
CommandRegistry var4 = this.getCommandRegistry();
var1.register((short)-48, ShutdownEvent.class, var1x -> this.disconnectAllPLayers());
var1.register((short)-32, ShutdownEvent.class, var1x -> this.shutdownAllWorlds());
var1.register((short)-24, ShutdownEvent.class, var1x -> this.flushUniverseResourcesForShutdown());
var1.registerGlobal(RemoveWorldEvent.class, this.worldCrashRecoveryHandler::onRemoveWorld);
ISpawnProvider.CODEC.register("Global", GlobalSpawnProvider.class, GlobalSpawnProvider.CODEC);
ISpawnProvider.CODEC.register("Individual", IndividualSpawnProvider.class, IndividualSpawnProvider.CODEC);
ISpawnProvider.CODEC.register("FitToHeightMap", FitToHeightMapSpawnProvider.class, FitToHeightMapSpawnProvider.CODEC);
IWorldGenProvider.CODEC.register("Flat", FlatWorldGenProvider.class, FlatWorldGenProvider.CODEC);
IWorldGenProvider.CODEC.register("Dummy", DummyWorldGenProvider.class, DummyWorldGenProvider.CODEC);
IWorldGenProvider.CODEC.register(Priority.DEFAULT, "Void", VoidWorldGenProvider.class, VoidWorldGenProvider.CODEC);
IWorldGenProvider.CODEC.register("CubicTest", CubicTestWorldGenProvider.class, CubicTestWorldGenProvider.CODEC);
IWorldMapProvider.CODEC.register("Disabled", DisabledWorldMapProvider.class, DisabledWorldMapProvider.CODEC);
IWorldMapProvider.CODEC.register(Priority.DEFAULT, "WorldGen", WorldGenWorldMapProvider.class, WorldGenWorldMapProvider.CODEC);
IChunkStorageProvider.CODEC.register(Priority.DEFAULT, "Hytale", DefaultChunkStorageProvider.class, DefaultChunkStorageProvider.CODEC);
IChunkStorageProvider.CODEC.register("Migration", MigrationChunkStorageProvider.class, MigrationChunkStorageProvider.CODEC);
IChunkStorageProvider.CODEC.register("IndexedStorage", IndexedStorageChunkStorageProvider.class, IndexedStorageChunkStorageProvider.CODEC);
IChunkStorageProvider.CODEC.register("RocksDb", RocksDbChunkStorageProvider.class, RocksDbChunkStorageProvider.CODEC);
IChunkStorageProvider.CODEC.register("Empty", EmptyChunkStorageProvider.class, EmptyChunkStorageProvider.CODEC);
IResourceStorageProvider.CODEC.register(Priority.DEFAULT, "Hytale", DefaultResourceStorageProvider.class, DefaultResourceStorageProvider.CODEC);
IResourceStorageProvider.CODEC.register("Disk", DiskResourceStorageProvider.class, DiskResourceStorageProvider.CODEC);
IResourceStorageProvider.CODEC.register("Empty", EmptyResourceStorageProvider.class, EmptyResourceStorageProvider.CODEC);
this.worldMarkersResourceType = var2.registerResource(WorldMarkersResource.class, "SharedUserMapMarkers", WorldMarkersResource.CODEC);
var2.registerSystem(new WorldPregenerateSystem());
var3.registerSystem(new WorldConfigSaveSystem());
this.playerRefComponentType = var3.registerComponent(PlayerRef.class, () -> {
throw new UnsupportedOperationException();
});
var3.registerSystem(new PlayerPingSystem());
ResourceType var5 = var3.registerResource(NetworkTickResource.class, NetworkTickResource::new);
var3.registerSystem(new NetworkTickSystem(var5));
var3.registerSystem(new PlayerConnectionFlushSystem(this.playerRefComponentType));
var3.registerSystem(new PlayerRefAddedSystem(this.playerRefComponentType));
var4.registerCommand(new SetTickingCommand());
var4.registerCommand(new BlockCommand());
var4.registerCommand(new BlockSelectCommand());
var4.registerCommand(new WorldCommand());
}
@Override
class="kw">protected void start() {
HytaleServerConfig var1 = HytaleServer.get().getConfig();
if (var1 == null) {
throw new IllegalStateException("Server config is not loaded!");
}
UniverseResources var2 = new UniverseResources(var1.getUniverseResourceStorageProvider().getResourceStorage());
var2.load(UniverseResources.registeredTypes());
this.universeResources = var2;
if (!Options.isBare()) {
AtomicBoolean var3 = new AtomicBoolean(false);
this.universeResourcesFlushTask = HytaleServer.SCHEDULED_EXECUTOR.scheduleWithFixedDelay(() -> {
if (var3.compareAndSet(false, true)) {
try {
this.universeResources.flushAll().whenComplete((var2x, var3x) -> {
var3.set(false);
if (var3x != null) {
((HytaleLogger.Api)this.getLogger().at(Level.SEVERE).withCause(var3x)).log("Failed to flush universe resources");
}
});
} catch (Exception var3) {
var3.set(false);
((HytaleLogger.Api)this.getLogger().at(Level.SEVERE).withCause(var3)).log("Failed to flush universe resources");
}
}
}, 10L, 10L, TimeUnit.SECONDS);
}
this.playerStorage = var1.getPlayerStorageProvider().getPlayerStorage();
WorldConfigProvider.Default var23 = new WorldConfigProvider.Default();
PrepareUniverseEvent var4 = HytaleServer.get()
.getEventBus()
.<Void, PrepareUniverseEvent>dispatchFor(PrepareUniverseEvent.class)
.dispatch(new PrepareUniverseEvent(var23));
WorldConfigProvider var5 = var4.getWorldConfigProvider();
if (var5 == null) {
var5 = var23;
}
this.worldConfigProvider = var5;
try {
Path var6 = this.path.resolve("blockIdMap.json");
Path var7 = this.path.resolve("blockIdMap.legacy.json");
if (Files.isRegularFile(var6)) {
Files.move(var6, var7, StandardCopyOption.REPLACE_EXISTING);
}
Files.deleteIfExists(this.path.resolve("blockIdMap.json.bak"));
if (Files.isRegularFile(var7)) {
Map var8 = new Int2ObjectOpenHashMap();
for (BsonValue var10 : BsonUtil.readDocument(var7).thenApply(var0 -> var0.getArray("Blocks")).join()) {
BsonDocument var11 = var10.asDocument();
var8.put(var11.getNumber("Id").intValue(), var11.getString("BlockType").getValue());
}
LEGACY_BLOCK_ID_MAP = Collections.unmodifiableMap(var8);
}
} catch (IOException var22) {
((HytaleLogger.Api)this.getLogger().at(Level.SEVERE).withCause(var22)).log("Failed to delete blockIdMap.json");
}
if (Options.isBare()) {
this.universeReady = CompletableFuture.completedFuture(null);
HytaleServer.get().getEventBus().dispatch(AllWorldsLoadedEvent.class);
} else {
ObjectArrayList var24 = new ObjectArrayList();
try {
if (Files.exists(this.worldsDeletedPath)) {
FileUtil.deleteDirectory(this.worldsDeletedPath);
}
} catch (Throwable var17) {
throw new RuntimeException("Failed to complete deletion of " + this.worldsDeletedPath.toAbsolutePath(), var17);
}
try {
Files.createDirectories(this.worldsPath);
if (Options.getOptionSet().has(Options.VERIFY_WORLDS)) {
boolean var26 = Options.getOptionSet().has(Options.RECOVERY_MODE);
try (DirectoryStream var28 = Files.newDirectoryStream(this.worldsPath)) {
for (Path var32 : var28) {
if (HytaleServer.get().isShuttingDown()) {
class="kw">return;
}
if (!var32.equals(this.worldsPath) && Files.isDirectory(var32)) {
Path var33 = var26 ? var32.resolve("recovery-tmp") : null;
if (var33 != null) {
if (Files.exists(var33)) {
FileUtil.deleteDirectory(var33);
}
Files.createDirectories(var33);
}
String var12 = var32.getFileName().toString();
try {
AtomicReference var13 = new AtomicReference<>();
IntIntPair var34 = var5.load(var32, var12)
.thenApplyAsync(SneakyThrow.sneakyFunction(var3x -> {
if (var33 != null) {
var3x.getChunkStorageProvider().beginRecovery(var32, var33);
}
var13.set(var3x);
class="kw">return var3x;
}))
.thenCompose(var3x -> this.makeWorld(var12, var32, var3x))
.thenCompose(SneakyThrow.sneakyFunction(var2x -> this.verifyWorld(var2x, var33)))
.whenComplete((var3x, var4x) -> {
WorldConfig var5 = var13.get();
if (var33 != null && var5 != null) {
try {
if (var4x == null) {
if (Files.exists(var33)) {
FileUtil.deleteDirectory(var33);
}
} else {
var5.getChunkStorageProvider().revertRecovery(var32, var33);
}
} catch (IOException var7) {
throw SneakyThrow.sneakyThrow(var7);
}
}
})
.join();
if (var34.leftInt() > 0) {
this.getLogger()
.at(Level.SEVERE)
.log("Failed to verify world %s, %d/%d chunks corrupted", var12, var34.leftInt(), var34.rightInt());
HytaleServer.get()
.shutdownServer(
ShutdownReason.VERIFY_ERROR
.withMessage(
Message.translation("client.disconnection.shutdownReason.verifyError.chunksCorrupted")
.param("world", var12)
.param("corrupted", var34.leftInt())
.param("total", var34.rightInt())
)
);
class="kw">return;
}
} catch (Exception var18) {
((HytaleLogger.Api)this.getLogger().at(Level.SEVERE).withCause(var18))
.log("Failed to %s world %s", var26 ? "recover" : "verify", var12);
String var14 = var26 ? "client.disconnection.shutdownReason.recoverError" : "client.disconnection.shutdownReason.verifyError";
HytaleServer.get()
.shutdownServer(
ShutdownReason.VERIFY_ERROR.withMessage(Message.translation(var14).param("world", var12).param("detail", var18.getMessage()))
);
class="kw">return;
}
}
}
}
HytaleServer.get().shutdownServer(ShutdownReason.SHUTDOWN);
} else {
try (DirectoryStream var25 = Files.newDirectoryStream(this.worldsPath)) {
for (Path var29 : var25) {
if (HytaleServer.get().isShuttingDown()) {
class="kw">return;
}
if (!var29.equals(this.worldsPath) && Files.isDirectory(var29)) {
String var31 = var29.getFileName().toString();
if (this.getWorld(var31) == null) {
var24.add(this.loadWorldFromStart(var29, var31).exceptionally(var2x -> {
((HytaleLogger.Api)this.getLogger().at(Level.SEVERE).withCause(var2x)).log("Failed to load world: %s", var31);
class="kw">return null;
}));
} else {
this.getLogger().at(Level.SEVERE).log("Skipping loading world '%s' because it already exists!", var31);
}
}
}
}
this.universeReady = CompletableFutureUtil._catch(
CompletableFuture.allOf((CompletableFuture<?>[])var24.toArray(CompletableFuture[]::new))
.thenCompose(
var2x -> {
if (HytaleServer.get().isShuttingDown()) {
class="kw">return CompletableFuture.completedFuture(null);
}
String var3 = var1.getDefaults().getWorld();
class="kw">return var3 != null && !this.worlds.containsKey(var3.toLowerCase(Locale.ROOT)) && !this.isWorldLoadable(var3)
? CompletableFutureUtil._catch(this.addWorld(var3))
: CompletableFuture.completedFuture(null);
}
)
.thenRun(() -> HytaleServer.get().getEventBus().dispatch(AllWorldsLoadedEvent.class))
);
}
} catch (IOException var21) {
throw new RuntimeException("Failed to load Worlds", var21);
}
}
}
class="kw">private CompletableFuture<IntIntPair> verifyWorld(World var1, @Nullable Path var2) class="kw">throws IOException {
ChunkStore var3 = var1.getChunkStore();
IChunkLoader var4 = var2 == null ? var3.getLoader() : var1.getWorldConfig().getChunkStorageProvider().getRecoveryLoader(var3.getStore(), var2);
IChunkSaver var5 = var3.getSaver();
if (var4 != null && var5 != null) {
LongList var6 = var4.getIndexes();
IChunkLoader var7;
if (Options.getOptionSet().valueOf(Options.RECOVERY_MODE) == Options.RecoveryMode.FROM_BACKUP_OR_REGENERATE) {
Path var8 = HytaleServer.get().getConfig().getBackupConfig().getDirectory();
if (var8 == null || !Files.exists(var8)) {
Path var9 = this.path.resolve("../backup");
if (Files.exists(var9)) {
var8 = var9;
}
}
List var12 = new ArrayList<>();
if (var8 == null) {
class="kw">return CompletableFuture.failedFuture(new RuntimeException("No usable backups"));
}
DateTimeFormatter var10 = DateTimeFormatter.ofPattern("yyyy-MM-dd_HH-mm-ss");
collectBackupZips(var8, var10, var12);
collectBackupZips(var8.resolve("archive"), var10, var12);
var12.sort(Comparator.<Path, String>comparing(var0 -> var0.getFileName().toString()).reversed());
var7 = new BackupChunkLoader(var3, var12);
} else {
var7 = null;
}
AtomicInteger var11 = new AtomicInteger();
AtomicInteger var13 = new AtomicInteger();
int var14 = var6.size();
class="kw">return this.verifyAllChunks(var1, var4, var5, var7, var6.iterator(), var11, var13, var14)
.thenApply(var2x -> IntIntPair.of(var13.get(), var14))
.whenCompleteAsync((var6x, var7x) -> {
try {
var5.flush();
if (var2 != null) {
var4.close();
}
} catch (IOException var10) {
throw SneakyThrow.sneakyThrow(var10);
}
this.removeWorld(var1.getName());
if (var7 != null) {
try {
var7.close();
} catch (IOException var9) {
throw SneakyThrow.sneakyThrow(var9);
}
}
});
} else {
class="kw">return CompletableFuture.failedFuture(new RuntimeException("Failed to load World"));
}
}
class="kw">private CompletableFuture<Void> verifyAllChunks(
@Nonnull World var1,
@Nonnull IChunkLoader var2,
@Nonnull IChunkSaver var3,
@Nullable IChunkLoader var4,
@Nonnull LongIterator var5,
@Nonnull AtomicInteger var6,
@Nonnull AtomicInteger var7,
int var8
) {
CompletableFuture var9 = new CompletableFuture<>();
this.verifyNextChunk(var9, var1, var2, var3, var4, var5, var6, var7, var8);
class="kw">return var9;
}
class="kw">private void verifyNextChunk(
@Nonnull CompletableFuture<Void> var1,
@Nonnull World var2,
@Nonnull IChunkLoader var3,
@Nonnull IChunkSaver var4,
@Nullable IChunkLoader var5,
@Nonnull LongIterator var6,
@Nonnull AtomicInteger var7,
@Nonnull AtomicInteger var8,
int var9
) {
if (!var6.hasNext()) {
var1.complete(null);
} else {
long var10 = var6.nextLong();
int var12 = ChunkUtil.xOfChunkIndex(var10);
int var13 = ChunkUtil.zOfChunkIndex(var10);
Options.RecoveryMode var14 = (Options.RecoveryMode)Options.getOptionSet().valueOf(Options.RECOVERY_MODE);
var3.loadHolder(var12, var13)
.thenCompose(var3x -> var4.saveHolder(var12, var13, (Holder<ChunkStore>)var3x))
.exceptionallyCompose(
var7x -> {
if (var14 == null) {
var8.incrementAndGet();
class="kw">return CompletableFuture.completedFuture(null);
}
class="kw">return class="kw">switch (var14) {
case REGENERATE -> var4.removeHolder(var12, var13);
case FROM_BACKUP_OR_REGENERATE -> var5 == null
? CompletableFuture.failedFuture(
new RuntimeException("Recovery of individual chunks from backups not supported by storage type. Please restore instead.")
)
: var4.removeHolder(var12, var13).thenCompose(var3x -> var5.loadHolder(var12, var13)).thenCompose(var4x -> {
if (var4x == null) {
((HytaleLogger.Api)this.getLogger().atWarning()).log("Failed to recover a chunk at %d, %d", var12, var13);
class="kw">return CompletableFuture.completedFuture(null);
} else {
((HytaleLogger.Api)this.getLogger().atInfo()).log("Managed to recover a chunk at %d, %d", var12, var13);
class="kw">return var4.saveHolder(var12, var13, (Holder<ChunkStore>)var4x);
}
}).exceptionally(var3x -> {
((HytaleLogger.Api)this.getLogger().atWarning()).log("Failed to recover a chunk at %d, %d", var12, var13);
class="kw">return null;
});
};
}
)
.thenAccept(
var5x -> {
int var6 = var7.incrementAndGet();
if (var6 % 100 == 0 || var6 == var9) {
String var7 = String.format("%s %d/%d chunks for world %s", var14 == null ? "Verified" : "Recovering", var6, var9, var2.getName());
((HytaleLogger.Api)this.getLogger().atInfo()).log("%s", var7);
String var8 = var14 == null ? "client.gameLoadingView.status.verifiedChunks" : "client.gameLoadingView.status.recoveringChunks";
double var9 = MathUtil.round((double)var6 / var9, 2) * 100.0;
HytaleServer.get()
.reportSingleplayerStatus(Message.translation(var8).param("done", var6).param("total", var9).param("name", var2.getName()), var9);
}
}
)
.whenComplete((var10x, var11) -> {
if (var11 != null) {
var1.completeExceptionally(var11);
} else {
this.verifyNextChunk(var1, var2, var3, var4, var5, var6, var7, var8, var9);
}
});
}
}
class="kw">private class="kw">static void collectBackupZips(@Nonnull Path var0, @Nonnull DateTimeFormatter var1, @Nonnull List<Path> var2) {
if (Files.isDirectory(var0)) {
try (Stream var3 = Files.list(var0)) {
var3.filter(var0x -> Files.isRegularFile(var0x) && var0x.getFileName().toString().endsWith(".zip")).filter(var1x -> {
String var2 = var1x.getFileName().toString();
var2 = var2.substring(0, var2.length() - 4);
try {
LocalDateTime.parse(var2, var1);
class="kw">return true;
} catch (DateTimeParseException var4) {
class="kw">return false;
}
}).forEach(var2::add);
} catch (IOException var8) {
}
}
}
@Override
class="kw">protected void shutdown() {
this.disconnectAllPLayers();
this.shutdownAllWorlds();
}
class="kw">private void flushUniverseResourcesForShutdown() {
if (this.universeResourcesFlushTask != null) {
this.universeResourcesFlushTask.cancel(false);
}
if (this.universeResources != null) {
try {
this.universeResources.flushAll().get(30L, TimeUnit.SECONDS);
} catch (TimeoutException var2) {
this.getLogger()
.at(Level.SEVERE)
.log(
"Timed out waiting for universe resource writes during shutdown (saving locked: %s), unfinished writes are lost when the process exits",
this.isSavingLocked()
);
} catch (InterruptedException var3) {
Thread.currentThread().interrupt();
this.getLogger().at(Level.SEVERE).log("Interrupted while flushing universe resources during shutdown");
} catch (Exception var4) {
((HytaleLogger.Api)this.getLogger().at(Level.SEVERE).withCause(var4)).log("Failed to flush universe resources during shutdown");
}
}
}
class="kw">public void disconnectAllPLayers() {
ShutdownReason var1 = HytaleServer.get().getShutdownReason();
FormattedMessage var2 = var1 != null && var1.getFormattedMessage() != null
? var1.getFormattedMessage()
: Message.translation("server.general.disconnect.stoppingServer").getFormattedMessage();
this.playersByUuid.values().forEach(var1x -> var1x.getPacketHandler().disconnect(var2));
}
class="kw">public void shutdownAllWorlds() {
Iterator var1 = this.worlds.values().iterator();
while (var1.hasNext()) {
World var2 = var1.next();
var2.stop();
var1.remove();
}
}
@Nonnull
@Override
class="kw">public MetricResults toMetricResults() {
class="kw">return METRICS_REGISTRY.toMetricResults(this);
}
class="kw">public CompletableFuture<Void> getUniverseReady() {
class="kw">return this.universeReady;
}
class="kw">public ResourceType<ChunkStore, WorldMarkersResource> getWorldMarkersResourceType() {
class="kw">return this.worldMarkersResourceType;
}
class="kw">public boolean isWorldLoadable(@Nonnull String var1) {
Path var2 = this.validateWorldPath(var1);
class="kw">return Files.isDirectory(var2) && (Files.exists(var2.resolve("config.bson")) || Files.exists(var2.resolve("config.json")));
}
@Nonnull
@CheckReturnValue
class="kw">public CompletableFuture<World> addWorld(@Nonnull String var1) {
class="kw">return this.addWorld(var1, null, null);
}
@Nonnull
@Deprecated
@CheckReturnValue
class="kw">public CompletableFuture<World> addWorld(@Nonnull String var1, @Nullable String var2, @Nullable String var3) {
if (this.worlds.containsKey(var1)) {
throw new IllegalArgumentException("World " + var1 + " already exists!");
}
if (this.isWorldLoadable(var1)) {
throw new IllegalArgumentException("World " + var1 + " already exists on disk!");
}
Path var4 = this.validateWorldPath(var1);
class="kw">return this.worldConfigProvider.load(var4, var1).thenCompose(var5 -> {
if (var2 != null && !"class="kw">default".equals(var2)) {
BuilderCodec var6 = IWorldGenProvider.CODEC.getCodecFor(var2);
if (var6 == null) {
throw new IllegalArgumentException("Unknown generatorType '" + var2 + "'");
}
IWorldGenProvider var7 = var6.getDefaultValue();
var5.setWorldGenProvider(var7);
var5.markChanged();
}
if (var3 != null && !"class="kw">default".equals(var3)) {
BuilderCodec var8 = IChunkStorageProvider.CODEC.getCodecFor(var3);
if (var8 == null) {
throw new IllegalArgumentException("Unknown chunkStorageType '" + var3 + "'");
}
IChunkStorageProvider var9 = (IChunkStorageProvider<?>)var8.getDefaultValue();
var5.setChunkStorageProvider(var9);
var5.markChanged();
}
class="kw">return this.makeWorld(var1, var4, var5);
});
}
class="kw">public Path validateWorldPath(@Nonnull String var1) {
Path var2 = PathUtil.resolvePathWithinDir(this.worldsPath, var1);
if (var2 == null) {
throw new IllegalArgumentException("World " + var1 + " contains invalid characters!");
} else {
class="kw">return var2;
}
}
@Nonnull
@CheckReturnValue
class="kw">public CompletableFuture<World> makeWorld(@Nonnull String var1, @Nonnull Path var2, @Nonnull WorldConfig var3) {
class="kw">return this.makeWorld(var1, var2, var3, true);
}
@Nonnull
@CheckReturnValue
class="kw">public CompletableFuture<World> makeWorld(@Nonnull String var1, @Nonnull Path var2, @Nonnull WorldConfig var3, boolean var4) {
if (!PathUtil.isChildOf(this.worldsPath, var2) && !PathUtil.isInTrustedRoot(var2)) {
throw new IllegalArgumentException("Invalid path");
}
Map var5 = var3.getRequiredPlugins();
if (var5 != null) {
PluginManager var6 = PluginManager.get();
for (Entry var8 : var5.entrySet()) {
if (!var6.hasPlugin(var8.getKey(), var8.getValue())) {
this.getLogger().at(Level.SEVERE).log("Failed to load world! Missing plugin: %s, Version: %s", var8.getKey(), var8.getValue());
throw new IllegalStateException("Missing plugin");
}
}
}
if (this.worlds.containsKey(var1)) {
throw new IllegalArgumentException("World " + var1 + " already exists!");
} else {
class="kw">return CompletableFuture.<World>supplyAsync(
() -> {
World var4 = new World(var1, var2, var3);
AddWorldEvent var5 = HytaleServer.get().getEventBus().dispatchFor(AddWorldEvent.class, var1).dispatch(new AddWorldEvent(var4));
if (!var5.isCancelled() && !HytaleServer.get().isShuttingDown()) {
World var6 = this.worlds.putIfAbsent(var1.toLowerCase(Locale.ROOT), var4);
if (var6 != null) {
throw new ConcurrentModificationException(
"World with name " + var1 + " already exists but didn't before! Looks like you have a race condition."
);
} else {
World var7 = this.worldsByUuid.putIfAbsent(var3.getUuid(), var4);
if (var7 != null) {
throw new ConcurrentModificationException(
"World with UUID " + var3.getUuid() + " already exists but didn't before! Looks like you have a race condition."
);
} else {
class="kw">return var4;
}
}
} else {
throw new WorldLoadCancelledException();
}
}
)
.thenCompose(World::init)
.thenCompose(
var1x -> !Options.getOptionSet().has(Options.MIGRATIONS) && var4
? var1x.start().thenApply(var1xx -> var1x)
: CompletableFuture.completedFuture(var1x)
)
.whenComplete((var2x, var3x) -> {
if (var3x != null) {
String var4 = var1.toLowerCase(Locale.ROOT);
if (this.worlds.containsKey(var4)) {
try {
this.removeWorldExceptionally(var1, Map.of());
} catch (Exception var6) {
((HytaleLogger.Api)this.getLogger().at(Level.WARNING).withCause(var6)).log("Failed to clean up world '%s' after init failure", var1);
}
}
}
});
}
}
class="kw">private CompletableFuture<Void> loadWorldFromStart(@Nonnull Path var1, @Nonnull String var2) {
class="kw">return this.worldConfigProvider.load(var1, var2).thenCompose(var3 -> var3.isDeleteOnUniverseStart() ? CompletableFuture.runAsync(() -> {
try {
FileUtil.deleteDirectory(var1);
this.getLogger().at(Level.INFO).log("Deleted world %s from DeleteOnUniverseStart flag on universe start at %s", var2, var1);
} catch (Throwable var4) {
throw new RuntimeException("Error deleting world directory on universe start", var4);
}
}) : this.makeWorld(var2, var1, var3).thenApply(var0 -> null));
}
@Nonnull
@CheckReturnValue
class="kw">public CompletableFuture<World> loadWorld(@Nonnull String var1) {
if (this.worlds.containsKey(var1)) {
throw new IllegalArgumentException("World " + var1 + " already loaded!");
} else {
Path var2 = this.validateWorldPath(var1);
if (!Files.isDirectory(var2)) {
throw new IllegalArgumentException("World " + var1 + " does not exist!");
} else {
class="kw">return this.worldConfigProvider.load(var2, var1).thenCompose(var3 -> this.makeWorld(var1, var2, var3));
}
}
}
@Nullable
class="kw">public World getWorld(@Nullable String var1) {
class="kw">return var1 == null ? null : this.worlds.get(var1.toLowerCase(Locale.ROOT));
}
@Nullable
class="kw">public World getWorld(@Nonnull UUID var1) {
class="kw">return this.worldsByUuid.get(var1);
}
@Nullable
class="kw">public World getDefaultWorld() {
HytaleServerConfig var1 = HytaleServer.get().getConfig();
if (var1 == null) {
class="kw">return null;
}
String var2 = var1.getDefaults().getWorld();
class="kw">return var2 != null ? this.getWorld(var2) : null;
}
class="kw">public boolean removeWorld(@Nonnull String var1) {
Objects.requireNonNull(var1, "Name can't be null!");
String var2 = var1.toLowerCase(Locale.ROOT);
World var3 = this.worlds.get(var2);
if (var3 == null) {
throw new NullPointerException("World " + var1 + " doesn't exist!");
}
RemoveWorldEvent var4 = HytaleServer.get()
.getEventBus()
.dispatchFor(RemoveWorldEvent.class, var1)
.dispatch(new RemoveWorldEvent(var3, RemoveWorldEvent.RemovalReason.GENERAL));
if (var4.isCancelled()) {
class="kw">return false;
}
if (var3.isAlive()) {
if (var3.isInThread()) {
var3.stopIndividualWorld();
} else {
CompletableFuture.runAsync(var3::stopIndividualWorld).join();
}
}
this.worlds.remove(var2);
this.worldsByUuid.remove(var3.getWorldConfig().getUuid());
var3.validateDeleteOnRemove();
class="kw">return true;
}
class="kw">public void removeWorldExceptionally(@Nonnull String var1, Map<UUID, PlayerRef> var2) {
Objects.requireNonNull(var1, "Name can't be null!");
this.getLogger().at(Level.INFO).log("Removing world exceptionally: %s", var1);
String var3 = var1.toLowerCase(Locale.ROOT);
World var4 = this.worlds.get(var3);
if (var4 == null) {
throw new NullPointerException("World " + var1 + " doesn't exist!");
}
HytaleServer.get()
.getEventBus()
.dispatchFor(RemoveWorldEvent.class, var1)
.dispatch(new RemoveWorldEvent(var4, RemoveWorldEvent.RemovalReason.EXCEPTIONAL));
if (var4.isAlive()) {
if (var4.isInThread()) {
var4.stopIndividualWorld(var2);
} else {
CompletableFuture.runAsync(() -> var4.stopIndividualWorld(var2)).join();
}
}
this.worlds.remove(var3);
this.worldsByUuid.remove(var4.getWorldConfig().getUuid());
var4.validateDeleteOnRemove();
}
@Nonnull
class="kw">public Path getPath() {
class="kw">return this.path;
}
class="kw">public Path getWorldsPath() {
class="kw">return this.worldsPath;
}
class="kw">public Path getWorldsDeletedPath() {
class="kw">return this.worldsDeletedPath;
}
@Nonnull
class="kw">public Map<String, World> getWorlds() {
class="kw">return this.unmodifiableWorlds;
}
@Nonnull
class="kw">public Collection<PlayerRef> getPlayers() {
class="kw">return this.players;
}
@Nullable
class="kw">public PlayerRef getPlayer(@Nonnull UUID var1) {
class="kw">return this.playersByUuid.get(var1);
}
@Nullable
class="kw">public PlayerRef getPlayer(@Nonnull String var1, @Nonnull NameMatching var2) {
class="kw">return var2.find(this.playersByUuid.values(), var1, var0 -> var0.getComponent(PlayerRef.getComponentType()).getUsername());
}
@Nullable
class="kw">public PlayerRef getPlayer(@Nonnull String var1, @Nonnull Comparator<String> var2, @Nonnull BiPredicate<String, String> var3) {
class="kw">return NameMatching.find(this.playersByUuid.values(), var1, var0 -> var0.getComponent(PlayerRef.getComponentType()).getUsername(), var2, var3);
}
@Nullable
class="kw">public PlayerRef getPlayerByUsername(@Nonnull String var1, @Nonnull NameMatching var2) {
class="kw">return var2.find(this.playersByUuid.values(), var1, PlayerRef::getUsername);
}
@Nullable
class="kw">public PlayerRef getPlayerByUsername(@Nonnull String var1, @Nonnull Comparator<String> var2, @Nonnull BiPredicate<String, String> var3) {
class="kw">return NameMatching.find(this.playersByUuid.values(), var1, PlayerRef::getUsername, var2, var3);
}
class="kw">public int getPlayerCount() {
class="kw">return this.playersByUuid.size();
}
@Nonnull
class="kw">public CompletableFuture<PlayerRef> addPlayer(
@Nonnull ChannelConnection var1, @Nonnull String var2, @Nonnull ProtocolVersion var3, @Nonnull PlayerAuthentication var4, int var5
) {
GamePacketHandler var6 = new GamePacketHandler(var1, var3, var4);
var6.setQueuePackets(false);
this.getLogger().at(Level.INFO).log("Adding player '%s (%s)", var4.getUsername(), var4.getUuid());
CompletableFuture var7 = var1.setupAuxiliaryChannels(var6, var6::setChannel);
class="kw">return var7.<Holder<EntityStore>, Holder<EntityStore>>thenCombine(this.playerStorage.load(var4.getUuid()), (var0, var1x) -> var1x)
.exceptionally(var0 -> {
throw new RuntimeException("Exception when adding player to universe:", var0);
})
.thenCompose(
var6x -> {
ChunkTracker var7 = new ChunkTracker();
PlayerRef var8 = new PlayerRef((Holder<EntityStore>)var6x, var4.getUuid(), var4.getUsername(), var2, var6, var7);
var7.setDefaultMaxSectionsPerSecond(var8);
var6x.putComponent(PlayerRef.getComponentType(), var8);
var6x.putComponent(ChunkTracker.getComponentType(), var7);
var6x.putComponent(UUIDComponent.getComponentType(), new UUIDComponent(var4.getUuid()));
var6x.ensureComponent(PositionDataComponent.getComponentType());
var6x.ensureComponent(MovementAudioComponent.getComponentType());
Player var9 = var6x.ensureAndGetComponent(Player.getComponentType());
var9.init(var4.getUuid(), var8);
PlayerConfigData var10 = var9.getPlayerConfigData();
var10.cleanup(this);
var1.logConnectionTimings("Load Player Config", Level.FINEST);
if (var4.getSkin() != null) {
var6x.putComponent(PlayerSkinComponent.getComponentType(), new PlayerSkinComponent(var4.getSkin()));
var6x.putComponent(ModelComponent.getComponentType(), new ModelComponent(CosmeticsModule.get().createModel(var4.getSkin())));
}
var6.setPlayerRef(var8);
var6.getChannel().setChannelHandler(var6);
var9.setClientViewRadius(var5);
EntityTrackerSystems.EntityViewer var11 = var6x.getComponent(EntityTrackerSystems.EntityViewer.getComponentType());
if (var11 != null) {
var11.viewRadiusBlocks = var9.getViewRadius() * 32;
} else {
var11 = new EntityTrackerSystems.EntityViewer(var9.getViewRadius() * 32, var6);
var6x.addComponent(EntityTrackerSystems.EntityViewer.getComponentType(), var11);
}
PlayerRef var12 = this.playersByUuid.putIfAbsent(var4.getUuid(), var8);
if (var12 != null) {
this.getLogger()
.at(Level.WARNING)
.log("Player '%s' (%s) already joining from another connection, rejecting duplicate", var4.getUsername(), var4.getUuid());
var6.disconnect(Message.translation("client.general.disconnect.accountAlreadyConnecting"));
class="kw">return CompletableFuture.completedFuture(null);
}
String var13 = var10.getWorld();
World var14 = this.getWorld(var13);
PlayerConnectEvent var15 = HytaleServer.get()
.getEventBus()
.<Void, PlayerConnectEvent>dispatchFor(PlayerConnectEvent.class)
.dispatch(new PlayerConnectEvent((Holder<EntityStore>)var6x, var8, var14 != null ? var14 : this.getDefaultWorld()));
if (!var1.isActive()) {
this.playersByUuid.remove(var4.getUuid(), var8);
this.getLogger()
.at(Level.INFO)
.log("Player '%s' (%s) disconnected during PlayerConnectEvent, cleaned up", var4.getUsername(), var4.getUuid());
class="kw">return CompletableFuture.completedFuture(null);
}
World var16 = var15.getWorld() != null ? var15.getWorld() : this.getDefaultWorld();
if (var16 == null) {
this.playersByUuid.remove(var4.getUuid(), var8);
var6.disconnect(Message.translation("client.general.disconnect.noWorldAvailable"));
this.getLogger().at(Level.SEVERE).log("Player '%s' (%s) could not join - no class="kw">default world configured", var4.getUsername(), var4.getUuid());
class="kw">return CompletableFuture.completedFuture(null);
}
if (var13 != null && var14 == null) {
var8.sendMessage(Message.translation("server.universe.failedToFindWorld").param("lastWorldName", var13).param("name", var16.getName()));
}
var1.logConnectionTimings("Processed Referral", Level.FINEST);
var8.getPacketHandler().write(new ServerTags(AssetRegistry.getClientTags()));
CompletableFuture var17 = var16.addPlayer(var8, null, false, false);
if (var17 == null) {
this.playersByUuid.remove(var4.getUuid(), var8);
this.getLogger().at(Level.INFO).log("Player '%s' (%s) disconnected before world addition, cleaned up", var4.getUsername(), var4.getUuid());
class="kw">return CompletableFuture.completedFuture(null);
} else {
class="kw">return var17.<PlayerRef>thenApply(
var5x -> {
var1.logConnectionTimings("Add to World", Level.FINEST);
if (!var1.isActive()) {
if (var5x != null) {
var9.remove();
}
this.playersByUuid.remove(var4.getUuid(), var8);
this.getLogger()
.at(Level.WARNING)
.log("Player '%s' (%s) disconnected during world join, cleaned up from universe", var4.getUsername(), var4.getUuid());
class="kw">return null;
} else if (var9.wasRemoved()) {
this.playersByUuid.remove(var4.getUuid(), var8);
class="kw">return null;
} else {
CommandManager.get().broadcastArgCacheInvalidation("player_ref");
class="kw">return (PlayerRef)var5x;
}
}
)
.exceptionally(var4x -> {
this.playersByUuid.remove(var4.getUuid(), var8);
var9.remove();
throw new RuntimeException("Exception when adding player to universe:", var4x);
});
}
}
);
}
class="kw">public void removePlayer(@Nonnull PlayerRef var1) {
this.getLogger().at(Level.INFO).log("Removing player '%s' (%s%s", var1.getUsername(), var1.getUuid(), ')');
IEventDispatcher var2 = HytaleServer.get().getEventBus().dispatchFor(PlayerDisconnectEvent.class);
if (var2.hasListener()) {
var2.dispatch(new PlayerDisconnectEvent(var1));
}
Ref var3 = var1.getReference();
if (var3 != null && var3.isValid()) {
World var4 = var3.getStore().getExternalData().getWorld();
if (var4.isInThread()) {
try {
Player var5 = var3.getStore().getComponent(var3, Player.getComponentType());
if (var5 != null) {
var5.remove();
}
} class="kw">finally {
this.finalizePlayerRemoval(var1);
}
} else {
CompletableFuture var9 = new CompletableFuture<>();
CompletableFuture.runAsync(() -> {
if (var3.isValid()) {
Player var1 = var3.getStore().getComponent(var3, Player.getComponentType());
if (var1 != null) {
var1.remove();
}
}
}, var4).whenComplete((var1x, var2x) -> {
if (var2x != null) {
var9.completeExceptionally(var2x);
} else {
var9.complete(null);
}
});
var9.orTimeout(5L, TimeUnit.SECONDS)
.whenComplete(
(var2x, var3x) -> {
if (var3x != null) {
((HytaleLogger.Api)this.getLogger().at(Level.WARNING).withCause(var3x))
.log("Timeout or error waiting for player '%s' removal from world store", var1.getUsername());
}
this.finalizePlayerRemoval(var1);
}
);
}
} else {
this.finalizePlayerRemoval(var1);
}
}
class="kw">private void finalizePlayerRemoval(@Nonnull PlayerRef var1) {
if (this.playersByUuid.remove(var1.getUuid(), var1)) {
CommandManager.get().broadcastArgCacheInvalidation("player_ref");
if (Constants.SINGLEPLAYER) {
if (this.playersByUuid.isEmpty()) {
this.getLogger().at(Level.INFO).log("No players left on singleplayer server shutting down!");
HytaleServer.get().shutdownServer();
} else if (SingleplayerModule.isOwner(var1)) {
this.getLogger().at(Level.INFO).log("Owner left the singleplayer server shutting down!");
this.getPlayers()
.forEach(
var1x -> var1x.getPacketHandler()
.disconnect(Message.translation("server.general.disconnect.singleplayerOwnerLeft").param("username", var1.getUsername()))
);
HytaleServer.get().shutdownServer();
}
}
}
}
@Nonnull
class="kw">public CompletableFuture<PlayerRef> resetPlayer(@Nonnull PlayerRef var1) {
class="kw">return this.playerStorage.load(var1.getUuid()).exceptionally(var0 -> {
throw new RuntimeException("Exception when adding player to universe:", var0);
}).thenCompose(var2 -> this.resetPlayer(var1, (Holder<EntityStore>)var2));
}
@Nonnull
class="kw">public CompletableFuture<PlayerRef> resetPlayer(@Nonnull PlayerRef var1, @Nonnull Holder<EntityStore> var2) {
class="kw">return this.resetPlayer(var1, var2, null, null);
}
@Nonnull
class="kw">public class="kw">static CompletableFuture<PlayerRef> transferPlayerAsync(
@Nonnull PlayerRef var0, @Nonnull World var1, @Nonnull CompletableFuture<World> var2, @Nonnull Function<World, Transform> var3
) {
class="kw">return CompletableFuture.runAsync(var0::removeFromStore, var1)
.thenCombine(var2.orTimeout(30L, TimeUnit.SECONDS), (var0x, var1x) -> (World)var1x)
.thenCompose(var2x -> var2x.addPlayer(var0, var3.apply(var2x), Boolean.TRUE, Boolean.FALSE));
}
@Nonnull
class="kw">public CompletableFuture<PlayerRef> resetPlayer(@Nonnull PlayerRef var1, @Nonnull Holder<EntityStore> var2, @Nullable World var3, @Nullable Transform var4) {
UUID var5 = var1.getUuid();
Player var6 = var1.getComponent(Player.getComponentType());
World var7;
if (var3 == null) {
var7 = var6.getWorld();
} else {
var7 = var3;
}
this.getLogger()
.at(Level.INFO)
.log("Resetting player '%s', moving to world '%s' at location %s (%s)", var1.getUsername(), var3 != null ? var3.getName() : null, var4, var1.getUuid());
GamePacketHandler var8 = (GamePacketHandler)var1.getPacketHandler();
Player var9 = var2.ensureAndGetComponent(Player.getComponentType());
var9.init(var5, var1);
CompletableFuture var10 = new CompletableFuture<>();
if (var6.getWorld() != null) {
var6.getWorld().execute(() -> {
var1.removeFromStore();
var10.complete(null);
});
} else {
var10.complete(null);
}
class="kw">return var10.thenAccept(var5x -> {
var6.resetManagers(var2);
var9.copyFrom(var6);
EntityTrackerSystems.EntityViewer var6 = var2.getComponent(EntityTrackerSystems.EntityViewer.getComponentType());
if (var6 != null) {
var6.viewRadiusBlocks = var9.getViewRadius() * 32;
} else {
var6 = new EntityTrackerSystems.EntityViewer(var9.getViewRadius() * 32, var8);
var2.addComponent(EntityTrackerSystems.EntityViewer.getComponentType(), var6);
}
var8.setPlayerRef(var1);
var1.replaceHolder(var2);
var2.putComponent(PlayerRef.getComponentType(), var1);
}).thenCompose(var3x -> var7.addPlayer(var1, var4));
}
@Override
class="kw">public void sendMessage(@Nonnull Message var1) {
for (PlayerRef var3 : this.playersByUuid.values()) {
var3.sendMessage(var1);
}
}
class="kw">public void broadcastPacket(@Nonnull ToClientPacket var1) {
for (PlayerRef var3 : this.playersByUuid.values()) {
var3.getPacketHandler().write(var1);
}
}
class="kw">public void broadcastPacketNoCache(@Nonnull ToClientPacket var1) {
for (PlayerRef var3 : this.playersByUuid.values()) {
var3.getPacketHandler().writeNoCache(var1);
}
}
class="kw">public void broadcastPacket(@Nonnull ToClientPacket... var1) {
for (PlayerRef var3 : this.playersByUuid.values()) {
var3.getPacketHandler().write(var1);
}
}
class="kw">public StorageManager getStorageManager() {
class="kw">return this.storageManager;
}
class="kw">public PlayerStorage getPlayerStorage() {
class="kw">return this.playerStorage;
}
class="kw">public void setPlayerStorage(@Nonnull PlayerStorage var1) {
this.playerStorage = var1;
}
class="kw">public WorldConfigProvider getWorldConfigProvider() {
class="kw">return this.worldConfigProvider;
}
@Nonnull
class="kw">public ComponentType<EntityStore, PlayerRef> getPlayerRefComponentType() {
class="kw">return this.playerRefComponentType;
}
@Nonnull
@Deprecated
class="kw">public class="kw">static Map<Integer, String> getLegacyBlockIdMap() {
class="kw">return LEGACY_BLOCK_ID_MAP;
}
class="kw">public class="kw">static Path getWorldGenPath() {
OptionSet var1 = Options.getOptionSet();
Path var0;
if (var1.has(Options.WORLD_GEN_DIRECTORY)) {
var0 = (Path)var1.valueOf(Options.WORLD_GEN_DIRECTORY);
} else {
var0 = AssetUtil.getHytaleAssetsPath().resolve("Server").resolve("World");
}
class="kw">return var0;
}
}