refactor the AbstractSaveStructure classes
This commit is contained in:
@@ -0,0 +1,36 @@
|
||||
package com.seibel.lod.core.file.structure;
|
||||
|
||||
import com.seibel.lod.core.logging.DhLoggerBuilder;
|
||||
import com.seibel.lod.core.wrapperInterfaces.world.ILevelWrapper;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* Abstract class for determining where LOD data should be saved to.
|
||||
*
|
||||
* @version 2022-12-17
|
||||
*/
|
||||
public abstract class AbstractSaveStructure implements AutoCloseable
|
||||
{
|
||||
public static final String RENDER_CACHE_FOLDER = "cache";
|
||||
public static final String DATA_FOLDER = "data";
|
||||
|
||||
protected static final Logger LOGGER = DhLoggerBuilder.getLogger();
|
||||
|
||||
/**
|
||||
* Attempts to return the folder that contains LOD data for the given {@link ILevelWrapper}.
|
||||
* If no appropriate folder exists, one will be created. <br><br>
|
||||
*
|
||||
* This will always return a folder, however that folder may not be the best match
|
||||
* if multiverse support is enabled.
|
||||
* */
|
||||
public abstract File tryGetOrCreateLevelFolder(ILevelWrapper wrapper);
|
||||
|
||||
/** Will return null if no parent folder exists for the given {@link ILevelWrapper}.*/
|
||||
public abstract File getRenderCacheFolder(ILevelWrapper world);
|
||||
/** Will return null if no parent folder exists for the given {@link ILevelWrapper}.*/
|
||||
public abstract File getDataFolder(ILevelWrapper world);
|
||||
|
||||
}
|
||||
|
||||
+226
-153
@@ -12,159 +12,232 @@ import com.seibel.lod.core.wrapperInterfaces.world.ILevelWrapper;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.io.File;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Optional;
|
||||
import java.util.*;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class ClientOnlySaveStructure extends SaveStructure {
|
||||
final File folder;
|
||||
private static final IMinecraftClientWrapper MC_CLIENT = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class);
|
||||
public static final String INVALID_FILE_CHARACTERS_REGEX = "[\\\\/:*?\"<>|]";
|
||||
private static String getServerFolderName()
|
||||
{
|
||||
// parse the current server's IP
|
||||
ParsedIp parsedIp = new ParsedIp(MC_CLIENT.getCurrentServerIp());
|
||||
String serverIpCleaned = parsedIp.ip.replaceAll(INVALID_FILE_CHARACTERS_REGEX, "");
|
||||
String serverPortCleaned = parsedIp.port != null ? parsedIp.port.replaceAll(INVALID_FILE_CHARACTERS_REGEX, "") : "";
|
||||
|
||||
// determine the format of the folder name
|
||||
EServerFolderNameMode folderNameMode = Config.Client.Multiplayer.serverFolderNameMode.get();
|
||||
if (folderNameMode == EServerFolderNameMode.AUTO)
|
||||
{
|
||||
if (parsedIp.isLan())
|
||||
{
|
||||
// LAN
|
||||
folderNameMode = EServerFolderNameMode.NAME_IP;
|
||||
}
|
||||
else
|
||||
{
|
||||
// normal multiplayer
|
||||
folderNameMode = EServerFolderNameMode.NAME_IP_PORT;
|
||||
}
|
||||
}
|
||||
String serverName = MC_CLIENT.getCurrentServerName().replaceAll(INVALID_FILE_CHARACTERS_REGEX, "");
|
||||
String serverMcVersion = MC_CLIENT.getCurrentServerVersion().replaceAll(INVALID_FILE_CHARACTERS_REGEX, "");
|
||||
// generate the folder name
|
||||
String folderName = "";
|
||||
switch (folderNameMode)
|
||||
{
|
||||
// default and auto shouldn't be used
|
||||
// and are just here to make the compiler happy
|
||||
default:
|
||||
case NAME_ONLY:
|
||||
folderName = serverName;
|
||||
break;
|
||||
|
||||
case NAME_IP:
|
||||
folderName = serverName + ", IP " + serverIpCleaned;
|
||||
break;
|
||||
case NAME_IP_PORT:
|
||||
folderName = serverName + ", IP " + serverIpCleaned + (serverPortCleaned.length() != 0 ? ("-" + serverPortCleaned) : "");
|
||||
break;
|
||||
case NAME_IP_PORT_MC_VERSION:
|
||||
folderName = serverName + ", IP " + serverIpCleaned + (serverPortCleaned.length() != 0 ? ("-" + serverPortCleaned) : "") + ", GameVersion " + serverMcVersion;
|
||||
break;
|
||||
}
|
||||
// PercentEscaper makes the characters all part of the standard alphameric character set
|
||||
// This fixes some issues when the server is named something in other languages
|
||||
return new PercentEscaper("", true).escape(folderName);
|
||||
}
|
||||
|
||||
SubDimensionLevelMatcher fileMatcher = null;
|
||||
final HashMap<ILevelWrapper, File> levelToFileMap = new HashMap<>();
|
||||
|
||||
// Fit for Client_Only environment
|
||||
public ClientOnlySaveStructure() {
|
||||
folder = new File(MC_CLIENT.getGameDirectory().getPath() +
|
||||
File.separatorChar + "Distant_Horizons_server_data" + File.separatorChar + getServerFolderName());
|
||||
if (!folder.exists()) folder.mkdirs(); //TODO: Deal with errors
|
||||
}
|
||||
|
||||
@Override
|
||||
public File tryGetLevelFolder(ILevelWrapper level) {
|
||||
return levelToFileMap.computeIfAbsent(level, (l) -> {
|
||||
if (Config.Client.Multiplayer.multiDimensionRequiredSimilarity.get() == 0) {
|
||||
if (fileMatcher != null) {
|
||||
fileMatcher.close();
|
||||
fileMatcher = null;
|
||||
}
|
||||
return getLevelFolderWithoutSimilarityMatching(l);
|
||||
}
|
||||
if (fileMatcher == null || !fileMatcher.isFindingLevel(l)) {
|
||||
LOGGER.info("Loading level for world " + l.getDimensionType().getDimensionName());
|
||||
fileMatcher = new SubDimensionLevelMatcher(l, folder,
|
||||
(File[]) getMatchingLevelFolders(l).toArray());
|
||||
}
|
||||
File levelFile = fileMatcher.tryGetLevel();
|
||||
if (levelFile != null) {
|
||||
fileMatcher.close();
|
||||
fileMatcher = null;
|
||||
}
|
||||
return levelFile;
|
||||
});
|
||||
}
|
||||
|
||||
private File getLevelFolderWithoutSimilarityMatching(ILevelWrapper level)
|
||||
{
|
||||
Stream<File> folders = getMatchingLevelFolders(level);
|
||||
Optional<File> first = folders.findFirst();
|
||||
if (first.isPresent())
|
||||
{
|
||||
LOGGER.info("Default Sub Dimension set to: [" + LodUtil.shortenString(first.get().getName(), 8) + "...]");
|
||||
return first.get();
|
||||
} else { // if no valid sub dimension was found, create a new one
|
||||
LOGGER.info("Default Sub Dimension not found. Creating: [" + level.getDimensionType().getDimensionName() + "]");
|
||||
return new File(folder, level.getDimensionType().getDimensionName());
|
||||
}
|
||||
}
|
||||
|
||||
public Stream<File> getMatchingLevelFolders(@Nullable ILevelWrapper level) {
|
||||
File[] folders = folder.listFiles();
|
||||
if (folders==null) return Stream.empty();
|
||||
return Arrays.stream(folders).filter(
|
||||
(f) -> {
|
||||
if (!isValidLevelFolder(f)) return false;
|
||||
return level==null || f.getName().equalsIgnoreCase(level.getDimensionType().getDimensionName());
|
||||
}
|
||||
).sorted();
|
||||
}
|
||||
|
||||
/** Returns true if the given folder holds valid Lod Dimension data */
|
||||
private static boolean isValidLevelFolder(File potentialFolder)
|
||||
{
|
||||
if (!potentialFolder.isDirectory())
|
||||
// it needs to be a folder
|
||||
return false;
|
||||
|
||||
File[] files = potentialFolder.listFiles((f) -> f.isDirectory() &&
|
||||
(f.getName().equalsIgnoreCase(RENDER_CACHE_FOLDER) || f.getName().equalsIgnoreCase(DATA_FOLDER)));
|
||||
// it needs to have folders with specified names in it
|
||||
return files != null && files.length != 0;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public File getRenderCacheFolder(ILevelWrapper level) {
|
||||
File levelFolder = levelToFileMap.get(level);
|
||||
if (levelFolder == null) return null;
|
||||
return new File(levelFolder, RENDER_CACHE_FOLDER);
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getDataFolder(ILevelWrapper level) {
|
||||
File levelFolder = levelToFileMap.get(level);
|
||||
if (levelFolder == null) return null;
|
||||
return new File(levelFolder, DATA_FOLDER);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
fileMatcher.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[ClientOnlySave@"+folder.getName()+"]";
|
||||
}
|
||||
/**
|
||||
* Designed for the Client_Only environment.
|
||||
*
|
||||
* @version 12-17-2022
|
||||
*/
|
||||
public class ClientOnlySaveStructure extends AbstractSaveStructure
|
||||
{
|
||||
final File folder;
|
||||
private static final IMinecraftClientWrapper MC_CLIENT = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class);
|
||||
public static final String INVALID_FILE_CHARACTERS_REGEX = "[\\\\/:*?\"<>|]";
|
||||
|
||||
SubDimensionLevelMatcher fileMatcher = null;
|
||||
final HashMap<ILevelWrapper, File> levelToFileMap = new HashMap<>();
|
||||
|
||||
|
||||
|
||||
public ClientOnlySaveStructure()
|
||||
{
|
||||
this.folder = new File(MC_CLIENT.getGameDirectory().getPath() +
|
||||
File.separatorChar + "Distant_Horizons_server_data" + File.separatorChar + getServerFolderName());
|
||||
|
||||
if (!this.folder.exists())
|
||||
{
|
||||
if (!this.folder.mkdirs())
|
||||
{
|
||||
LOGGER.warn("Unable to create folder [" + this.folder.getPath() + "]");
|
||||
//TODO: Deal with errors
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//================//
|
||||
// folder methods //
|
||||
//================//
|
||||
|
||||
@Override
|
||||
public File tryGetOrCreateLevelFolder(ILevelWrapper level)
|
||||
{
|
||||
return this.levelToFileMap.computeIfAbsent(level, (newLevel) ->
|
||||
{
|
||||
if (Config.Client.Multiplayer.multiDimensionRequiredSimilarity.get() == 0)
|
||||
{
|
||||
if (this.fileMatcher != null)
|
||||
{
|
||||
this.fileMatcher.close();
|
||||
this.fileMatcher = null;
|
||||
}
|
||||
return this.getLevelFolderWithoutSimilarityMatching(newLevel);
|
||||
}
|
||||
|
||||
if (this.fileMatcher == null || !this.fileMatcher.isFindingLevel(newLevel))
|
||||
{
|
||||
LOGGER.info("Loading level for world " + newLevel.getDimensionType().getDimensionName());
|
||||
this.fileMatcher = new SubDimensionLevelMatcher(newLevel, this.folder,
|
||||
this.getMatchingLevelFolders(newLevel).toArray(new File[0] /* surprisingly we don't need to create an array of any specific size for this to work */));
|
||||
}
|
||||
|
||||
File levelFile = this.fileMatcher.tryGetLevel();
|
||||
if (levelFile != null)
|
||||
{
|
||||
this.fileMatcher.close();
|
||||
this.fileMatcher = null;
|
||||
}
|
||||
return levelFile;
|
||||
});
|
||||
}
|
||||
|
||||
private File getLevelFolderWithoutSimilarityMatching(ILevelWrapper level)
|
||||
{
|
||||
List<File> folders = this.getMatchingLevelFolders(level);
|
||||
if (folders.size() > 0 && folders.get(0) == null)
|
||||
{
|
||||
LOGGER.info("Default Sub Dimension set to: [" + LodUtil.shortenString(folders.get(0).getName(), 8) + "...]");
|
||||
return folders.get(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
// if no valid sub dimension was found, create a new one
|
||||
LOGGER.info("Default Sub Dimension not found. Creating: [" + level.getDimensionType().getDimensionName() + "]");
|
||||
return new File(this.folder, level.getDimensionType().getDimensionName());
|
||||
}
|
||||
}
|
||||
|
||||
public List<File> getMatchingLevelFolders(@Nullable ILevelWrapper level)
|
||||
{
|
||||
File[] folders = this.folder.listFiles();
|
||||
if (folders == null)
|
||||
{
|
||||
return new ArrayList<>(0);
|
||||
}
|
||||
|
||||
Stream<File> fileStream = Arrays.stream(folders).filter(
|
||||
(folder) ->
|
||||
{
|
||||
if (!isValidLevelFolder(folder))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return level == null || folder.getName().equalsIgnoreCase(level.getDimensionType().getDimensionName());
|
||||
}
|
||||
}
|
||||
).sorted();
|
||||
|
||||
return fileStream.toList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getRenderCacheFolder(ILevelWrapper level)
|
||||
{
|
||||
File levelFolder = this.levelToFileMap.get(level);
|
||||
if (levelFolder == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return new File(levelFolder, RENDER_CACHE_FOLDER);
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getDataFolder(ILevelWrapper level)
|
||||
{
|
||||
File levelFolder = this.levelToFileMap.get(level);
|
||||
if (levelFolder == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return new File(levelFolder, DATA_FOLDER);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//================//
|
||||
// helper methods //
|
||||
//================//
|
||||
|
||||
/** Returns true if the given folder holds valid Lod Dimension data */
|
||||
private static boolean isValidLevelFolder(File potentialFolder)
|
||||
{
|
||||
if (!potentialFolder.isDirectory())
|
||||
{
|
||||
// a valid level folder needs to be a folder
|
||||
return false;
|
||||
}
|
||||
|
||||
// filter out any non-DH folders
|
||||
File[] files = potentialFolder.listFiles((file) ->
|
||||
file.isDirectory() &&
|
||||
(file.getName().equalsIgnoreCase(RENDER_CACHE_FOLDER) || file.getName().equalsIgnoreCase(DATA_FOLDER)));
|
||||
|
||||
// a valid level folder needs to have DH specific folders in it
|
||||
return files != null && files.length != 0;
|
||||
}
|
||||
|
||||
/** Generated from the server the client is currently connected to. */
|
||||
private static String getServerFolderName()
|
||||
{
|
||||
// parse the current server's IP
|
||||
ParsedIp parsedIp = new ParsedIp(MC_CLIENT.getCurrentServerIp());
|
||||
String serverIpCleaned = parsedIp.ip.replaceAll(INVALID_FILE_CHARACTERS_REGEX, "");
|
||||
String serverPortCleaned = parsedIp.port != null ? parsedIp.port.replaceAll(INVALID_FILE_CHARACTERS_REGEX, "") : "";
|
||||
|
||||
|
||||
// determine the auto folder name format
|
||||
EServerFolderNameMode folderNameMode = Config.Client.Multiplayer.serverFolderNameMode.get();
|
||||
if (folderNameMode == EServerFolderNameMode.AUTO)
|
||||
{
|
||||
if (parsedIp.isLan())
|
||||
{
|
||||
// LAN
|
||||
folderNameMode = EServerFolderNameMode.NAME_IP;
|
||||
}
|
||||
else
|
||||
{
|
||||
// normal multiplayer
|
||||
folderNameMode = EServerFolderNameMode.NAME_IP_PORT;
|
||||
}
|
||||
// TODO can we determine if a server is a Mojang operated Realm based on the IP?
|
||||
// If so we should also default to either NAME_IP or just NAME
|
||||
}
|
||||
String serverName = MC_CLIENT.getCurrentServerName().replaceAll(INVALID_FILE_CHARACTERS_REGEX, "");
|
||||
String serverMcVersion = MC_CLIENT.getCurrentServerVersion().replaceAll(INVALID_FILE_CHARACTERS_REGEX, "");
|
||||
|
||||
|
||||
// generate the folder name
|
||||
String folderName;
|
||||
switch (folderNameMode)
|
||||
{
|
||||
default:
|
||||
case NAME_ONLY:
|
||||
folderName = serverName;
|
||||
break;
|
||||
|
||||
case NAME_IP:
|
||||
folderName = serverName + ", IP " + serverIpCleaned;
|
||||
break;
|
||||
case NAME_IP_PORT:
|
||||
folderName = serverName + ", IP " + serverIpCleaned + (serverPortCleaned.length() != 0 ? ("-" + serverPortCleaned) : "");
|
||||
break;
|
||||
case NAME_IP_PORT_MC_VERSION:
|
||||
folderName = serverName + ", IP " + serverIpCleaned + (serverPortCleaned.length() != 0 ? ("-" + serverPortCleaned) : "") + ", GameVersion " + serverMcVersion;
|
||||
break;
|
||||
}
|
||||
|
||||
// PercentEscaper makes the characters all part of the standard alphameric character set
|
||||
// This fixes some issues when the server is named something in other languages
|
||||
return new PercentEscaper("", true).escape(folderName);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//==================//
|
||||
// override methods //
|
||||
//==================//
|
||||
|
||||
@Override
|
||||
public void close() { this.fileMatcher.close(); }
|
||||
|
||||
@Override
|
||||
public String toString() { return "[" + this.getClass().getSimpleName() + "@" + this.folder.getName() + "]"; }
|
||||
|
||||
}
|
||||
|
||||
@@ -5,41 +5,61 @@ import com.seibel.lod.core.wrapperInterfaces.world.IServerLevelWrapper;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public class LocalSaveStructure extends SaveStructure {
|
||||
/**
|
||||
* Designed for Client_Server & Server_Only environments.
|
||||
*
|
||||
* @version 2022-12-17
|
||||
*/
|
||||
public class LocalSaveStructure extends AbstractSaveStructure
|
||||
{
|
||||
public static final String SERVER_FOLDER_NAME = "Distant_Horizons";
|
||||
|
||||
private File debugPath = new File("");
|
||||
|
||||
// Fit for Client_Server & Server_Only environment
|
||||
public LocalSaveStructure() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public File tryGetLevelFolder(ILevelWrapper wrapper) {
|
||||
|
||||
|
||||
public LocalSaveStructure() { }
|
||||
|
||||
|
||||
|
||||
//================//
|
||||
// folder methods //
|
||||
//================//
|
||||
|
||||
@Override
|
||||
public File tryGetOrCreateLevelFolder(ILevelWrapper wrapper)
|
||||
{
|
||||
IServerLevelWrapper serverSide = (IServerLevelWrapper) wrapper;
|
||||
debugPath = new File(serverSide.getSaveFolder(), "Distant_Horizons");
|
||||
this.debugPath = new File(serverSide.getSaveFolder(), "Distant_Horizons");
|
||||
return new File(serverSide.getSaveFolder(), "Distant_Horizons");
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getRenderCacheFolder(ILevelWrapper level) {
|
||||
public File getRenderCacheFolder(ILevelWrapper level)
|
||||
{
|
||||
IServerLevelWrapper serverSide = (IServerLevelWrapper) level;
|
||||
debugPath = new File(serverSide.getSaveFolder(), "Distant_Horizons");
|
||||
this.debugPath = new File(serverSide.getSaveFolder(), "Distant_Horizons");
|
||||
return new File(new File(serverSide.getSaveFolder(), "Distant_Horizons"), RENDER_CACHE_FOLDER);
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getDataFolder(ILevelWrapper level) {
|
||||
public File getDataFolder(ILevelWrapper level)
|
||||
{
|
||||
IServerLevelWrapper serverSide = (IServerLevelWrapper) level;
|
||||
debugPath = new File(serverSide.getSaveFolder(), "Distant_Horizons");
|
||||
return new File(new File(serverSide.getSaveFolder(), "Distant_Horizons"), DATA_FOLDER);
|
||||
this.debugPath = new File(serverSide.getSaveFolder(), SERVER_FOLDER_NAME);
|
||||
return new File(new File(serverSide.getSaveFolder(), SERVER_FOLDER_NAME), DATA_FOLDER);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//==================//
|
||||
// override methods //
|
||||
//==================//
|
||||
|
||||
@Override
|
||||
public void close() throws Exception { }
|
||||
|
||||
@Override
|
||||
public void close() throws Exception {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[LocalSave at ["+debugPath+"] ]";
|
||||
}
|
||||
public String toString() { return "[" + this.getClass().getSimpleName() + "@" + this.debugPath + "]"; }
|
||||
|
||||
}
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
package com.seibel.lod.core.file.structure;
|
||||
|
||||
import com.seibel.lod.core.logging.DhLoggerBuilder;
|
||||
import com.seibel.lod.core.wrapperInterfaces.world.ILevelWrapper;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public abstract class SaveStructure implements AutoCloseable {
|
||||
|
||||
public static final String RENDER_CACHE_FOLDER = "cache";
|
||||
public static final String DATA_FOLDER = "data";
|
||||
|
||||
protected static final Logger LOGGER = DhLoggerBuilder.getLogger();
|
||||
|
||||
public abstract File tryGetLevelFolder(ILevelWrapper wrapper);
|
||||
|
||||
public abstract File getRenderCacheFolder(ILevelWrapper world);
|
||||
public abstract File getDataFolder(ILevelWrapper world);
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ package com.seibel.lod.core.util;
|
||||
|
||||
import com.seibel.lod.core.file.datafile.IDataSourceProvider;
|
||||
import com.seibel.lod.core.file.renderfile.IRenderSourceProvider;
|
||||
import com.seibel.lod.core.file.structure.SaveStructure;
|
||||
import com.seibel.lod.core.file.structure.AbstractSaveStructure;
|
||||
import com.seibel.lod.core.logging.DhLoggerBuilder;
|
||||
import com.seibel.lod.core.wrapperInterfaces.world.ILevelWrapper;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
@@ -18,7 +18,7 @@ public class FileScanUtil {
|
||||
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
|
||||
public static final int MAX_SCAN_DEPTH = 5;
|
||||
public static final String LOD_FILE_POSTFIX = ".lod";
|
||||
public static void scanFile(SaveStructure save, ILevelWrapper level,
|
||||
public static void scanFile(AbstractSaveStructure save, ILevelWrapper level,
|
||||
@Nullable IDataSourceProvider dataSource,
|
||||
@Nullable IRenderSourceProvider renderSource) {
|
||||
if (dataSource != null) {
|
||||
|
||||
@@ -39,7 +39,7 @@ public class DhClientServerWorld extends AbstractDhWorld implements IDhClientWor
|
||||
public DhClientServerLevel getOrLoadLevel(ILevelWrapper wrapper) {
|
||||
if (wrapper instanceof IServerLevelWrapper) {
|
||||
return levelObjMap.computeIfAbsent(wrapper, (w) -> {
|
||||
File levelFile = saveStructure.tryGetLevelFolder(w);
|
||||
File levelFile = saveStructure.tryGetOrCreateLevelFolder(w);
|
||||
LodUtil.assertTrue(levelFile != null);
|
||||
DhClientServerLevel level = new DhClientServerLevel(saveStructure, (IServerLevelWrapper) w);
|
||||
dhLevels.add(level);
|
||||
|
||||
@@ -35,7 +35,7 @@ public class DhClientWorld extends AbstractDhWorld implements IDhClientWorld
|
||||
if (!(wrapper instanceof IClientLevelWrapper)) return null;
|
||||
|
||||
return levels.computeIfAbsent((IClientLevelWrapper) wrapper, (w) -> {
|
||||
File level = saveStructure.tryGetLevelFolder(wrapper);
|
||||
File level = saveStructure.tryGetOrCreateLevelFolder(wrapper);
|
||||
if (level == null) return null;
|
||||
return new DhClientLevel(saveStructure, w);
|
||||
});
|
||||
|
||||
@@ -27,7 +27,7 @@ public class DhServerWorld extends AbstractDhWorld implements IDhServerWorld
|
||||
public DhServerLevel getOrLoadLevel(ILevelWrapper wrapper) {
|
||||
if (!(wrapper instanceof IServerLevelWrapper)) return null;
|
||||
return levels.computeIfAbsent((IServerLevelWrapper) wrapper, (w) -> {
|
||||
File levelFile = saveStructure.tryGetLevelFolder(wrapper);
|
||||
File levelFile = saveStructure.tryGetOrCreateLevelFolder(wrapper);
|
||||
LodUtil.assertTrue(levelFile != null);
|
||||
return new DhServerLevel(saveStructure, w);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user