Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 47 additions & 42 deletions common/src/main/java/com/daqem/grieflogger/database/Database.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,10 @@ public class Database {

@Nullable
private Connection connection;
@Nullable
private Statement statement;
public final IQueue queue;
public final IQueue batchQueue;
private IDatabaseDialect dialect;
private final Object lock = new Object();

public Database() {
queue = new Queue(this, false);
Expand All @@ -46,20 +45,14 @@ public boolean createConnection() {
}
if (connection != null) {
GriefLogger.LOGGER.info("Connected to database");
try {
statement = connection.createStatement();
} catch (SQLException e) {
GriefLogger.LOGGER.error("Failed to create statement", e);
return false;
}
try {
connection.setAutoCommit(false);
} catch (SQLException e) {
GriefLogger.LOGGER.error("Failed to set auto commit", e);
return false;
}
}
return connected && connection != null && statement != null;
return connected && connection != null;
}

public boolean createMysqlConnection() {
Expand Down Expand Up @@ -98,7 +91,6 @@ public boolean createSqliteConnection() {
path.toFile().mkdirs();
}
try {
// Construct the JDBC URL with the full path to database.db
String dbPath = path.resolve("database.db").toString();
connection = DriverManager.getConnection("jdbc:sqlite:" + dbPath);
} catch (SQLException e) {
Expand All @@ -109,23 +101,25 @@ public boolean createSqliteConnection() {
}

public void createTable(String sql) {
try {
if (statement != null) {
statement.execute(sql);
}
} catch (SQLException e) {
GriefLogger.LOGGER.error("Failed to create table", e);
}
execute(sql, true);
}

public void execute(String sql, boolean logError) {
try {
if (statement != null) {
if (connection == null) return;

synchronized (lock) {
try (Statement statement = connection.createStatement()) {
statement.execute(sql);
}
} catch (SQLException e) {
if (logError) {
GriefLogger.LOGGER.error("Failed to execute statement", e);
connection.commit();
} catch (SQLException e) {
if (logError) {
GriefLogger.LOGGER.error("Failed to execute statement", e);
}
try {
connection.rollback();
} catch (SQLException ex) {
GriefLogger.LOGGER.error("Failed to rollback", ex);
}
}
}
}
Expand All @@ -139,30 +133,41 @@ public PreparedStatement prepareStatement(String query) throws SQLException {
}

public void executeQueue(List<Object> items, boolean isBatch) {
try {
for (Object item : items) {
if (item instanceof PreparedStatement preparedStatement) {
if (preparedStatement.isClosed()) {
continue;
}
try (preparedStatement) {
if (isBatch) {
preparedStatement.executeBatch();
} else {
preparedStatement.executeUpdate();
if (connection == null) return;

synchronized (lock) {
try {
for (Object item : items) {
if (item instanceof PreparedStatement preparedStatement) {
if (preparedStatement.isClosed()) {
continue;
}
try (preparedStatement) {
if (isBatch) {
preparedStatement.executeBatch();
} else {
preparedStatement.executeUpdate();
}
}
} else if (item instanceof SqlTask task) {
task.execute(connection);
}
} else if (item instanceof SqlTask task) {
task.execute(connection);
}
}
if (!items.isEmpty()) {
if (connection != null) {
connection.commit();
if (!items.isEmpty()) {
if (connection != null && !connection.isClosed()) {
connection.commit();
}
}
} catch (SQLException e) {
GriefLogger.LOGGER.error("Failed to execute database queue", e);
try {
if (connection != null && !connection.isClosed()) {
connection.rollback();
}
} catch (SQLException ex) {
GriefLogger.LOGGER.error("Failed to rollback transaction", ex);
}
}
} catch (SQLException e) {
GriefLogger.LOGGER.error("Failed to execute database queue", e);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public class UserCache implements ICache {
private final Map<Integer, String> usernames = new HashMap<>();

public Map<Integer, String> getAllUsernames() {
if (usernameTime + 1000 < System.currentTimeMillis()) {
if (usernameTime + 300000 < System.currentTimeMillis()) {
usernames.clear();
usernames.putAll(userService.getAllUsernames());
usernameTime = System.currentTimeMillis();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.daqem.grieflogger.database.repository;

import java.io.ByteArrayInputStream;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
Expand All @@ -9,6 +10,10 @@
import java.util.Map;

import com.daqem.grieflogger.database.dialect.MySQLDialect;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.NbtAccounter;
import net.minecraft.nbt.NbtIo;
import net.minecraft.nbt.NbtOps;
import org.jetbrains.annotations.Nullable;

import com.daqem.grieflogger.GriefLogger;
Expand All @@ -19,10 +24,7 @@
import com.daqem.grieflogger.model.history.ContainerHistory;
import com.daqem.grieflogger.model.history.IHistory;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import net.minecraft.core.component.DataComponentPatch;
import net.minecraft.network.RegistryFriendlyByteBuf;
import net.minecraft.resources.Identifier;
import net.minecraft.world.level.Level;

Expand All @@ -34,7 +36,6 @@ public ContainerRepository(Database database) {
this.database = database;
}

// createTable / createIndexes omitted (same as original)
public void createTable() {
String sql = "CREATE TABLE IF NOT EXISTS containers (" +
"time " + database.getDialect().getDataType("bigint") + " NOT NULL," +
Expand Down Expand Up @@ -199,7 +200,20 @@ public void insertMap(long time, String userUuid, Level level, int x, int y, int
});
}

// ... getHistory, getFilteredContainerHistory (read-only methods, same as original) ...
private DataComponentPatch readPatch(byte[] bytes, Level level) {
if (bytes == null || bytes.length == 0) {
return DataComponentPatch.EMPTY;
}
try {
ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
CompoundTag compoundTag = NbtIo.readCompressed(inputStream, NbtAccounter.unlimitedHeap());
return DataComponentPatch.CODEC.parse(level.registryAccess().createSerializationContext(NbtOps.INSTANCE), compoundTag)
.getOrThrow(IllegalStateException::new);
} catch (Exception e) {
return DataComponentPatch.EMPTY;
}
}

public List<IHistory> getHistory(Level level, int x, int y, int z) {
List<IHistory> containerHistory = new ArrayList<>();
String query = """
Expand All @@ -222,9 +236,7 @@ public List<IHistory> getHistory(Level level, int x, int y, int z) {

ResultSet resultSet = preparedStatement.executeQuery();
while (resultSet.next()) {
ByteBuf buf1 = Unpooled.wrappedBuffer(resultSet.getBytes(8));
RegistryFriendlyByteBuf buf = new RegistryFriendlyByteBuf(buf1, level.registryAccess());
DataComponentPatch patch = DataComponentPatch.STREAM_CODEC.decode(buf);
DataComponentPatch patch = readPatch(resultSet.getBytes(8), level);
containerHistory.add(new ContainerHistory(
resultSet.getLong(1),
resultSet.getString(2),
Expand Down Expand Up @@ -269,9 +281,7 @@ public List<IHistory> getHistory(Level level, int x, int y, int z, int x2, int y

ResultSet resultSet = preparedStatement.executeQuery();
while (resultSet.next()) {
ByteBuf buf1 = Unpooled.wrappedBuffer(resultSet.getBytes(8));
RegistryFriendlyByteBuf buf = new RegistryFriendlyByteBuf(buf1, level.registryAccess());
DataComponentPatch patch = DataComponentPatch.STREAM_CODEC.decode(buf);
DataComponentPatch patch = readPatch(resultSet.getBytes(8), level);
containerHistory.add(new ContainerHistory(
resultSet.getLong(1),
resultSet.getString(2),
Expand Down Expand Up @@ -374,9 +384,7 @@ public List<IHistory> getFilteredContainerHistory(Level level, FilterList filter
List<IHistory> blockHistory = new ArrayList<>();
ResultSet resultSet = preparedStatement.executeQuery();
while (resultSet.next()) {
ByteBuf buf1 = Unpooled.wrappedBuffer(resultSet.getBytes(8));
RegistryFriendlyByteBuf buf = new RegistryFriendlyByteBuf(buf1, level.registryAccess());
DataComponentPatch patch = DataComponentPatch.STREAM_CODEC.decode(buf);
DataComponentPatch patch = readPatch(resultSet.getBytes(8), level);
blockHistory.add(new ContainerHistory(
resultSet.getLong(1),
resultSet.getString(2),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.daqem.grieflogger.database.repository;

import java.io.ByteArrayInputStream;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
Expand All @@ -9,6 +10,10 @@
import java.util.Map;

import com.daqem.grieflogger.database.dialect.MySQLDialect;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.NbtAccounter;
import net.minecraft.nbt.NbtIo;
import net.minecraft.nbt.NbtOps;
import org.jetbrains.annotations.Nullable;

import com.daqem.grieflogger.GriefLogger;
Expand All @@ -18,10 +23,7 @@
import com.daqem.grieflogger.model.action.ItemAction;
import com.daqem.grieflogger.model.history.ItemHistory;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import net.minecraft.core.component.DataComponentPatch;
import net.minecraft.network.RegistryFriendlyByteBuf;
import net.minecraft.resources.Identifier;
import net.minecraft.world.level.Level;

Expand Down Expand Up @@ -152,6 +154,20 @@ public void insertMap(long time, String userUuid, Level level, int x, int y, int
});
}

private DataComponentPatch readPatch(byte[] bytes, Level level) {
if (bytes == null || bytes.length == 0) {
return DataComponentPatch.EMPTY;
}
try {
ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
CompoundTag compoundTag = NbtIo.readCompressed(inputStream, NbtAccounter.unlimitedHeap());
return DataComponentPatch.CODEC.parse(level.registryAccess().createSerializationContext(NbtOps.INSTANCE), compoundTag)
.getOrThrow(IllegalStateException::new);
} catch (Exception e) {
return DataComponentPatch.EMPTY;
}
}

public List<ItemHistory> getFilteredItemHistory(Level level, FilterList filterList) {
@Nullable String actions = filterList.getActionString();
@Nullable String users = filterList.getUserString();
Expand Down Expand Up @@ -235,9 +251,7 @@ public List<ItemHistory> getFilteredItemHistory(Level level, FilterList filterLi
List<ItemHistory> itemHistory = new ArrayList<>();
ResultSet resultSet = preparedStatement.executeQuery();
while (resultSet.next()) {
ByteBuf buf1 = Unpooled.wrappedBuffer(resultSet.getBytes(8));
RegistryFriendlyByteBuf buf = new RegistryFriendlyByteBuf(buf1, level.registryAccess());
DataComponentPatch patch = DataComponentPatch.STREAM_CODEC.decode(buf);
DataComponentPatch patch = readPatch(resultSet.getBytes(8), level);
itemHistory.add(new ItemHistory(
resultSet.getLong(1),
resultSet.getString(2),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public void insertOrUpdateName(String name, String uuid) {
}

public void insertNonPlayer(String name) {
String query = "INSERT INTO users(name) VALUES('%s') " +
String query = "INSERT INTO users(name) VALUES(?) " +
database.getDialect().getOnConflictDoNothing("name");

database.queue.add(connection -> {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
package com.daqem.grieflogger.model;

import io.netty.buffer.Unpooled;
import com.daqem.grieflogger.GriefLogger;
import net.minecraft.core.component.DataComponentPatch;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.network.RegistryFriendlyByteBuf;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.NbtIo;
import net.minecraft.nbt.NbtOps;
import net.minecraft.nbt.Tag;
import net.minecraft.resources.Identifier;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;
import org.jetbrains.annotations.Nullable;

import java.io.ByteArrayOutputStream;
import java.util.Objects;

public class SimpleItemStack {
Expand Down Expand Up @@ -77,14 +81,20 @@ public void addCount(int count) {
}

public byte @Nullable [] getTagBytes(Level level) {
if (tag == null) {
if (tag == null || tag.isEmpty()) {
return null;
}
try {
Tag nbtTag = DataComponentPatch.CODEC.encodeStart(level.registryAccess().createSerializationContext(NbtOps.INSTANCE), tag)
.getOrThrow(IllegalStateException::new);

ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
NbtIo.writeCompressed((CompoundTag) nbtTag, outputStream);
return outputStream.toByteArray();
} catch (Exception e) {
GriefLogger.LOGGER.error("Failed to serialize item components", e);
return null;
}
RegistryFriendlyByteBuf buf = new RegistryFriendlyByteBuf(Unpooled.buffer(), level.registryAccess());
DataComponentPatch.STREAM_CODEC.encode(buf, tag);
byte[] temp = new byte[buf.readableBytes()];
buf.readBytes(temp);
return temp;
}

public ItemStack toItemStack() {
Expand All @@ -96,4 +106,4 @@ public ItemStack toItemStack() {
public boolean isEmpty() {
return item.equals(ItemStack.EMPTY.getItem()) || count == 0;
}
}
}
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ maven_group=com.daqem.grieflogger
archives_base_name=grieflogger

# Project
mod_version=19.0.3
mod_version=19.0.4
mod_id=grieflogger
mod_name=GriefLogger
mod_description=A mod that logs all player interactions with blocks and entities and stores them in a database.
Expand Down
Loading