Add some missing calls in restore queue with database addition

This commit is contained in:
zontreck 2024-04-23 20:25:52 -07:00
parent c8fc5f4c81
commit b91ce4e912
6 changed files with 85 additions and 39 deletions

View file

@ -53,7 +53,7 @@ mod_name=Zontreck's Library Mod
# The license of the mod. Review your options at https://choosealicense.com/. All Rights Reserved is the default. # The license of the mod. Review your options at https://choosealicense.com/. All Rights Reserved is the default.
mod_license=GPLv3 mod_license=GPLv3
# The mod version. See https://semver.org/ # The mod version. See https://semver.org/
mod_version=1201.13.042324.1837 mod_version=1201.13.042324.2018
# The group ID for the mod. It is only important when publishing as an artifact to a Maven repository. # The group ID for the mod. It is only important when publishing as an artifact to a Maven repository.
# This should match the base package used for the mod sources. # This should match the base package used for the mod sources.
# See https://maven.apache.org/guides/mini/guide-naming-conventions.html # See https://maven.apache.org/guides/mini/guide-naming-conventions.html

View file

@ -11,4 +11,9 @@ public class BlockRestore extends BlockRestoreQueue
public void notifyDirtyQueue(boolean blockAdded) { public void notifyDirtyQueue(boolean blockAdded) {
return; // We dont care. This is a basic queue return; // We dont care. This is a basic queue
} }
@Override
public boolean sorted() {
return false;
}
} }

View file

@ -1,19 +1,14 @@
package dev.zontreck.libzontreck.memory.world; package dev.zontreck.libzontreck.memory.world;
import dev.zontreck.libzontreck.vectors.WorldPosition;
import net.minecraft.core.BlockPos;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.NbtIo; import net.minecraft.nbt.NbtIo;
import net.minecraft.nbt.NbtUtils;
import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.block.Block;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.event.TickEvent; import net.minecraftforge.event.TickEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
import java.io.*; import java.io.*;
import java.sql.PreparedStatement; import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -70,6 +65,7 @@ public abstract class BlockRestoreQueue
if(usesDatabase()) if(usesDatabase())
{ {
databaseUpdate(block); databaseUpdate(block);
notifyDirtyQueue(true);
return; return;
} }
BLOCK_QUEUE.add(block); BLOCK_QUEUE.add(block);
@ -86,28 +82,17 @@ public abstract class BlockRestoreQueue
PreparedStatement pstmt = null; PreparedStatement pstmt = null;
try { try {
pstmt = DatabaseWrapper.get().prepareStatement("REPLACE INTO `blocks` (queueName, posX, posY, posZ, state, entity, dimension, snapshotID) VALUES (?, ?, ?, ?, ?, ?, ?, ?);"); pstmt = DatabaseWrapper.get().prepareStatement("INSERT INTO `blocks` (queueName, posX, posY, posZ, snapshotID, block) VALUES (?, ?, ?, ?, ?, ?);");
pstmt.setString(0, getRestoreQueueName()); pstmt.setString(0, getRestoreQueueName());
pstmt.setInt(1, block.position.getX()); pstmt.setInt(1, block.position.getX());
pstmt.setInt(2, block.position.getY()); pstmt.setInt(2, block.position.getY());
pstmt.setInt(3, block.position.getZ()); pstmt.setInt(3, block.position.getZ());
pstmt.setInt(4, 0);
ByteArrayOutputStream blockState = new ByteArrayOutputStream(); ByteArrayOutputStream blockState = new ByteArrayOutputStream();
DataOutputStream dos0 = new DataOutputStream(blockState); DataOutputStream dos0 = new DataOutputStream(blockState);
NbtIo.write(NbtUtils.writeBlockState(block.blockState), dos0); NbtIo.write(block.serialize(), dos0);
pstmt.setBytes(4, blockState.toByteArray()); pstmt.setBytes(5, blockState.toByteArray());
ByteArrayOutputStream blockEntity = new ByteArrayOutputStream();
if(block.blockEntity == null)
{
pstmt.setObject(5, null);
} else {
dos0 = new DataOutputStream(blockEntity);
NbtIo.write(block.blockEntity, dos0);
pstmt.setBytes(5, blockEntity.toByteArray());
}
pstmt.setString(6, WorldPosition.getDim(block.level));
pstmt.setInt(7, 0);
DatabaseWrapper.get().executePreparedStatement(pstmt); DatabaseWrapper.get().executePreparedStatement(pstmt);
@ -130,12 +115,62 @@ public abstract class BlockRestoreQueue
*/ */
public PrimitiveBlock getNextBlock() public PrimitiveBlock getNextBlock()
{ {
if (usesDatabase()) {
// Send a query to the database to retrieve the block, and reconstruct here
try {
PreparedStatement sel;
if (sorted()) {
sel = DatabaseWrapper.get().prepareStatement("SELECT * FROM `blocks` WHERE queueName=? ORDER BY posY ASC LIMIT 1;");
} else
sel = DatabaseWrapper.get().prepareStatement("SELECT * FROM `blocks` WHERE queueName=? LIMIT 1;");
sel.setString(0, getRestoreQueueName());
ResultSet res = DatabaseWrapper.get().executePreparedStatementQuery(sel);
// Now retrieve the block from the database
if (res.next()) {
byte[] data = res.getBytes("block");
ByteArrayInputStream bais = new ByteArrayInputStream(data);
DataInputStream dis = new DataInputStream(bais);
PrimitiveBlock block = PrimitiveBlock.deserialize(NbtIo.read(dis));
try {
res.deleteRow();
if (!res.rowDeleted()) {
}
} catch (SQLException e001) {
PreparedStatement pstat = DatabaseWrapper.get().prepareStatement("DELETE FROM `blocks` WHERE queueName=? AND posX=? AND posY=? AND posZ=?;");
pstat.setString(0, getRestoreQueueName());
pstat.setInt(1, block.position.getX());
pstat.setInt(2, block.position.getY());
pstat.setInt(3, block.position.getZ());
DatabaseWrapper.get().executePreparedStatement(pstat);
}
return block;
} else return null;
} catch (SQLException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
PrimitiveBlock blk = BLOCK_QUEUE.get(0); PrimitiveBlock blk = BLOCK_QUEUE.get(0);
BLOCK_QUEUE.remove(0); BLOCK_QUEUE.remove(0);
notifyDirtyQueue(false); notifyDirtyQueue(false);
return blk; return blk;
} }
/**
* Override to indicate if the list should be sorted by lowest Y value
*
* @return
*/
public abstract boolean sorted();
/** /**
* Clears the entire queue, discarding the saved blocks permanently. * Clears the entire queue, discarding the saved blocks permanently.
*/ */

View file

@ -108,15 +108,13 @@ public class DatabaseMigrations
" `posX` int(11) NOT NULL," + " `posX` int(11) NOT NULL," +
" `posY` int(11) NOT NULL," + " `posY` int(11) NOT NULL," +
" `posZ` int(11) NOT NULL," + " `posZ` int(11) NOT NULL," +
" `state` blob NOT NULL," +
" `entity` blob," +
" `dimension` varchar(255) NOT NULL," +
" `snapshotID` int(11) NOT NULL DEFAULT 0 COMMENT 'Enables multiple blocks existing at the same position'," + " `snapshotID` int(11) NOT NULL DEFAULT 0 COMMENT 'Enables multiple blocks existing at the same position'," +
" `block` blob NOT NULL COMMENT 'NBT Data representing a SavedBlock'," +
" PRIMARY KEY (`time`)," + " PRIMARY KEY (`time`)," +
" UNIQUE KEY `posX` (`posX`)," + " UNIQUE KEY `posX` (`posX`)," +
" UNIQUE KEY `posY` (`posY`)," + " UNIQUE KEY `posY` (`posY`)," +
" UNIQUE KEY `posZ` (`posZ`)" + " UNIQUE KEY `posZ` (`posZ`)" +
"); "); ") ;");
migrations.add(blocksTable.withMigrationAction(makeBlocksTable)); migrations.add(blocksTable.withMigrationAction(makeBlocksTable));

View file

@ -10,26 +10,24 @@ public class DatabaseWrapper {
private Connection connection; private Connection connection;
private static DatabaseWrapper instance; private static DatabaseWrapper instance;
private static boolean hasDatabase=false; private static boolean hasDatabase = false;
private static void setHasDatabase(boolean value) private static void setHasDatabase(boolean value) {
{
hasDatabase = value; hasDatabase = value;
} }
public static DatabaseWrapper get() public static DatabaseWrapper get() {
{ if (instance == null)
if(instance==null)
start(); start();
return instance; return instance;
} }
/** /**
* This function will return true if the database drivers are available. * This function will return true if the database drivers are available.
*
* @return * @return
*/ */
public static boolean databaseIsAvailable() public static boolean databaseIsAvailable() {
{
return hasDatabase; return hasDatabase;
} }
@ -37,8 +35,7 @@ public class DatabaseWrapper {
connection = null; connection = null;
} }
public static void start() public static void start() {
{
instance = new DatabaseWrapper(); instance = new DatabaseWrapper();
try { try {
instance.connect(ServerConfig.database.host, ServerConfig.database.user, ServerConfig.database.password); instance.connect(ServerConfig.database.host, ServerConfig.database.user, ServerConfig.database.password);
@ -66,10 +63,9 @@ public class DatabaseWrapper {
Class.forName("com.mysql.jdbc.Driver"); Class.forName("com.mysql.jdbc.Driver");
connection = DriverManager.getConnection("jdbc:mysql://" + url, username, password); connection = DriverManager.getConnection("jdbc:mysql://" + url, username, password);
}catch (ClassNotFoundException | SQLException ex1) } catch (ClassNotFoundException | SQLException ex1) {
{
LibZontreck.LOGGER.warn("Failed to connect via MySQL: " + e.getMessage() + "; " + ex1.getMessage()+ "; Attempting to fall back to sqlite"); LibZontreck.LOGGER.warn("Failed to connect via MySQL: " + e.getMessage() + "; " + ex1.getMessage() + "; Attempting to fall back to sqlite");
try { try {
Class.forName("org.sqlite.JDBC"); Class.forName("org.sqlite.JDBC");
@ -111,6 +107,13 @@ public class DatabaseWrapper {
return preparedStatement.executeUpdate(); return preparedStatement.executeUpdate();
} }
public ResultSet executePreparedStatementQuery(PreparedStatement query) throws SQLException {
if (connection == null) {
throw new SQLException("Connection not established.");
}
return query.executeQuery();
}
public PreparedStatement prepareStatement(String query) throws SQLException { public PreparedStatement prepareStatement(String query) throws SQLException {
if (connection == null) { if (connection == null) {
throw new SQLException("Connection not established."); throw new SQLException("Connection not established.");

View file

@ -33,4 +33,9 @@ public class SortedBlockQueue extends BlockRestoreQueue
} }
} }
@Override
public boolean sorted() {
return true;
}
} }