From 26d42209672f4f8102e12bb36992186a3a527992 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Tue, 9 Dec 2025 07:12:33 -0600 Subject: [PATCH] Add logging/messaging for corrupted DB files --- .../GeneratedFullDataSourceProvider.java | 6 ++- .../RemoteFullDataSourceProvider.java | 5 ++- .../V1/FullDataSourceProviderV1.java | 19 +-------- .../file/fullDatafile/V2/DataMigratorV1.java | 5 ++- .../V2/FullDataSourceProviderV2.java | 41 +++++++++++-------- .../distanthorizons/core/jar/JarMain.java | 2 +- .../core/level/AbstractDhLevel.java | 9 ++-- .../core/level/AbstractDhServerLevel.java | 15 ++++--- .../core/level/DhClientLevel.java | 15 ++++++- .../core/level/DhClientServerLevel.java | 8 +++- .../core/level/DhServerLevel.java | 12 ++++-- .../core/level/ServerLevelModule.java | 5 ++- .../core/sql/repo/AbstractDhRepo.java | 10 ++--- .../core/sql/repo/BeaconBeamRepo.java | 3 +- .../core/sql/repo/ChunkHashRepo.java | 3 +- .../core/sql/repo/FullDataSourceV1Repo.java | 3 +- .../core/sql/repo/FullDataSourceV2Repo.java | 2 +- .../core/world/AbstractDhServerWorld.java | 8 +++- .../core/world/DhClientServerWorld.java | 20 +++++++-- .../core/world/DhClientWorld.java | 21 +++++++++- .../core/world/DhServerWorld.java | 19 ++++++++- .../core/world/IDhServerWorld.java | 2 + .../distanthorizons/core/world/IDhWorld.java | 1 + .../testItems/sql/TestCompoundKeyRepo.java | 3 +- .../testItems/sql/TestPrimaryKeyRepo.java | 3 +- .../src/test/java/tests/DhRepoSqliteTest.java | 9 ++-- 26 files changed, 171 insertions(+), 78 deletions(-) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/GeneratedFullDataSourceProvider.java b/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/GeneratedFullDataSourceProvider.java index 7d21a5898..3423ba02e 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/GeneratedFullDataSourceProvider.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/GeneratedFullDataSourceProvider.java @@ -47,6 +47,8 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.io.File; +import java.io.IOException; +import java.sql.SQLException; import java.util.*; import java.util.concurrent.*; import java.util.concurrent.atomic.AtomicInteger; @@ -80,8 +82,8 @@ public class GeneratedFullDataSourceProvider extends FullDataSourceProviderV2 im // constructor // //=============// - public GeneratedFullDataSourceProvider(IDhLevel level, ISaveStructure saveStructure) { super(level, saveStructure); } - public GeneratedFullDataSourceProvider(IDhLevel level, ISaveStructure saveStructure, @Nullable File saveDirOverride) + public GeneratedFullDataSourceProvider(IDhLevel level, ISaveStructure saveStructure) throws SQLException, IOException { super(level, saveStructure); } + public GeneratedFullDataSourceProvider(IDhLevel level, ISaveStructure saveStructure, @Nullable File saveDirOverride) throws SQLException, IOException { super(level, saveStructure, saveDirOverride); diff --git a/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/RemoteFullDataSourceProvider.java b/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/RemoteFullDataSourceProvider.java index 2aaa265c7..80bae225c 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/RemoteFullDataSourceProvider.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/RemoteFullDataSourceProvider.java @@ -31,6 +31,8 @@ import com.seibel.distanthorizons.core.logging.DhLogger; import org.jetbrains.annotations.Nullable; import java.io.File; +import java.io.IOException; +import java.sql.SQLException; import java.util.Collections; import java.util.Set; import java.util.concurrent.TimeUnit; @@ -58,7 +60,8 @@ public class RemoteFullDataSourceProvider extends GeneratedFullDataSourceProvide public RemoteFullDataSourceProvider( IDhLevel level, ISaveStructure saveStructure, @Nullable File saveDirOverride, - @Nullable SyncOnLoadRequestQueue syncOnLoadRequestQueue) + @Nullable SyncOnLoadRequestQueue syncOnLoadRequestQueue + ) throws SQLException, IOException { super(level, saveStructure, saveDirOverride); this.syncOnLoadRequestQueue = syncOnLoadRequestQueue; diff --git a/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/V1/FullDataSourceProviderV1.java b/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/V1/FullDataSourceProviderV1.java index 2124a90a7..c15542e86 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/V1/FullDataSourceProviderV1.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/V1/FullDataSourceProviderV1.java @@ -43,7 +43,7 @@ public class FullDataSourceProviderV1 // constructor // //=============// - public FullDataSourceProviderV1(TDhLevel level, File saveDir) + public FullDataSourceProviderV1(TDhLevel level, File saveDir) throws SQLException, IOException { this.level = level; this.saveDir = saveDir; @@ -52,7 +52,7 @@ public class FullDataSourceProviderV1 LOGGER.warn("Unable to create full data folder, file saving may fail."); } - this.repo = this.createRepo(); + this.repo = new FullDataSourceV1Repo(AbstractDhRepo.DEFAULT_DATABASE_TYPE, new File(this.saveDir.getPath() + File.separator + ISaveStructure.DATABASE_NAME)); } @@ -61,21 +61,6 @@ public class FullDataSourceProviderV1 // abstract methods // //==================// - /** When this is called the parent folders should be created */ - protected FullDataSourceV1Repo createRepo() - { - try - { - return new FullDataSourceV1Repo(AbstractDhRepo.DEFAULT_DATABASE_TYPE, new File(this.saveDir.getPath() + File.separator + ISaveStructure.DATABASE_NAME)); - } - catch (SQLException e) - { - // should only happen if there is an issue with the database (it's locked or can't be created if missing) - // or the database update failed - throw new RuntimeException(e); - } - } - protected FullDataSourceV1 createDataSourceFromDto(FullDataSourceV1DTO dto) throws InterruptedException, IOException, DataCorruptedException { FullDataSourceV1 dataSource = FullDataSourceV1.createEmpty(dto.pos); diff --git a/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/V2/DataMigratorV1.java b/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/V2/DataMigratorV1.java index fef122cce..000ddbb2c 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/V2/DataMigratorV1.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/V2/DataMigratorV1.java @@ -14,6 +14,8 @@ import com.seibel.distanthorizons.core.render.renderer.IDebugRenderable; import com.seibel.distanthorizons.core.util.threading.ThreadPoolUtil; import java.io.File; +import java.io.IOException; +import java.sql.SQLException; import java.text.NumberFormat; import java.util.ArrayList; import java.util.List; @@ -62,7 +64,8 @@ public class DataMigratorV1 implements IDebugRenderable, AutoCloseable public DataMigratorV1( FullDataUpdaterV2 dataUpdater, - IDhLevel level, String levelId, File saveDir) + IDhLevel level, String levelId, File saveDir + ) throws SQLException, IOException { this.dataUpdater = dataUpdater; this.saveDir = saveDir; diff --git a/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/V2/FullDataSourceProviderV2.java b/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/V2/FullDataSourceProviderV2.java index 32dad829b..c95e01c32 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/V2/FullDataSourceProviderV2.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/V2/FullDataSourceProviderV2.java @@ -96,11 +96,11 @@ public class FullDataSourceProviderV2 implements IDebugRenderable, AutoCloseable // constructor // //=============// - public FullDataSourceProviderV2(IDhLevel level, ISaveStructure saveStructure) { this(level, saveStructure, null); } - public FullDataSourceProviderV2(IDhLevel level, ISaveStructure saveStructure, @Nullable File saveDirOverride) + public FullDataSourceProviderV2(IDhLevel level, ISaveStructure saveStructure) throws SQLException, IOException { this(level, saveStructure, null); } + public FullDataSourceProviderV2(IDhLevel level, ISaveStructure saveStructure, @Nullable File saveDirOverride) throws SQLException, IOException { this.saveDir = (saveDirOverride == null) ? saveStructure.getSaveFolder(level.getLevelWrapper()) : saveDirOverride; - this.repo = this.createRepo(); + this.repo = new FullDataSourceV2Repo(AbstractDhRepo.DEFAULT_DATABASE_TYPE, new File(this.saveDir.getPath() + File.separator + ISaveStructure.DATABASE_NAME)); this.level = level; this.levelId = this.level.getLevelWrapper().getDhIdentifier(); @@ -112,19 +112,6 @@ public class FullDataSourceProviderV2 implements IDebugRenderable, AutoCloseable DebugRenderer.register(this, Config.Client.Advanced.Debugging.DebugWireframe.showFullDataUpdateStatus); } - private FullDataSourceV2Repo createRepo() - { - try - { - return new FullDataSourceV2Repo(AbstractDhRepo.DEFAULT_DATABASE_TYPE, new File(this.saveDir.getPath() + File.separator + ISaveStructure.DATABASE_NAME)); - } - catch (SQLException e) - { - // should only happen if there is an issue with the database (it's locked or the folder path is missing) - // or the database update failed - throw new RuntimeException(e); - } - } @@ -239,7 +226,27 @@ public class FullDataSourceProviderV2 implements IDebugRenderable, AutoCloseable catch (InterruptedException ignore) { } catch (IOException e) { - LOGGER.warn("File read Error for pos ["+DhSectionPos.toString(pos)+"], error: "+e.getMessage(), e); + String message = e.getMessage(); + if (CORRUPT_DATA_ERRORS_LOGGED.add(message)) + { + LOGGER.warn("File read Error for pos [" + DhSectionPos.toString(pos) + "], this error message will only be logged once, error: [" + message + "].", e); + } + } + catch (IllegalStateException e) + { + String message = e.getMessage(); + if (CORRUPT_DATA_ERRORS_LOGGED.add(message)) + { + LOGGER.warn("Incorrectly formatted data for: [" + DhSectionPos.toString(pos) + "], this error message will only be logged once, error: [" + message + "].", e); + } + } + catch (Exception e) + { + String message = e.getMessage(); + if (CORRUPT_DATA_ERRORS_LOGGED.add(message)) + { + LOGGER.warn("Unexpected error getting: [" + DhSectionPos.toString(pos) + "], this error message will only be logged once, error: [" + message + "].", e); + } } // an error occurred diff --git a/core/src/main/java/com/seibel/distanthorizons/core/jar/JarMain.java b/core/src/main/java/com/seibel/distanthorizons/core/jar/JarMain.java index 806b3baeb..982d0b073 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/jar/JarMain.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/jar/JarMain.java @@ -216,7 +216,7 @@ public class JarMain { repo = new FullDataSourceV2Repo(FullDataSourceV2Repo.DEFAULT_DATABASE_TYPE, dbFile); } - catch (SQLException e) + catch (SQLException | IOException e) { LOGGER.error("Failed to initialize connection with database: ["+exportFile.getAbsolutePath()+"], error: ["+e.getMessage()+"].", e); return; diff --git a/core/src/main/java/com/seibel/distanthorizons/core/level/AbstractDhLevel.java b/core/src/main/java/com/seibel/distanthorizons/core/level/AbstractDhLevel.java index 482259b00..a855d3ab7 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/level/AbstractDhLevel.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/level/AbstractDhLevel.java @@ -55,6 +55,7 @@ import org.jetbrains.annotations.Nullable; import java.awt.*; import java.io.File; +import java.io.IOException; import java.sql.SQLException; import java.util.ArrayList; import java.util.HashMap; @@ -106,9 +107,9 @@ public abstract class AbstractDhLevel implements IDhLevel { newChunkHashRepo = new ChunkHashRepo(AbstractDhRepo.DEFAULT_DATABASE_TYPE, databaseFile); } - catch (SQLException e) + catch (SQLException | IOException e) { - LOGGER.error("Unable to create [ChunkHashRepo], error: ["+e.getMessage()+"].", e); + LOGGER.fatal("Unable to create ["+ChunkHashRepo.class.getSimpleName()+"], error: ["+e.getMessage()+"].", e); } this.chunkHashRepo = newChunkHashRepo; @@ -119,9 +120,9 @@ public abstract class AbstractDhLevel implements IDhLevel { newBeaconBeamRepo = new BeaconBeamRepo(AbstractDhRepo.DEFAULT_DATABASE_TYPE, databaseFile); } - catch (SQLException e) + catch (SQLException | IOException e) { - LOGGER.error("Unable to create [BeaconBeamRepo], error: ["+e.getMessage()+"].", e); + LOGGER.error("Unable to create ["+BeaconBeamRepo.class.getSimpleName()+"], error: ["+e.getMessage()+"].", e); } this.beaconBeamRepo = newBeaconBeamRepo; } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/level/AbstractDhServerLevel.java b/core/src/main/java/com/seibel/distanthorizons/core/level/AbstractDhServerLevel.java index 5a53bde5f..e30a2e985 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/level/AbstractDhServerLevel.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/level/AbstractDhServerLevel.java @@ -29,6 +29,8 @@ import com.seibel.distanthorizons.core.logging.DhLogger; import org.jetbrains.annotations.NotNull; import javax.annotation.Nullable; +import java.io.IOException; +import java.sql.SQLException; import java.util.List; import java.util.concurrent.*; @@ -56,16 +58,19 @@ public abstract class AbstractDhServerLevel extends AbstractDhLevel implements I // constructor // //=============// - public AbstractDhServerLevel(ISaveStructure saveStructure, IServerLevelWrapper serverLevelWrapper, ServerPlayerStateManager serverPlayerStateManager) - { - this(saveStructure, serverLevelWrapper, serverPlayerStateManager, true); - } + public AbstractDhServerLevel( + ISaveStructure saveStructure, + IServerLevelWrapper serverLevelWrapper, + ServerPlayerStateManager serverPlayerStateManager + ) throws SQLException, IOException + { this(saveStructure, serverLevelWrapper, serverPlayerStateManager, true); } + public AbstractDhServerLevel( ISaveStructure saveStructure, IServerLevelWrapper serverLevelWrapper, ServerPlayerStateManager serverPlayerStateManager, boolean runRepoReliantSetup - ) + ) throws SQLException, IOException { if (saveStructure.getSaveFolder(serverLevelWrapper).mkdirs()) { diff --git a/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientLevel.java b/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientLevel.java index 21554c235..7d3d520cd 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientLevel.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientLevel.java @@ -49,6 +49,8 @@ import org.jetbrains.annotations.Nullable; import javax.annotation.CheckForNull; import java.awt.*; import java.io.File; +import java.io.IOException; +import java.sql.SQLException; import java.util.*; import java.util.List; import java.util.concurrent.CompletableFuture; @@ -94,9 +96,18 @@ public class DhClientLevel extends AbstractDhLevel implements IDhClientLevel // constructor // //=============// - public DhClientLevel(ISaveStructure saveStructure, IClientLevelWrapper clientLevelWrapper, @Nullable ClientNetworkState networkState) + public DhClientLevel( + ISaveStructure saveStructure, + IClientLevelWrapper clientLevelWrapper, + @Nullable ClientNetworkState networkState + ) throws SQLException, IOException { this(saveStructure, clientLevelWrapper, null, networkState); } - public DhClientLevel(ISaveStructure saveStructure, IClientLevelWrapper clientLevelWrapper, @Nullable File fullDataSaveDirOverride, @Nullable ClientNetworkState networkState) + public DhClientLevel( + ISaveStructure saveStructure, + IClientLevelWrapper clientLevelWrapper, + @Nullable File fullDataSaveDirOverride, + @Nullable ClientNetworkState networkState + ) throws SQLException, IOException { File saveFolder = saveStructure.getSaveFolder(clientLevelWrapper); File pre23Folder = saveStructure.getPre23SaveFolder(clientLevelWrapper); diff --git a/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientServerLevel.java b/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientServerLevel.java index 680be05f8..64e39251f 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientServerLevel.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientServerLevel.java @@ -33,6 +33,8 @@ import com.seibel.distanthorizons.core.wrapperInterfaces.world.IServerLevelWrapp import org.jetbrains.annotations.Nullable; import java.awt.*; +import java.io.IOException; +import java.sql.SQLException; import java.util.List; /** The level used for a singleplayer world */ @@ -48,7 +50,11 @@ public class DhClientServerLevel extends AbstractDhServerLevel implements IDhCli // constructor // //=============// - public DhClientServerLevel(ISaveStructure saveStructure, IServerLevelWrapper serverLevelWrapper, ServerPlayerStateManager serverPlayerStateManager) + public DhClientServerLevel( + ISaveStructure saveStructure, + IServerLevelWrapper serverLevelWrapper, + ServerPlayerStateManager serverPlayerStateManager + ) throws SQLException, IOException { super(saveStructure, serverLevelWrapper, serverPlayerStateManager, false); diff --git a/core/src/main/java/com/seibel/distanthorizons/core/level/DhServerLevel.java b/core/src/main/java/com/seibel/distanthorizons/core/level/DhServerLevel.java index 2539acd5d..3f0b77112 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/level/DhServerLevel.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/level/DhServerLevel.java @@ -27,6 +27,8 @@ import com.seibel.distanthorizons.core.render.renderer.generic.GenericObjectRend import com.seibel.distanthorizons.core.wrapperInterfaces.world.IServerLevelWrapper; import org.jetbrains.annotations.Nullable; +import java.io.IOException; +import java.sql.SQLException; import java.util.List; public class DhServerLevel extends AbstractDhServerLevel @@ -35,10 +37,12 @@ public class DhServerLevel extends AbstractDhServerLevel // constructor // //=============// - public DhServerLevel(ISaveStructure saveStructure, IServerLevelWrapper serverLevelWrapper, ServerPlayerStateManager serverPlayerStateManager) - { - super(saveStructure, serverLevelWrapper, serverPlayerStateManager); - } + public DhServerLevel( + ISaveStructure saveStructure, + IServerLevelWrapper serverLevelWrapper, + ServerPlayerStateManager serverPlayerStateManager + ) throws SQLException, IOException + { super(saveStructure, serverLevelWrapper, serverPlayerStateManager); } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/level/ServerLevelModule.java b/core/src/main/java/com/seibel/distanthorizons/core/level/ServerLevelModule.java index 4f2212363..d9a1c3442 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/level/ServerLevelModule.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/level/ServerLevelModule.java @@ -28,6 +28,9 @@ import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; import com.seibel.distanthorizons.coreapi.DependencyInjection.WorldGeneratorInjector; import com.seibel.distanthorizons.core.logging.DhLogger; +import java.io.IOException; +import java.sql.SQLException; + public class ServerLevelModule implements AutoCloseable { private static final DhLogger LOGGER = new DhLoggerBuilder().build(); @@ -44,7 +47,7 @@ public class ServerLevelModule implements AutoCloseable // constructor // //=============// - public ServerLevelModule(IDhServerLevel parentServerLevel, ISaveStructure saveStructure) + public ServerLevelModule(IDhServerLevel parentServerLevel, ISaveStructure saveStructure) throws SQLException, IOException { this.parentServerLevel = parentServerLevel; this.saveStructure = saveStructure; diff --git a/core/src/main/java/com/seibel/distanthorizons/core/sql/repo/AbstractDhRepo.java b/core/src/main/java/com/seibel/distanthorizons/core/sql/repo/AbstractDhRepo.java index c015ac836..2c1733665 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/sql/repo/AbstractDhRepo.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/sql/repo/AbstractDhRepo.java @@ -75,7 +75,7 @@ public abstract class AbstractDhRepo> implemen //=============// /** @throws SQLException if the repo is unable to access the database or has trouble updating said database. */ - public AbstractDhRepo(String databaseType, File databaseFile, Class dtoClass) throws SQLException + public AbstractDhRepo(String databaseType, File databaseFile, Class dtoClass) throws SQLException, IOException { this.databaseType = databaseType; this.databaseFile = databaseFile; @@ -107,7 +107,7 @@ public abstract class AbstractDhRepo> implemen { if (!parentFolder.mkdirs()) { - throw new RuntimeException("Unable to create the necessary parent folders for the database file at location ["+databaseFile.getPath()+"]."); + throw new IOException("Unable to create the necessary parent folders for the database file at location ["+databaseFile.getPath()+"]."); } } @@ -119,18 +119,18 @@ public abstract class AbstractDhRepo> implemen } catch (IOException e) { - throw new RuntimeException("Unable to create database file at location ["+databaseFile.getPath()+"] due to error: ["+e.getMessage()+"]", e); + throw new IOException("Unable to create database file at location ["+databaseFile.getPath()+"] due to error: ["+e.getMessage()+"]", e); } } } if (!databaseFile.canRead()) { - throw new RuntimeException("Unable to read database file at location ["+databaseFile.getPath()+"], please make sure the folder and file has the correct permissions."); + throw new IOException("Unable to read database file at location ["+databaseFile.getPath()+"], please make sure the folder and file has the correct permissions."); } if (!databaseFile.canWrite()) { - throw new RuntimeException("Unable to write database file at location ["+databaseFile.getPath()+"], please make sure the folder and file aren't set to read-only."); + throw new IOException("Unable to write database file at location ["+databaseFile.getPath()+"], please make sure the folder and file aren't set to read-only."); } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/sql/repo/BeaconBeamRepo.java b/core/src/main/java/com/seibel/distanthorizons/core/sql/repo/BeaconBeamRepo.java index 4f0ed48ed..97c9b08b4 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/sql/repo/BeaconBeamRepo.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/sql/repo/BeaconBeamRepo.java @@ -31,6 +31,7 @@ import org.jetbrains.annotations.Nullable; import java.awt.*; import java.io.File; +import java.io.IOException; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; @@ -47,7 +48,7 @@ public class BeaconBeamRepo extends AbstractDhRepo // constructor // //=============// - public BeaconBeamRepo(String databaseType, File databaseFile) throws SQLException + public BeaconBeamRepo(String databaseType, File databaseFile) throws SQLException, IOException { super(databaseType, databaseFile, BeaconBeamDTO.class); } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/sql/repo/ChunkHashRepo.java b/core/src/main/java/com/seibel/distanthorizons/core/sql/repo/ChunkHashRepo.java index 5ae49fa98..ffe3f94ef 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/sql/repo/ChunkHashRepo.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/sql/repo/ChunkHashRepo.java @@ -26,6 +26,7 @@ import com.seibel.distanthorizons.core.logging.DhLogger; import org.jetbrains.annotations.Nullable; import java.io.File; +import java.io.IOException; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; @@ -40,7 +41,7 @@ public class ChunkHashRepo extends AbstractDhRepo // constructor // //=============// - public ChunkHashRepo(String databaseType, File databaseFile) throws SQLException + public ChunkHashRepo(String databaseType, File databaseFile) throws SQLException, IOException { super(databaseType, databaseFile, ChunkHashDTO.class); } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/sql/repo/FullDataSourceV1Repo.java b/core/src/main/java/com/seibel/distanthorizons/core/sql/repo/FullDataSourceV1Repo.java index ce0b32ce8..e2eb58b5b 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/sql/repo/FullDataSourceV1Repo.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/sql/repo/FullDataSourceV1Repo.java @@ -28,6 +28,7 @@ import it.unimi.dsi.fastutil.longs.LongArrayList; import org.jetbrains.annotations.Nullable; import java.io.File; +import java.io.IOException; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; @@ -45,7 +46,7 @@ public class FullDataSourceV1Repo extends AbstractDhRepo it = this.dhLevelByLevelWrapper.values().stream().distinct().iterator(); while (it.hasNext()) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/world/DhClientServerWorld.java b/core/src/main/java/com/seibel/distanthorizons/core/world/DhClientServerWorld.java index ce9693d0a..fc9725406 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/world/DhClientServerWorld.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/world/DhClientServerWorld.java @@ -19,6 +19,7 @@ package com.seibel.distanthorizons.core.world; +import com.seibel.distanthorizons.core.api.internal.ClientApi; import com.seibel.distanthorizons.core.level.DhClientServerLevel; import com.seibel.distanthorizons.core.util.ThreadUtil; import com.seibel.distanthorizons.core.util.objects.EventLoop; @@ -67,9 +68,22 @@ public class DhClientServerWorld extends AbstractDhServerWorld { - DhClientServerLevel level = new DhClientServerLevel(this.saveStructure, (IServerLevelWrapper) levelWrapper, this.getServerPlayerStateManager()); - this.dhLevels.add(level); - return level; + try + { + DhClientServerLevel level = new DhClientServerLevel(this.saveStructure, (IServerLevelWrapper) levelWrapper, this.getServerPlayerStateManager()); + this.dhLevels.add(level); + return level; + } + catch (Exception e) + { + LOGGER.fatal("Failed to load client-server level, error: ["+e.getMessage()+"].", e); + + ClientApi.INSTANCE.showChatMessageNextFrame(// red text + "\u00A7c" + "Distant Horizons: ClientServer level loading failed." + "\u00A7r \n" + + "Unable to load level ["+levelWrapper.getDhIdentifier()+"], LODs may not appear. See log for more information."); + + return null; + } }); } else diff --git a/core/src/main/java/com/seibel/distanthorizons/core/world/DhClientWorld.java b/core/src/main/java/com/seibel/distanthorizons/core/world/DhClientWorld.java index 0cc4b6088..9fec8cf1f 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/world/DhClientWorld.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/world/DhClientWorld.java @@ -19,6 +19,7 @@ package com.seibel.distanthorizons.core.world; +import com.seibel.distanthorizons.core.api.internal.ClientApi; import com.seibel.distanthorizons.core.file.structure.ClientOnlySaveStructure; import com.seibel.distanthorizons.core.level.DhClientLevel; import com.seibel.distanthorizons.core.level.IDhLevel; @@ -74,8 +75,24 @@ public class DhClientWorld extends AbstractDhWorld implements IDhClientWorld return null; } - return this.levels.computeIfAbsent((IClientLevelWrapper) wrapper, - (clientLevelWrapper) -> new DhClientLevel(this.saveStructure, clientLevelWrapper, this.networkState)); + return this.levels.computeIfAbsent((IClientLevelWrapper) wrapper, + (clientLevelWrapper) -> + { + try + { + return new DhClientLevel(this.saveStructure, clientLevelWrapper, this.networkState); + } + catch (Exception e) + { + LOGGER.fatal("Failed to load client level, error: ["+e.getMessage()+"].", e); + + ClientApi.INSTANCE.showChatMessageNextFrame(// red text + "\u00A7c" + "Distant Horizons: Client level loading failed." + "\u00A7r \n" + + "Unable to load level ["+clientLevelWrapper.getDhIdentifier()+"], LODs may not appear. See log for more information."); + + return null; + } + }); } @Override diff --git a/core/src/main/java/com/seibel/distanthorizons/core/world/DhServerWorld.java b/core/src/main/java/com/seibel/distanthorizons/core/world/DhServerWorld.java index 9871be809..97d70785b 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/world/DhServerWorld.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/world/DhServerWorld.java @@ -19,6 +19,7 @@ package com.seibel.distanthorizons.core.world; +import com.seibel.distanthorizons.core.api.internal.ClientApi; import com.seibel.distanthorizons.core.level.DhServerLevel; import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.world.IServerLevelWrapper; @@ -51,7 +52,23 @@ public class DhServerWorld extends AbstractDhServerWorld } return this.dhLevelByLevelWrapper.computeIfAbsent(wrapper, - (serverLevelWrapper) -> new DhServerLevel(this.saveStructure, (IServerLevelWrapper) serverLevelWrapper, this.getServerPlayerStateManager())); + (serverLevelWrapper) -> + { + try + { + return new DhServerLevel(this.saveStructure, (IServerLevelWrapper) serverLevelWrapper, this.getServerPlayerStateManager()); + } + catch (Exception e) + { + LOGGER.fatal("Failed to load server level, error: ["+e.getMessage()+"].", e); + + ClientApi.INSTANCE.showChatMessageNextFrame(// red text + "\u00A7c" + "Distant Horizons: Server level loading failed." + "\u00A7r \n" + + "Unable to load level ["+serverLevelWrapper.getDhIdentifier()+"], LODs may not appear. See log for more information."); + + return null; + } + }); } @Override diff --git a/core/src/main/java/com/seibel/distanthorizons/core/world/IDhServerWorld.java b/core/src/main/java/com/seibel/distanthorizons/core/world/IDhServerWorld.java index 40e4a1e28..7617a55c0 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/world/IDhServerWorld.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/world/IDhServerWorld.java @@ -24,6 +24,7 @@ import com.seibel.distanthorizons.core.multiplayer.server.ServerPlayerStateManag import com.seibel.distanthorizons.core.wrapperInterfaces.misc.IServerPlayerWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.world.IServerLevelWrapper; +import org.jetbrains.annotations.Nullable; /** Used both for dedicated server and singleplayer worlds */ public interface IDhServerWorld extends IDhWorld @@ -33,6 +34,7 @@ public interface IDhServerWorld extends IDhWorld void removePlayer(IServerPlayerWrapper serverPlayer); void changePlayerLevel(IServerPlayerWrapper player, IServerLevelWrapper originLevel, IServerLevelWrapper destinationLevel); + @Nullable default IDhServerLevel getOrLoadServerLevel(ILevelWrapper levelWrapper) { return (IDhServerLevel) this.getOrLoadLevel(levelWrapper); } } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/world/IDhWorld.java b/core/src/main/java/com/seibel/distanthorizons/core/world/IDhWorld.java index 97d2c050e..6910979bc 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/world/IDhWorld.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/world/IDhWorld.java @@ -31,6 +31,7 @@ import java.util.concurrent.CompletableFuture; public interface IDhWorld extends Closeable { + @Nullable IDhLevel getOrLoadLevel(@NotNull ILevelWrapper levelWrapper); @Nullable IDhLevel getLevel(@NotNull ILevelWrapper wrapper); diff --git a/core/src/test/java/testItems/sql/TestCompoundKeyRepo.java b/core/src/test/java/testItems/sql/TestCompoundKeyRepo.java index 4548a09cd..3891fe140 100644 --- a/core/src/test/java/testItems/sql/TestCompoundKeyRepo.java +++ b/core/src/test/java/testItems/sql/TestCompoundKeyRepo.java @@ -25,6 +25,7 @@ import com.seibel.distanthorizons.core.sql.repo.AbstractDhRepo; import org.jetbrains.annotations.Nullable; import java.io.File; +import java.io.IOException; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; @@ -33,7 +34,7 @@ import java.util.Map; public class TestCompoundKeyRepo extends AbstractDhRepo { - public TestCompoundKeyRepo(String databaseType, File databaseFile) throws SQLException + public TestCompoundKeyRepo(String databaseType, File databaseFile) throws SQLException, IOException { super(databaseType, databaseFile, TestCompoundKeyDto.class); diff --git a/core/src/test/java/testItems/sql/TestPrimaryKeyRepo.java b/core/src/test/java/testItems/sql/TestPrimaryKeyRepo.java index 8c3ac9f70..ebdc5e9c0 100644 --- a/core/src/test/java/testItems/sql/TestPrimaryKeyRepo.java +++ b/core/src/test/java/testItems/sql/TestPrimaryKeyRepo.java @@ -24,6 +24,7 @@ import com.seibel.distanthorizons.core.sql.repo.AbstractDhRepo; import org.jetbrains.annotations.Nullable; import java.io.File; +import java.io.IOException; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; @@ -32,7 +33,7 @@ import java.util.Map; public class TestPrimaryKeyRepo extends AbstractDhRepo { - public TestPrimaryKeyRepo(String databaseType, File databaseFile) throws SQLException + public TestPrimaryKeyRepo(String databaseType, File databaseFile) throws SQLException, IOException { super(databaseType, databaseFile, TestSingleKeyDto.class); diff --git a/core/src/test/java/tests/DhRepoSqliteTest.java b/core/src/test/java/tests/DhRepoSqliteTest.java index a86719c88..eeb2d4121 100644 --- a/core/src/test/java/tests/DhRepoSqliteTest.java +++ b/core/src/test/java/tests/DhRepoSqliteTest.java @@ -34,6 +34,7 @@ import testItems.sql.TestPrimaryKeyRepo; import testItems.sql.TestSingleKeyDto; import java.io.File; +import java.io.IOException; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; @@ -137,7 +138,7 @@ public class DhRepoSqliteTest Assert.assertFalse("DTO exists failed", primaryKeyRepo.existsWithKey(insertDto.getKey())); } - catch (SQLException e) + catch (SQLException | IOException e) { Assert.fail(e.getMessage()); } @@ -200,7 +201,7 @@ public class DhRepoSqliteTest Assert.assertFalse("DTO exists failed", compoundKeyRepo.existsWithKey(insertDto.getKey())); } - catch (SQLException e) + catch (SQLException | IOException e) { Assert.fail(e.getMessage()); } @@ -330,7 +331,7 @@ public class DhRepoSqliteTest Assert.assertNotEquals(0, primaryKeyRepo.openClosables.size()); } } - catch (SQLException e) + catch (SQLException | IOException e) { Assert.fail(e.getMessage()); } @@ -367,7 +368,7 @@ public class DhRepoSqliteTest long endMs = System.currentTimeMillis(); System.out.println("Bulk update took ["+(endMs - startMs)+"] ms"); } - catch (SQLException e) + catch (SQLException | IOException e) { Assert.fail(e.getMessage()); }