From df2dabfdfd1e35397029ed56d7e5ed9062ec858f Mon Sep 17 00:00:00 2001 From: Will Date: Wed, 29 May 2024 15:10:40 -0700 Subject: [PATCH 1/7] Remove mutex from default sqlite (#261) Co-authored-by: Drex --- docs/parameters.md | 2 +- .../commands/arguments/SearchParamArgument.kt | 4 +- .../commands/parameters/SourceParameter.kt | 10 +- .../ledger/database/DatabaseManager.kt | 273 ++++++++++++------ 4 files changed, 187 insertions(+), 102 deletions(-) diff --git a/docs/parameters.md b/docs/parameters.md index 0e705414..00ec7282 100644 --- a/docs/parameters.md +++ b/docs/parameters.md @@ -83,7 +83,7 @@ An easy way to remember the difference between `before:1d` and `after:1d` is to If you go back in time 1 day, do you want everything that happened `before` then or `after` then. Usually you want `after`. -### Rollback Status +## Rollback Status Key - `rolledback:` Value - `true` or `false` Negative Allowed - `No` diff --git a/src/main/kotlin/com/github/quiltservertools/ledger/commands/arguments/SearchParamArgument.kt b/src/main/kotlin/com/github/quiltservertools/ledger/commands/arguments/SearchParamArgument.kt index 50162aa0..829e6738 100644 --- a/src/main/kotlin/com/github/quiltservertools/ledger/commands/arguments/SearchParamArgument.kt +++ b/src/main/kotlin/com/github/quiltservertools/ledger/commands/arguments/SearchParamArgument.kt @@ -27,6 +27,7 @@ import net.minecraft.util.math.BlockBox import net.minecraft.util.math.BlockPos import net.minecraft.util.math.Vec3i import java.time.Instant +import java.util.* import java.util.concurrent.CompletableFuture object SearchParamArgument { @@ -140,7 +141,8 @@ object SearchParamArgument { } } else { val profile = source.server.userCache?.findByName(sourceInput.property) - val id = profile?.orElse(null)?.id + // If the player doesn't exist use a random UUID to make the query not match + val id = profile?.orElse(null)?.id ?: UUID.randomUUID() if (id != null) { val playerIdEntry = Negatable(id, sourceInput.allowed) diff --git a/src/main/kotlin/com/github/quiltservertools/ledger/commands/parameters/SourceParameter.kt b/src/main/kotlin/com/github/quiltservertools/ledger/commands/parameters/SourceParameter.kt index 676b013b..3c7d510c 100644 --- a/src/main/kotlin/com/github/quiltservertools/ledger/commands/parameters/SourceParameter.kt +++ b/src/main/kotlin/com/github/quiltservertools/ledger/commands/parameters/SourceParameter.kt @@ -5,9 +5,9 @@ import com.mojang.brigadier.StringReader import com.mojang.brigadier.context.CommandContext import com.mojang.brigadier.suggestion.Suggestions import com.mojang.brigadier.suggestion.SuggestionsBuilder -import java.util.concurrent.CompletableFuture import net.minecraft.command.CommandSource import net.minecraft.server.command.ServerCommandSource +import java.util.concurrent.CompletableFuture class SourceParameter : SimpleParameter() { override fun parse(stringReader: StringReader): String { @@ -27,14 +27,12 @@ class SourceParameter : SimpleParameter() { val stringReader = StringReader(builder.input) stringReader.cursor = builder.start - val players = context.source.playerNames + val sources = context.source.playerNames DatabaseManager.getKnownSources().forEach { - players.add("@$it") + sources.add("@$it") } - // TODO suggest non-player sources - return CommandSource.suggestMatching( - players, + sources, builder ) } diff --git a/src/main/kotlin/com/github/quiltservertools/ledger/database/DatabaseManager.kt b/src/main/kotlin/com/github/quiltservertools/ledger/database/DatabaseManager.kt index 37245960..1eb647c9 100644 --- a/src/main/kotlin/com/github/quiltservertools/ledger/database/DatabaseManager.kt +++ b/src/main/kotlin/com/github/quiltservertools/ledger/database/DatabaseManager.kt @@ -13,24 +13,23 @@ import com.github.quiltservertools.ledger.logWarn import com.github.quiltservertools.ledger.registry.ActionRegistry import com.github.quiltservertools.ledger.utility.Negatable import com.github.quiltservertools.ledger.utility.PlayerResult +import com.google.common.cache.Cache import com.mojang.authlib.GameProfile -import java.time.Instant -import java.time.temporal.ChronoUnit -import java.util.* -import javax.sql.DataSource import kotlinx.coroutines.delay -import kotlinx.coroutines.sync.Mutex import net.minecraft.util.Identifier import net.minecraft.util.WorldSavePath import net.minecraft.util.math.BlockPos +import org.jetbrains.exposed.dao.Entity +import org.jetbrains.exposed.dao.EntityClass +import org.jetbrains.exposed.dao.IntEntityClass import org.jetbrains.exposed.dao.id.EntityID +import org.jetbrains.exposed.dao.id.IntIdTable import org.jetbrains.exposed.sql.Column import org.jetbrains.exposed.sql.Database import org.jetbrains.exposed.sql.Op import org.jetbrains.exposed.sql.Query import org.jetbrains.exposed.sql.SchemaUtils import org.jetbrains.exposed.sql.SortOrder -import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq import org.jetbrains.exposed.sql.SqlExpressionBuilder.inSubQuery import org.jetbrains.exposed.sql.SqlExpressionBuilder.lessEq import org.jetbrains.exposed.sql.SqlLogger @@ -44,7 +43,6 @@ import org.jetbrains.exposed.sql.deleteWhere import org.jetbrains.exposed.sql.innerJoin import org.jetbrains.exposed.sql.insertAndGetId import org.jetbrains.exposed.sql.insertIgnore -import org.jetbrains.exposed.sql.lowerCase import org.jetbrains.exposed.sql.or import org.jetbrains.exposed.sql.orWhere import org.jetbrains.exposed.sql.selectAll @@ -53,10 +51,20 @@ import org.jetbrains.exposed.sql.statements.expandArgs import org.jetbrains.exposed.sql.transactions.experimental.newSuspendedTransaction import org.jetbrains.exposed.sql.transactions.transaction import org.jetbrains.exposed.sql.update +import org.sqlite.SQLiteConfig import org.sqlite.SQLiteDataSource +import java.time.Instant +import java.time.temporal.ChronoUnit +import java.util.* +import java.util.function.Function +import javax.sql.DataSource import kotlin.io.path.pathString import kotlin.math.ceil +const val MAX_QUERY_RETRIES = 10 +const val MIN_RETRY_DELAY = 1000L +const val MAX_RETRY_DELAY = 300_000L + object DatabaseManager { // These values are initialised late to allow the database to be created at server start, @@ -66,8 +74,6 @@ object DatabaseManager { get() = database.dialect.name private val cache = DatabaseCacheService - private val dbMutex = Mutex() - private var enforceMutex = false fun setup(dataSource: DataSource?) { val source = dataSource ?: getDefaultDatasource() @@ -76,8 +82,9 @@ object DatabaseManager { private fun getDefaultDatasource(): DataSource { val dbFilepath = Ledger.server.getSavePath(WorldSavePath.ROOT).resolve("ledger.sqlite").pathString - enforceMutex = true - return SQLiteDataSource().apply { + return SQLiteDataSource(SQLiteConfig().apply { + setJournalMode(SQLiteConfig.JournalMode.WAL) + }).apply { url = "jdbc:sqlite:$dbFilepath" } } @@ -169,8 +176,8 @@ object DatabaseManager { type.world = Identifier.tryParse(action[Tables.Worlds.identifier]) type.objectIdentifier = Identifier(action[Tables.ObjectIdentifiers.identifier]) type.oldObjectIdentifier = Identifier( - action[Tables.ObjectIdentifiers.alias("oldObjects")[Tables.ObjectIdentifiers.identifier]] - ) + action[Tables.ObjectIdentifiers.alias("oldObjects")[Tables.ObjectIdentifiers.identifier]] + ) type.objectState = action[Tables.Actions.blockState] type.oldObjectState = action[Tables.Actions.oldBlockState] type.sourceName = action[Tables.Sources.name] @@ -209,62 +216,65 @@ object DatabaseManager { op = op.and { Tables.Actions.rolledBack.eq(params.rolledBack) } } - val sourceNames = ArrayList>() - params.sourceNames?.forEach { - val sourceId = getSourceId(it.property) - if (sourceId != null) { - sourceNames.add(Negatable(sourceId, it.allowed)) - } else { - // Unknown source name - op = Op.FALSE - } - } - - val playerNames = ArrayList>() - params.sourcePlayerIds?.forEach { - val playerId = getPlayerId(it.property) - if (playerId != null) { - playerNames.add(Negatable(playerId, it.allowed)) - } else { - // Unknown player name - op = Op.FALSE - } - } - op = addParameters( op, - sourceNames, + params.sourceNames, + DatabaseManager::getSourceId, Tables.Actions.sourceName ) op = addParameters( op, - params.actions?.map { Negatable(getActionId(it.property), it.allowed) }, + params.actions, + DatabaseManager::getActionId, Tables.Actions.actionIdentifier ) op = addParameters( op, - params.worlds?.map { Negatable(getWorldId(it.property), it.allowed) }, + params.worlds, + DatabaseManager::getWorldId, Tables.Actions.world ) op = addParameters( op, - params.objects?.map { Negatable(getRegistryKeyId(it.property), it.allowed) }, + params.objects, + DatabaseManager::getRegistryKeyId, Tables.Actions.objectId, Tables.Actions.oldObjectId ) op = addParameters( op, - playerNames, + params.sourcePlayerIds, + DatabaseManager::getPlayerId, Tables.Actions.sourcePlayer ) return op } + private fun , C : EntityID?, T> addParameters( + op: Op, + paramSet: Collection>?, + objectToId: Function, + column: Column, + orColumn: Column? = null, + ): Op { + val idParamSet = mutableSetOf>() + paramSet?.forEach { + val paramId = objectToId.apply(it.property) + if (paramId != null) { + idParamSet.add(Negatable(paramId, it.allowed)) + } else { + // Unknown source name + return Op.FALSE + } + } + return addParameters(op, idParamSet, column, orColumn) + } + private fun , C : EntityID?> addParameters( op: Op, paramSet: Collection>?, @@ -277,7 +287,6 @@ object DatabaseManager { ): Op { if (allowed.isEmpty()) return op - var operator = if (orColumn != null) { Op.build { column eq allowed.first() or (orColumn eq allowed.first()) } } else { @@ -354,12 +363,15 @@ object DatabaseManager { } private suspend fun execute(body: suspend Transaction.() -> T): T { - if (enforceMutex) dbMutex.lock() while (Ledger.server.overworld?.savingDisabled != false) { delay(timeMillis = 1000) } return newSuspendedTransaction(db = database) { + repetitionAttempts = MAX_QUERY_RETRIES + minRepetitionDelay = MIN_RETRY_DELAY + maxRepetitionDelay = MAX_RETRY_DELAY + if (Ledger.config[DatabaseSpec.logSQL]) { addLogger(object : SqlLogger { override fun log(context: StatementContext, transaction: Transaction) { @@ -368,7 +380,7 @@ object DatabaseManager { }) } body(this) - }.also { if (enforceMutex) dbMutex.unlock() } + } } suspend fun purgeActions(params: ActionSearchParams) { @@ -402,18 +414,18 @@ object DatabaseManager { private fun Transaction.insertActions(actions: List) { Tables.Actions.batchInsert(actions, shouldReturnGeneratedValues = false) { action -> - this[Tables.Actions.actionIdentifier] = getActionId(action.identifier) + this[Tables.Actions.actionIdentifier] = getOrCreateActionId(action.identifier) this[Tables.Actions.timestamp] = action.timestamp this[Tables.Actions.x] = action.pos.x this[Tables.Actions.y] = action.pos.y this[Tables.Actions.z] = action.pos.z - this[Tables.Actions.objectId] = getRegistryKeyId(action.objectIdentifier) - this[Tables.Actions.oldObjectId] = getRegistryKeyId(action.oldObjectIdentifier) - this[Tables.Actions.world] = getWorldId(action.world ?: Ledger.server.overworld.registryKey.value) + this[Tables.Actions.objectId] = getOrCreateRegistryKeyId(action.objectIdentifier) + this[Tables.Actions.oldObjectId] = getOrCreateRegistryKeyId(action.oldObjectIdentifier) + this[Tables.Actions.world] = getOrCreateWorldId(action.world ?: Ledger.server.overworld.registryKey.value) this[Tables.Actions.blockState] = action.objectState this[Tables.Actions.oldBlockState] = action.oldObjectState this[Tables.Actions.sourceName] = getOrCreateSourceId(action.sourceName) - this[Tables.Actions.sourcePlayer] = action.sourceProfile?.let { getPlayerId(it.id) } + this[Tables.Actions.sourcePlayer] = action.sourceProfile?.let { getOrCreatePlayerId(it.id) } this[Tables.Actions.extraData] = action.extraData } } @@ -440,7 +452,10 @@ object DatabaseManager { .innerJoin(Tables.ActionIdentifiers) .innerJoin(Tables.Worlds) .leftJoin(Tables.Players) - .innerJoin(Tables.oldObjectTable, { Tables.Actions.oldObjectId }, { Tables.oldObjectTable[Tables.ObjectIdentifiers.id] }) + .innerJoin( + Tables.oldObjectTable, + { Tables.Actions.oldObjectId }, + { Tables.oldObjectTable[Tables.ObjectIdentifiers.id] }) .innerJoin(Tables.ObjectIdentifiers, { Tables.Actions.objectId }, { Tables.ObjectIdentifiers.id }) .innerJoin(Tables.Sources) .selectAll() @@ -479,7 +494,10 @@ object DatabaseManager { .innerJoin(Tables.ActionIdentifiers) .innerJoin(Tables.Worlds) .leftJoin(Tables.Players) - .innerJoin(Tables.oldObjectTable, { Tables.Actions.oldObjectId }, { Tables.oldObjectTable[Tables.ObjectIdentifiers.id] }) + .innerJoin( + Tables.oldObjectTable, + { Tables.Actions.oldObjectId }, + { Tables.oldObjectTable[Tables.ObjectIdentifiers.id] }) .innerJoin(Tables.ObjectIdentifiers, { Tables.Actions.objectId }, { Tables.ObjectIdentifiers.id }) .innerJoin(Tables.Sources) .selectAll() @@ -497,13 +515,17 @@ object DatabaseManager { .innerJoin(Tables.ActionIdentifiers) .innerJoin(Tables.Worlds) .leftJoin(Tables.Players) - .innerJoin(Tables.oldObjectTable, { Tables.Actions.oldObjectId }, { Tables.oldObjectTable[Tables.ObjectIdentifiers.id] }) + .innerJoin( + Tables.oldObjectTable, + { Tables.Actions.oldObjectId }, + { Tables.oldObjectTable[Tables.ObjectIdentifiers.id] }) .innerJoin(Tables.ObjectIdentifiers, { Tables.Actions.objectId }, { Tables.ObjectIdentifiers.id }) .innerJoin(Tables.Sources) .selectAll() .andWhere { buildQueryParams(params) and (Tables.Actions.rolledBack eq false) } .orderBy(Tables.Actions.id, SortOrder.DESC) - val actionIds = selectQuery.map { it[Tables.Actions.id] }.toSet() // SQLite doesn't support update where so select by ID. Might not be as efficent + val actionIds = selectQuery.map { it[Tables.Actions.id] } + .toSet() // SQLite doesn't support update where so select by ID. Might not be as efficent actions.addAll(getActionsFromQuery(selectQuery)) val updateQuery = Tables.Actions @@ -521,7 +543,10 @@ object DatabaseManager { .innerJoin(Tables.ActionIdentifiers) .innerJoin(Tables.Worlds) .leftJoin(Tables.Players) - .innerJoin(Tables.oldObjectTable, { Tables.Actions.oldObjectId }, { Tables.oldObjectTable[Tables.ObjectIdentifiers.id] }) + .innerJoin( + Tables.oldObjectTable, + { Tables.Actions.oldObjectId }, + { Tables.oldObjectTable[Tables.ObjectIdentifiers.id] }) .innerJoin(Tables.ObjectIdentifiers, { Tables.Actions.objectId }, { Tables.ObjectIdentifiers.id }) .innerJoin(Tables.Sources) .selectAll() @@ -538,62 +563,122 @@ object DatabaseManager { return actions } - private fun getPlayerId(playerId: UUID): Int? { - cache.playerKeys.getIfPresent(playerId)?.let { return it } + fun getKnownSources() = + cache.sourceKeys.asMap().keys - return Tables.Player.find { Tables.Players.playerId eq playerId }.firstOrNull()?.id?.value?.also { - cache.playerKeys.put(playerId, it) + private fun getObjectId( + obj: T, + cache: Cache, + table: EntityClass>, + column: Column + ): Int? = getObjectId(obj, Function.identity(), cache, table, column) + + private fun getObjectId( + obj: T, + mapper: Function, + cache: Cache, + table: EntityClass>, + column: Column + ): Int? { + cache.getIfPresent(obj)?.let { return it } + return table.find { column eq mapper.apply(obj) }.firstOrNull()?.id?.value?.also { + cache.put(obj, it) } } - private fun Transaction.selectPlayer(playerName: String) = - Tables.Player.find { Tables.Players.playerName.lowerCase() eq playerName }.firstOrNull() - - fun getKnownSources() = - cache.sourceKeys.asMap().keys + private fun getOrCreateObjectId( + obj: T, + cache: Cache, + entity: IntEntityClass<*>, + table: IntIdTable, + column: Column + ): Int = + getOrCreateObjectId(obj, Function.identity(), cache, entity, table, column) + + private fun getOrCreateObjectId( + obj: T, + mapper: Function, + cache: Cache, + entity: IntEntityClass<*>, + table: IntIdTable, + column: Column + ): Int { + getObjectId(obj, mapper, cache, entity, column)?.let { return it } + + return entity[ + table.insertAndGetId { + it[column] = mapper.apply(obj) + } + ].id.value.also { cache.put(obj, it) } + } - private fun getSourceId(source: String): Int? { - cache.sourceKeys.getIfPresent(source)?.let { return it } + private fun getOrCreatePlayerId(playerId: UUID): Int = + getOrCreateObjectId(playerId, cache.playerKeys, Tables.Player, Tables.Players, Tables.Players.playerId) - return Tables.Source.find { Tables.Sources.name eq source }.firstOrNull()?.id?.value.also { - it?.let { cache.sourceKeys.put(source, it) } - } - } + private fun getOrCreateSourceId(source: String): Int = + getOrCreateObjectId(source, cache.sourceKeys, Tables.Source, Tables.Sources, Tables.Sources.name) - private fun getOrCreateSourceId(source: String): Int { - cache.sourceKeys.getIfPresent(source)?.let { return it } - Tables.Source.find { Tables.Sources.name eq source }.firstOrNull()?.let { return it.id.value } + private fun getOrCreateActionId(actionTypeId: String): Int = + getOrCreateObjectId( + actionTypeId, + cache.actionIdentifierKeys, + Tables.ActionIdentifier, + Tables.ActionIdentifiers, + Tables.ActionIdentifiers.actionIdentifier + ) - return Tables.Source[ - Tables.Sources.insertAndGetId { - it[name] = source - } - ].id.value.also { cache.sourceKeys.put(source, it) } - } + private fun getOrCreateRegistryKeyId(identifier: Identifier): Int = + getOrCreateObjectId( + identifier, + Identifier::toString, + cache.objectIdentifierKeys, + Tables.ObjectIdentifier, + Tables.ObjectIdentifiers, + Tables.ObjectIdentifiers.identifier + ) - private fun getActionId(actionTypeId: String): Int { - cache.actionIdentifierKeys.getIfPresent(actionTypeId)?.let { return it } + private fun getOrCreateWorldId(identifier: Identifier): Int = + getOrCreateObjectId( + identifier, + Identifier::toString, + cache.worldIdentifierKeys, + Tables.World, + Tables.Worlds, + Tables.Worlds.identifier + ) - return Tables.ActionIdentifier.find { Tables.ActionIdentifiers.actionIdentifier eq actionTypeId } - .first().id.value - .also { cache.actionIdentifierKeys.put(actionTypeId, it) } - } + private fun getPlayerId(playerId: UUID): Int? = + getObjectId(playerId, cache.playerKeys, Tables.Player, Tables.Players.playerId) - private fun getRegistryKeyId(identifier: Identifier): Int { - cache.objectIdentifierKeys.getIfPresent(identifier)?.let { return it } + private fun getSourceId(source: String): Int? = + getObjectId(source, cache.sourceKeys, Tables.Source, Tables.Sources.name) - return Tables.ObjectIdentifier.find { Tables.ObjectIdentifiers.identifier eq identifier.toString() } - .limit(1).first().id.value - .also { cache.objectIdentifierKeys.put(identifier, it) } - } + private fun getActionId(actionTypeId: String): Int? = + getObjectId( + actionTypeId, + cache.actionIdentifierKeys, + Tables.ActionIdentifier, + Tables.ActionIdentifiers.actionIdentifier + ) - private fun getWorldId(identifier: Identifier): Int { - cache.worldIdentifierKeys.getIfPresent(identifier)?.let { return it } + private fun getRegistryKeyId(identifier: Identifier): Int? = + getObjectId( + identifier, + Identifier::toString, + cache.objectIdentifierKeys, + Tables.ObjectIdentifier, + Tables.ObjectIdentifiers.identifier + ) - return Tables.World.find { Tables.Worlds.identifier eq identifier.toString() }.limit(1).first().id.value - .also { cache.worldIdentifierKeys.put(identifier, it) } - } + private fun getWorldId(identifier: Identifier): Int? = + getObjectId( + identifier, + Identifier::toString, + cache.worldIdentifierKeys, + Tables.World, + Tables.Worlds.identifier + ) // Workaround because can't delete from a join in exposed https://kotlinlang.slack.com/archives/C0CG7E0A1/p1605866974117400 private fun Transaction.purgeActions(params: ActionSearchParams) = Tables.Actions From 5041b93380856fd7cf77ef7bc255faef6202a774 Mon Sep 17 00:00:00 2001 From: Tim Kolijn Date: Thu, 30 May 2024 00:12:35 +0200 Subject: [PATCH 2/7] Update install.md (#259) --- docs/install.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/install.md b/docs/install.md index 1034f412..91a40f72 100644 --- a/docs/install.md +++ b/docs/install.md @@ -40,7 +40,7 @@ properties = [] `url`: Must be URL of database with `/` appended. An example URL would be `localhost/ledger`. You can optionally add port information such as `localhost:3000/ledger` ### PostgreSQL -MySQL requires running a separate PostgreSQL database and more setup than just plug and play SQLite, but can support much larger databases at faster speeds. It is more experimental the MySQL but may yield faster performance. +PostgreSQL requires running a separate PostgreSQL database and more setup than just plug and play SQLite, but can support much larger databases at faster speeds. It is more experimental the MySQL but may yield faster performance. Add the following to the bottom of your Ledger config file: From 7cc3337efc3a970fa515bf1a4ac1acb794ef65bf Mon Sep 17 00:00:00 2001 From: matisanabria <143863247+matisanabria@users.noreply.github.com> Date: Wed, 29 May 2024 18:17:43 -0400 Subject: [PATCH 3/7] Spanish translation for Ledger (#263) --- .../resources/data/ledger/lang/es_es.json | 66 +++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 src/main/resources/data/ledger/lang/es_es.json diff --git a/src/main/resources/data/ledger/lang/es_es.json b/src/main/resources/data/ledger/lang/es_es.json new file mode 100644 index 00000000..07b45447 --- /dev/null +++ b/src/main/resources/data/ledger/lang/es_es.json @@ -0,0 +1,66 @@ +{ + "text.ledger.header.search.pos": "--- Buscando registros en %s ---", + "text.ledger.header.search": "------ Buscando registros ------", + "text.ledger.header.status": "------ Ledger ------", + + "text.ledger.footer.search": "------- %s [Página %s de %s] %s -------", + "text.ledger.footer.page_forward": ">>", + "text.ledger.footer.page_forward.hover": "Página siguiente", + "text.ledger.footer.page_backward": "<<", + "text.ledger.footer.page_backward.hover": "Página anterior", + + "text.ledger.status.queue": "Cola de Base de Datos: %s", + "text.ledger.status.queue.busy": "Ocupada", + "text.ledger.status.queue.empty": "Vacía", + "text.ledger.status.version": "Versión: %s", + "text.ledger.status.discord": "Discord: %s", + "text.ledger.status.discord.join": "Clic para unirse", + "text.ledger.status.db_type": "Tipo de Base de Datos: %s", + "text.ledger.status.wiki": "Wiki: %s", + "text.ledger.status.wiki.view": "Clic para ver", + + "text.ledger.preview.start": "Iniciando vista previa", + + "text.ledger.action_message": "%1$s %2$s %3$s %4$s %5$s", + "text.ledger.action_message.time_diff": "hace %s", + "text.ledger.action_message.location.hover": "Clic para teletransportarse", + "text.ledger.action_message.with": "with", + + "text.ledger.rollback.start": "Retrocediendo %s acciones", + "text.ledger.rollback.finish": "Retroceso completo", + "text.ledger.rollback.fail": "Fallo al retroceder %s x%s", + + "text.ledger.restore.start": "Restaurando %s acciones", + "text.ledger.restore.finish": "Restauración completa", + "text.ledger.restore.fail": "Fallo al restaurar %s x%s", + + "text.ledger.inspect.toggle": "Modo de inspección: %s", + "text.ledger.inspect.on": "Activado", + "text.ledger.inspect.off": "Desactivado", + + "text.ledger.database.busy": "La base de datos está actualmente ocupada, esto puede tomar un momento.", + + "error.ledger.no_cached_params": "Sin búsqueda en caché, realice una búsqueda antes de continuar.", + "error.ledger.command.no_results": "Sin resultados de búsqueda", + "error.ledger.no_more_pages": "No más páginas", + "error.ledger.unknown_param": "Parámetro desconocido %s", + "error.ledger.no_preview": "Sin vista previa", + + "text.ledger.action.block-place": "colocado", + "text.ledger.action.block-break": "roto", + "text.ledger.action.block-change": "cambiado", + "text.ledger.action.item-insert": "añadido", + "text.ledger.action.item-remove": "quitado", + "text.ledger.action.item-pick-up": "recogido", + "text.ledger.action.item-drop": "dropeado", + "text.ledger.action.entity-kill": "matado", + "text.ledger.action.entity-change": "cambiado", + + "text.ledger.network.protocols_mismatched": "Las versiones del protocolo no coinciden: la versión del Ledger es %d y la versión del cliente es %d", + "text.ledger.network.no_mod_info": "No se pudo identificar la información del mod de cliente.", + + "text.ledger.purge.starting": "------ Iniciando purga ------", + "text.ledger.purge.complete": "------ Purga completada ------", + + "text.ledger.player.result": "%1$s: Primera conexión: %2$s. Última conexión: %3$s" +} \ No newline at end of file From d62c25fb4a61a5d6fcd90d7a0e0a3c95bbf228ee Mon Sep 17 00:00:00 2001 From: Will Date: Wed, 29 May 2024 18:07:27 -0700 Subject: [PATCH 4/7] Custom database file locations (#264) --- docs/config.md | 15 ++++++++++++++- .../ledger/api/ExtensionManager.kt | 4 ++-- .../ledger/config/DatabaseSpec.kt | 14 ++++++++++++++ .../ledger/database/DatabaseManager.kt | 4 ++-- src/main/resources/ledger.toml | 2 ++ 5 files changed, 34 insertions(+), 5 deletions(-) diff --git a/docs/config.md b/docs/config.md index 539baeb9..279d4eb3 100644 --- a/docs/config.md +++ b/docs/config.md @@ -14,7 +14,20 @@ Found under `[database]` `queueTimeoutMin` [Default: 5] is the maximum amount of time to wait for the queue to drain when the server stops in minutes -`queueCheckDelaySec` [Default: 10] is the amount of time between checking if the queue is empty when the server stops in seconds +`queueCheckDelaySec` [Default: 10] is the frequency in seconds to notify in console that the queue is not empty when the server stops + +`autoPurgeDays` [Default: -1] is the number of days to keep actions in the database. If set to -1, actions will never be purged automatically + +`batchSize` [Default: 1000] is the number of actions to insert into the database at once. +This can be increased to improve performance, but may cause issues with slow databases + +`batchDelay` [Default: 10] is the amount of time in ticks to wait between batches if the next batch isn't full. +This can be increased to improve performance, but may cause issues with slow databases + +`location` [Default: Nothing] is the location of the database file when using the default SQLite database or other file based databases like H2. +The path is relative to the server's root directory. If the path is left out, the database will default to the server's world directory. + +`logSQL` [Default: false] will log all SQL queries to the console. This is useful for debugging, but can be very spammy ### Search settings diff --git a/src/main/kotlin/com/github/quiltservertools/ledger/api/ExtensionManager.kt b/src/main/kotlin/com/github/quiltservertools/ledger/api/ExtensionManager.kt index ee59f709..e676e127 100644 --- a/src/main/kotlin/com/github/quiltservertools/ledger/api/ExtensionManager.kt +++ b/src/main/kotlin/com/github/quiltservertools/ledger/api/ExtensionManager.kt @@ -2,8 +2,8 @@ package com.github.quiltservertools.ledger.api import com.github.quiltservertools.ledger.Ledger import com.github.quiltservertools.ledger.config.config +import com.github.quiltservertools.ledger.config.getDatabasePath import net.minecraft.server.MinecraftServer -import net.minecraft.util.WorldSavePath import javax.sql.DataSource object ExtensionManager { @@ -30,7 +30,7 @@ object ExtensionManager { extensions.forEach { if (it is DatabaseExtension) { if (dataSource == null) { - dataSource = it.getDataSource(server.getSavePath(WorldSavePath.ROOT)) + dataSource = it.getDataSource(config.getDatabasePath()) } else { failExtensionRegistration(it) } diff --git a/src/main/kotlin/com/github/quiltservertools/ledger/config/DatabaseSpec.kt b/src/main/kotlin/com/github/quiltservertools/ledger/config/DatabaseSpec.kt index 8314ab96..62e953f2 100644 --- a/src/main/kotlin/com/github/quiltservertools/ledger/config/DatabaseSpec.kt +++ b/src/main/kotlin/com/github/quiltservertools/ledger/config/DatabaseSpec.kt @@ -1,6 +1,10 @@ package com.github.quiltservertools.ledger.config +import com.github.quiltservertools.ledger.Ledger +import com.uchuhimo.konf.Config import com.uchuhimo.konf.ConfigSpec +import net.minecraft.util.WorldSavePath +import java.nio.file.Path @Suppress("MagicNumber") object DatabaseSpec : ConfigSpec() { @@ -10,4 +14,14 @@ object DatabaseSpec : ConfigSpec() { val batchSize by optional(1000) val batchDelay by optional(10) val logSQL by optional(false) + val location by optional(null) +} + +fun Config.getDatabasePath(): Path { + val location = config[DatabaseSpec.location] + return if (location != null) { + Path.of(location) + } else { + Ledger.server.getSavePath(WorldSavePath.ROOT) + } } diff --git a/src/main/kotlin/com/github/quiltservertools/ledger/database/DatabaseManager.kt b/src/main/kotlin/com/github/quiltservertools/ledger/database/DatabaseManager.kt index 1eb647c9..13cf4c7d 100644 --- a/src/main/kotlin/com/github/quiltservertools/ledger/database/DatabaseManager.kt +++ b/src/main/kotlin/com/github/quiltservertools/ledger/database/DatabaseManager.kt @@ -8,6 +8,7 @@ import com.github.quiltservertools.ledger.actionutils.SearchResults import com.github.quiltservertools.ledger.config.DatabaseSpec import com.github.quiltservertools.ledger.config.SearchSpec import com.github.quiltservertools.ledger.config.config +import com.github.quiltservertools.ledger.config.getDatabasePath import com.github.quiltservertools.ledger.logInfo import com.github.quiltservertools.ledger.logWarn import com.github.quiltservertools.ledger.registry.ActionRegistry @@ -17,7 +18,6 @@ import com.google.common.cache.Cache import com.mojang.authlib.GameProfile import kotlinx.coroutines.delay import net.minecraft.util.Identifier -import net.minecraft.util.WorldSavePath import net.minecraft.util.math.BlockPos import org.jetbrains.exposed.dao.Entity import org.jetbrains.exposed.dao.EntityClass @@ -81,7 +81,7 @@ object DatabaseManager { } private fun getDefaultDatasource(): DataSource { - val dbFilepath = Ledger.server.getSavePath(WorldSavePath.ROOT).resolve("ledger.sqlite").pathString + val dbFilepath = config.getDatabasePath().resolve("ledger.sqlite").pathString return SQLiteDataSource(SQLiteConfig().apply { setJournalMode(SQLiteConfig.JournalMode.WAL) }).apply { diff --git a/src/main/resources/ledger.toml b/src/main/resources/ledger.toml index b04e48a8..eb32917d 100644 --- a/src/main/resources/ledger.toml +++ b/src/main/resources/ledger.toml @@ -9,6 +9,8 @@ autoPurgeDays = -1 batchSize = 1000 # The amount of time to wait between batches in ticks (20 ticks = 1 second) batchDelay = 10 +# The location of the database file. Defaults to the world folder if not specified +#location = "./custom-dir" [search] # Number of actions to show per page From 3335e5d7d6a532b4497f4f625e4c08602f12bb62 Mon Sep 17 00:00:00 2001 From: Will Date: Thu, 30 May 2024 11:51:50 -0700 Subject: [PATCH 5/7] Bump version to 1.3.1 (#265) --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index d771a068..d7ea39e9 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,7 +2,7 @@ kotlin.code.style=official org.gradle.jvmargs=-Xmx2G # Mod Properties -modVersion = 1.3.0 +modVersion = 1.3.1 mavenGroup = com.github.quiltservertools modId = ledger modName = Ledger From bbe4d75d99a053af1b1b56ae02a285e72ea2df56 Mon Sep 17 00:00:00 2001 From: Drex Date: Sun, 2 Jun 2024 00:32:38 +0200 Subject: [PATCH 6/7] Update to 1.20.5/6 (#262) Co-authored-by: Potatoboy9999 <51728317+PotatoPresident@users.noreply.github.com> --- .github/workflows/build-docs.yml | 4 +- .github/workflows/build.yml | 11 ++- .github/workflows/release.yml | 9 +- build.gradle.kts | 4 +- detekt.yml | 42 +++----- docs/index.md | 2 +- gradle.properties | 2 +- libs.versions.toml | 22 +++-- .../mixin/BucketDispenserBehaviorMixin.java | 6 +- .../ledger/mixin/BucketItemMixin.java | 2 +- .../ledger/mixin/blocks/BedBlockMixin.java | 5 +- .../ledger/mixin/blocks/CakeBlockMixin.java | 6 +- .../mixin/blocks/CampfireBlockMixin.java | 15 +-- .../mixin/blocks/ComparatorBlockMixin.java | 3 +- .../blocks/DaylightDetectorBlockMixin.java | 3 +- .../ledger/mixin/blocks/DoorBlockMixin.java | 3 +- .../mixin/blocks/FenceGateBlockMixin.java | 3 +- .../mixin/blocks/FlowerPotBlockMixin.java | 3 +- .../mixin/blocks/JukeBoxBlockMixin.java | 3 +- .../ledger/mixin/blocks/LeverBlockMixin.java | 3 +- .../ledger/mixin/blocks/NoteBlockMixin.java | 3 +- .../mixin/blocks/RepeaterBlockMixin.java | 3 +- .../blocks/lectern/ScreenHandlerMixin.java | 2 +- .../blocks/sign/AbstractSignBlockMixin.java | 6 +- .../blocks/sign/SignBlockEntityMixin.java | 11 ++- .../github/quiltservertools/ledger/Ledger.kt | 16 +++- .../ledger/actions/AbstractActionType.kt | 9 +- .../ledger/actions/ActionType.kt | 5 +- .../ledger/actions/BlockBreakActionType.kt | 3 +- .../ledger/actions/BlockChangeActionType.kt | 26 +++-- .../ledger/actions/BlockPlaceActionType.kt | 5 +- .../ledger/actions/EntityChangeActionType.kt | 13 +-- .../ledger/actions/EntityKillActionType.kt | 2 +- .../ledger/actions/ItemChangeActionType.kt | 23 +++-- .../ledger/actions/ItemDropActionType.kt | 17 +++- .../ledger/actions/ItemPickUpActionType.kt | 17 +++- .../ledger/actionutils/ActionFactory.kt | 8 +- .../ledger/actionutils/ActionSearchParams.kt | 12 ++- .../ledger/actionutils/Preview.kt | 1 - .../ledger/callbacks/BlockChangeCallback.kt | 31 +++++- .../commands/parameters/ObjectParameter.kt | 12 ++- .../commands/subcommands/PlayerCommand.kt | 7 +- .../commands/subcommands/PreviewCommand.kt | 6 +- .../commands/subcommands/PurgeCommand.kt | 6 +- .../commands/subcommands/SearchCommand.kt | 6 +- .../commands/subcommands/StatusCommand.kt | 6 +- .../commands/subcommands/TeleportCommand.kt | 8 +- .../ledger/database/DatabaseManager.kt | 5 +- .../ledger/database/Tables.kt | 1 - .../ledger/listeners/BlockEventListener.kt | 1 - .../listeners/EntityCallbackListener.kt | 1 - .../ledger/listeners/PlayerEventListener.kt | 1 - .../ledger/network/Networking.kt | 46 ++++----- .../ledger/network/packet/LedgerPacket.kt | 10 -- .../network/packet/action/ActionPacket.kt | 33 ------- .../network/packet/action/ActionS2CPacket.kt | 39 ++++++++ .../packet/handshake/HandshakePacket.kt | 27 ------ .../packet/handshake/HandshakeS2CPacket.kt | 33 +++++++ .../network/packet/handshake/ModInfo.kt | 2 +- .../packet/receiver/HandshakeC2SPacket.kt | 87 +++++++++++++++++ .../receiver/HandshakePacketReceiver.kt | 75 --------------- .../packet/receiver/InspectC2SPacket.kt | 65 +++++++++++++ .../packet/receiver/InspectReceiver.kt | 54 ----------- .../network/packet/receiver/PurgeC2SPacket.kt | 65 +++++++++++++ .../network/packet/receiver/PurgeReceiver.kt | 45 --------- .../packet/receiver/RollbackC2SPacket.kt | 58 +++++++++++ .../packet/receiver/RollbackReceiver.kt | 76 --------------- .../packet/receiver/SearchC2SPacket.kt | 96 +++++++++++++++++++ .../network/packet/receiver/SearchReceiver.kt | 82 ---------------- .../network/packet/response/ResponsePacket.kt | 27 ------ .../packet/response/ResponseS2CPacket.kt | 29 ++++++ .../ledger/utility/InspectionManager.kt | 7 +- .../ledger/utility/MessageUtils.kt | 9 +- .../ledger/utility/NbtUtils.kt | 74 +++++++------- .../ledger/utility/Negatable.kt | 1 + .../ledger/utility/PlayerResult.kt | 7 +- .../ledger/utility/TextColorPallet.kt | 10 +- src/main/resources/fabric.mod.json | 4 +- .../ledger/testmod/LedgerTest.kt | 59 +++--------- .../commands/packet/ActionS2CPacket.kt | 58 +++++++++++ .../commands/packet/HandshakeC2SPacket.kt | 24 +++++ .../commands/packet/HandshakeS2CPacket.kt | 39 ++++++++ .../commands/packet/InspectC2SPacket.kt | 24 +++++ .../commands/packet/SearchC2SPacket.kt | 23 +++++ 84 files changed, 993 insertions(+), 719 deletions(-) delete mode 100644 src/main/kotlin/com/github/quiltservertools/ledger/network/packet/LedgerPacket.kt delete mode 100644 src/main/kotlin/com/github/quiltservertools/ledger/network/packet/action/ActionPacket.kt create mode 100644 src/main/kotlin/com/github/quiltservertools/ledger/network/packet/action/ActionS2CPacket.kt delete mode 100644 src/main/kotlin/com/github/quiltservertools/ledger/network/packet/handshake/HandshakePacket.kt create mode 100644 src/main/kotlin/com/github/quiltservertools/ledger/network/packet/handshake/HandshakeS2CPacket.kt create mode 100644 src/main/kotlin/com/github/quiltservertools/ledger/network/packet/receiver/HandshakeC2SPacket.kt delete mode 100644 src/main/kotlin/com/github/quiltservertools/ledger/network/packet/receiver/HandshakePacketReceiver.kt create mode 100644 src/main/kotlin/com/github/quiltservertools/ledger/network/packet/receiver/InspectC2SPacket.kt delete mode 100644 src/main/kotlin/com/github/quiltservertools/ledger/network/packet/receiver/InspectReceiver.kt create mode 100644 src/main/kotlin/com/github/quiltservertools/ledger/network/packet/receiver/PurgeC2SPacket.kt delete mode 100644 src/main/kotlin/com/github/quiltservertools/ledger/network/packet/receiver/PurgeReceiver.kt create mode 100644 src/main/kotlin/com/github/quiltservertools/ledger/network/packet/receiver/RollbackC2SPacket.kt delete mode 100644 src/main/kotlin/com/github/quiltservertools/ledger/network/packet/receiver/RollbackReceiver.kt create mode 100644 src/main/kotlin/com/github/quiltservertools/ledger/network/packet/receiver/SearchC2SPacket.kt delete mode 100644 src/main/kotlin/com/github/quiltservertools/ledger/network/packet/receiver/SearchReceiver.kt delete mode 100644 src/main/kotlin/com/github/quiltservertools/ledger/network/packet/response/ResponsePacket.kt create mode 100644 src/main/kotlin/com/github/quiltservertools/ledger/network/packet/response/ResponseS2CPacket.kt create mode 100644 src/testmod/kotlin/com/github/quiltservertools/ledger/testmod/commands/packet/ActionS2CPacket.kt create mode 100644 src/testmod/kotlin/com/github/quiltservertools/ledger/testmod/commands/packet/HandshakeC2SPacket.kt create mode 100644 src/testmod/kotlin/com/github/quiltservertools/ledger/testmod/commands/packet/HandshakeS2CPacket.kt create mode 100644 src/testmod/kotlin/com/github/quiltservertools/ledger/testmod/commands/packet/InspectC2SPacket.kt create mode 100644 src/testmod/kotlin/com/github/quiltservertools/ledger/testmod/commands/packet/SearchC2SPacket.kt diff --git a/.github/workflows/build-docs.yml b/.github/workflows/build-docs.yml index f6dbe24e..a1692354 100644 --- a/.github/workflows/build-docs.yml +++ b/.github/workflows/build-docs.yml @@ -10,11 +10,11 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v2 + uses: actions/checkout@v4 with: fetch-depth: 0 - name: Set up python 3 - uses: actions/setup-python@v2 + uses: actions/setup-python@v5 with: python-version: 3.x - name: Install mkdocs and mike diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 86edd206..ad3b177c 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -11,15 +11,16 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - name: Set up JDK 17 - uses: actions/setup-java@v1 + - uses: actions/checkout@v4 + - name: Set up JDK 21 + uses: actions/setup-java@v4 with: - java-version: 17 + java-version: 21 + distribution: 'temurin' - name: Build artifacts run: ./gradlew build - name: Upload build artifacts - uses: actions/upload-artifact@v1 + uses: actions/upload-artifact@v4 with: name: build-artifacts path: build/libs \ No newline at end of file diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 1338d250..109814e8 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -9,12 +9,13 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - - name: Set up JDK 17 - uses: actions/setup-java@v1 + - name: Set up JDK 21 + uses: actions/setup-java@v4 with: - java-version: 17 + java-version: 21 + distribution: 'temurin' - name: Build release run: ./gradlew build diff --git a/build.gradle.kts b/build.gradle.kts index ea43f3e0..69b018e1 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -84,10 +84,12 @@ dependencies { // Config shadow(libs.konf.core) shadow(libs.konf.toml) + + detektPlugins(libs.detekt.formatting) } tasks { - val javaVersion = JavaVersion.VERSION_17 + val javaVersion = JavaVersion.VERSION_21 processResources { inputs.property("id", modId) diff --git a/detekt.yml b/detekt.yml index 1c47e569..7834e88d 100644 --- a/detekt.yml +++ b/detekt.yml @@ -70,7 +70,7 @@ complexity: threshold: 10 includeStaticDeclarations: false includePrivateDeclarations: false - ComplexMethod: + CyclomaticComplexMethod: active: false threshold: 15 ignoreSingleWhenExpression: false @@ -258,7 +258,6 @@ formatting: active: false autoCorrect: false indentSize: 4 - continuationIndentSize: 4 MaximumLineLength: active: true maxLineLength: 120 @@ -359,7 +358,6 @@ naming: parameterPattern: '[a-z][A-Za-z0-9]*' privateParameterPattern: '[a-z][A-Za-z0-9]*' excludeClassPattern: '$^' - ignoreOverridden: true EnumNaming: active: true excludes: ['**/test/**', '**/androidTest/**', '**/*.Test.kt', '**/*.Spec.kt', '**/*.Spek.kt'] @@ -381,13 +379,11 @@ naming: excludes: ['**/test/**', '**/androidTest/**', '**/*.Test.kt', '**/*.Spec.kt', '**/*.Spek.kt'] functionPattern: '^([a-z$][a-zA-Z$0-9]*)|(`.*`)$' excludeClassPattern: '$^' - ignoreOverridden: true FunctionParameterNaming: active: true excludes: ['**/test/**', '**/androidTest/**', '**/*.Test.kt', '**/*.Spec.kt', '**/*.Spek.kt'] parameterPattern: '[a-z][A-Za-z0-9]*' excludeClassPattern: '$^' - ignoreOverridden: true InvalidPackageDeclaration: # If you want to use this, set the root package and enable it active: false rootPackage: 'template' @@ -429,7 +425,6 @@ naming: variablePattern: '[a-z][A-Za-z0-9]*' privateVariablePattern: '(_)?[a-z][A-Za-z0-9]*' excludeClassPattern: '$^' - ignoreOverridden: true performance: active: true @@ -448,8 +443,6 @@ potential-bugs: active: true Deprecation: active: true - DuplicateCaseInWhenExpression: - active: true EqualsAlwaysReturnsTrueOrFalse: active: true EqualsWithHashCodeExist: @@ -474,16 +467,12 @@ potential-bugs: LateinitUsage: active: false excludes: ['**/test/**', '**/androidTest/**', '**/*.Test.kt', '**/*.Spec.kt', '**/*.Spek.kt'] - excludeAnnotatedProperties: [] + ignoreAnnotated: [] ignoreOnClassesPattern: '' MapGetWithNotNullAssertionOperator: active: true - MissingWhenCase: - active: true NullableToStringCall: active: true - RedundantElseInWhen: - active: true UnconditionalJumpStatementInLoop: active: true UnnecessaryNotNullOperator: @@ -503,13 +492,15 @@ potential-bugs: style: active: true + BracesOnWhenStatements: + active: true ClassOrdering: active: true CollapsibleIfStatements: active: true DataClassContainsFunctions: active: false - conversionFunctionPrefix: 'to' + conversionFunctionPrefix: ['to'] DataClassShouldBeImmutable: active: false EqualsNullCall: @@ -525,7 +516,7 @@ style: includeLineWrapping: false ForbiddenComment: active: false - values: ['TODO:', 'FIXME:', 'STOPSHIP:'] + comments: ['TODO:', 'FIXME:', 'STOPSHIP:'] allowedPatterns: '' ForbiddenImport: active: false @@ -534,9 +525,6 @@ style: ForbiddenMethodCall: active: false methods: [] - ForbiddenPublicDataClass: - active: false - ignorePackages: ['*.internal', '*.internal.*'] ForbiddenVoid: active: true ignoreOverridden: true @@ -544,8 +532,8 @@ style: FunctionOnlyReturningConstant: active: true ignoreOverridableFunction: true - excludedFunctions: 'describeContents' - excludeAnnotatedFunction: ['dagger.Provides'] + excludedFunctions: ['describeContents'] + ignoreAnnotated: ['dagger.Provides'] LibraryCodeMustSpecifyReturnType: active: true LibraryEntitiesShouldNotBePublic: @@ -566,7 +554,7 @@ style: ignoreNamedArgument: true ignoreEnums: true ignoreRanges: false - MandatoryBracesIfStatements: + BracesOnIfStatements: active: true MandatoryBracesLoops: active: true @@ -590,8 +578,6 @@ style: active: true OptionalUnit: active: false - OptionalWhenBraces: - active: true PreferToOverPairSyntax: active: true ProtectedMemberInFinalClass: @@ -603,7 +589,7 @@ style: ReturnCount: active: false max: 2 - excludedFunctions: 'equals' + excludedFunctions: ['equals'] excludeLabeled: false excludeReturnFromLambda: true excludeGuardClauses: false @@ -620,10 +606,10 @@ style: active: true UnderscoresInNumericLiterals: active: true - acceptableDecimalLength: 5 + acceptableLength: 5 UnnecessaryAbstractClass: active: true - excludeAnnotatedClasses: ['dagger.Module'] + ignoreAnnotated: ['dagger.Module'] UnnecessaryAnnotationUseSiteTarget: active: true UnnecessaryApply: @@ -638,6 +624,8 @@ style: active: true UnusedImports: active: true + UnusedParameter: + active: false UnusedPrivateClass: active: true UnusedPrivateMember: @@ -651,7 +639,7 @@ style: active: true UseDataClass: active: true - excludeAnnotatedClasses: [] + ignoreAnnotated: [] allowVars: false UseEmptyCounterpart: active: true diff --git a/docs/index.md b/docs/index.md index 43a168a1..bf8d2d17 100644 --- a/docs/index.md +++ b/docs/index.md @@ -3,5 +3,5 @@ ![Last commit](https://img.shields.io/github/last-commit/quiltservertools/ledger?color=7e56c2&style=for-the-badge) ![Contributors](https://img.shields.io/github/contributors/quiltservertools/ledger?color=7e56c2&style=for-the-badge) -Ledger is a server-side fabric logging mod for modern Minecraft 1.17 and 1.18. +Ledger is a server-side fabric logging mod for modern Minecraft 1.17+. Ledger has been written from scratch in Kotlin to solve the main issues of previous logging mods have encountered. diff --git a/gradle.properties b/gradle.properties index d7ea39e9..8da14fbb 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,7 +2,7 @@ kotlin.code.style=official org.gradle.jvmargs=-Xmx2G # Mod Properties -modVersion = 1.3.1 +modVersion = 1.3.2 mavenGroup = com.github.quiltservertools modId = ledger modName = Ledger diff --git a/libs.versions.toml b/libs.versions.toml index 05bbe638..65b44868 100644 --- a/libs.versions.toml +++ b/libs.versions.toml @@ -1,17 +1,17 @@ [versions] -minecraft = "1.20.4" -yarn-mappings = "1.20.4+build.1" -fabric-loader = "0.15.10" +minecraft = "1.20.6" +yarn-mappings = "1.20.6+build.3" +fabric-loader = "0.15.11" -fabric-api = "0.91.3+1.20.4" +fabric-api = "0.99.0+1.20.6" # Kotlin -kotlin = "1.8.22" +kotlin = "1.9.23" # Also modrinth version in gradle.properties -fabric-kotlin = "1.9.4+kotlin.1.8.21" +fabric-kotlin = "1.10.19+kotlin.1.9.23" fabric-permissions = "0.3.1" -translations = "2.2.0+1.20.3-rc1" +translations = "2.3.0+1.20.5-rc2" exposed = "0.46.0" sqlite-jdbc = "3.44.1.0" @@ -20,6 +20,8 @@ konf = "1.1.2" wdmcf = "1.0.2" +detect = "1.23.6" + [libraries] minecraft = { module = "net.minecraft:minecraft", version.ref = "minecraft" } yarn-mappings = { module = "net.fabricmc:yarn", version.ref = "yarn-mappings" } @@ -39,12 +41,14 @@ sqlite-jdbc = { module = "org.xerial:sqlite-jdbc", version.ref = "sqlite-jdbc" } konf-core = { module = "com.uchuhimo:konf-core", version.ref = "konf"} konf-toml = { module = "com.uchuhimo:konf-toml", version.ref = "konf"} +detekt-formatting = { module = "io.gitlab.arturbosch.detekt:detekt-formatting", version.ref = "detect" } wdmcf = { module = "me.bymartrixx:wdmcf", version.ref = "wdmcf" } [plugins] kotlin = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" } -detekt = { id = "io.gitlab.arturbosch.detekt", version = "1.19.0" } +detekt = { id = "io.gitlab.arturbosch.detekt", version.ref = "detect" } loom = { id = "fabric-loom", version = "1.6.+" } git_hooks = { id = "com.github.jakemarsden.git-hooks", version = "0.0.2" } -shadow = { id = "com.github.johnrengelman.shadow", version = "7.1.2" } \ No newline at end of file +# https://github.com/johnrengelman/shadow/issues/894 +shadow = { id = "io.github.goooler.shadow", version = "8.1.7" } diff --git a/src/main/java/com/github/quiltservertools/ledger/mixin/BucketDispenserBehaviorMixin.java b/src/main/java/com/github/quiltservertools/ledger/mixin/BucketDispenserBehaviorMixin.java index 52c1e085..e12f6b37 100644 --- a/src/main/java/com/github/quiltservertools/ledger/mixin/BucketDispenserBehaviorMixin.java +++ b/src/main/java/com/github/quiltservertools/ledger/mixin/BucketDispenserBehaviorMixin.java @@ -15,18 +15,18 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -@Mixin(targets = "net/minecraft/block/dispenser/DispenserBehavior$9") +@Mixin(targets = "net/minecraft/block/dispenser/DispenserBehavior$16") public abstract class BucketDispenserBehaviorMixin extends ItemDispenserBehavior { @Inject( - method = "dispenseSilently(Lnet/minecraft/util/math/BlockPointer;Lnet/minecraft/item/ItemStack;)Lnet/minecraft/item/ItemStack;", + method = "dispenseSilently", at = @At( value = "INVOKE", target = "Lnet/minecraft/block/FluidDrainable;tryDrainFluid(Lnet/minecraft/entity/player/PlayerEntity;Lnet/minecraft/world/WorldAccess;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/block/BlockState;)Lnet/minecraft/item/ItemStack;", shift = At.Shift.AFTER ) ) - private void logFluidPickup(BlockPointer pointer, ItemStack stack, CallbackInfoReturnable cir, @Local ItemStack itemStack, @Local BlockPos pos, @Local BlockState blockState) { + private void logFluidPickup(BlockPointer pointer, ItemStack stack, CallbackInfoReturnable cir, @Local(argsOnly = true) ItemStack itemStack, @Local BlockPos pos, @Local BlockState blockState) { var world = pointer.world(); if (!itemStack.isEmpty()) { if (blockState.isLiquid() || blockState.isOf(Blocks.POWDER_SNOW)) { diff --git a/src/main/java/com/github/quiltservertools/ledger/mixin/BucketItemMixin.java b/src/main/java/com/github/quiltservertools/ledger/mixin/BucketItemMixin.java index 1c040356..c335a9c0 100644 --- a/src/main/java/com/github/quiltservertools/ledger/mixin/BucketItemMixin.java +++ b/src/main/java/com/github/quiltservertools/ledger/mixin/BucketItemMixin.java @@ -72,7 +72,7 @@ private void logWaterlog(PlayerEntity player, World world, BlockPos pos, BlockHi } } - @Inject(method = "use", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/player/PlayerEntity;incrementStat(Lnet/minecraft/stat/Stat;)V")) + @Inject(method = "use", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/player/PlayerEntity;incrementStat(Lnet/minecraft/stat/Stat;)V", ordinal = 0)) private void logFluidPickup(World world, PlayerEntity player, Hand hand, CallbackInfoReturnable> cir, @Local(ordinal = 0) BlockPos pos, @Local BlockState blockState) { if (blockState.getBlock() instanceof Waterloggable) { BlockChangeCallback.EVENT.invoker().changeBlock( diff --git a/src/main/java/com/github/quiltservertools/ledger/mixin/blocks/BedBlockMixin.java b/src/main/java/com/github/quiltservertools/ledger/mixin/blocks/BedBlockMixin.java index bc8ef93f..d1f56d25 100644 --- a/src/main/java/com/github/quiltservertools/ledger/mixin/blocks/BedBlockMixin.java +++ b/src/main/java/com/github/quiltservertools/ledger/mixin/blocks/BedBlockMixin.java @@ -8,7 +8,6 @@ import net.minecraft.block.enums.BedPart; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.util.ActionResult; -import net.minecraft.util.Hand; import net.minecraft.util.hit.BlockHitResult; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; @@ -35,12 +34,12 @@ public void logBedBreak(World world, BlockPos pos, BlockState state, PlayerEntit } @Inject(method = "onUse", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/World;removeBlock(Lnet/minecraft/util/math/BlockPos;Z)Z")) - public void storeBlockEntity(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit, CallbackInfoReturnable cir) { + public void storeBlockEntity(BlockState state, World world, BlockPos pos, PlayerEntity player, BlockHitResult hit, CallbackInfoReturnable cir) { oldBlockEntity = world.getBlockEntity(pos); } @Inject(method = "onUse", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/World;removeBlock(Lnet/minecraft/util/math/BlockPos;Z)Z", shift = At.Shift.AFTER)) - public void logBedExplosion(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit, CallbackInfoReturnable cir) { + public void logBedExplosion(BlockState state, World world, BlockPos pos, PlayerEntity player, BlockHitResult hit, CallbackInfoReturnable cir) { BlockBreakCallback.EVENT.invoker().breakBlock(world, pos, state, oldBlockEntity, Sources.INTERACT, player); } } diff --git a/src/main/java/com/github/quiltservertools/ledger/mixin/blocks/CakeBlockMixin.java b/src/main/java/com/github/quiltservertools/ledger/mixin/blocks/CakeBlockMixin.java index fff3b132..c78dc1f6 100644 --- a/src/main/java/com/github/quiltservertools/ledger/mixin/blocks/CakeBlockMixin.java +++ b/src/main/java/com/github/quiltservertools/ledger/mixin/blocks/CakeBlockMixin.java @@ -5,9 +5,11 @@ import net.minecraft.block.BlockState; import net.minecraft.block.CakeBlock; import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.ItemStack; import net.minecraft.state.property.IntProperty; import net.minecraft.util.ActionResult; import net.minecraft.util.Hand; +import net.minecraft.util.ItemActionResult; import net.minecraft.util.hit.BlockHitResult; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; @@ -56,11 +58,11 @@ private static void ledgerLogCakeEatAndRemove( player); } - @Inject(method = "onUse", at = @At(value = "INVOKE", + @Inject(method = "onUseWithItem", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/World;setBlockState(Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/block/BlockState;)Z", shift = At.Shift.AFTER)) private void ledgerLogCakeAddCandle( - BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit, CallbackInfoReturnable cir) { + ItemStack itemStack, BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult blockHitResult, CallbackInfoReturnable cir) { BlockChangeCallback.EVENT.invoker().changeBlock( player.getWorld(), pos, diff --git a/src/main/java/com/github/quiltservertools/ledger/mixin/blocks/CampfireBlockMixin.java b/src/main/java/com/github/quiltservertools/ledger/mixin/blocks/CampfireBlockMixin.java index 030114dd..09e62653 100644 --- a/src/main/java/com/github/quiltservertools/ledger/mixin/blocks/CampfireBlockMixin.java +++ b/src/main/java/com/github/quiltservertools/ledger/mixin/blocks/CampfireBlockMixin.java @@ -2,15 +2,17 @@ import com.github.quiltservertools.ledger.callbacks.BlockChangeCallback; import com.github.quiltservertools.ledger.utility.Sources; +import com.llamalad7.mixinextras.sugar.Local; import net.minecraft.block.BlockState; import net.minecraft.block.CampfireBlock; import net.minecraft.block.entity.BlockEntity; import net.minecraft.entity.Entity; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.projectile.ProjectileEntity; +import net.minecraft.item.ItemStack; import net.minecraft.state.property.BooleanProperty; -import net.minecraft.util.ActionResult; import net.minecraft.util.Hand; +import net.minecraft.util.ItemActionResult; import net.minecraft.util.hit.BlockHitResult; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; @@ -22,7 +24,6 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import org.spongepowered.asm.mixin.injection.callback.LocalCapture; @Mixin(CampfireBlock.class) public abstract class CampfireBlockMixin { @@ -31,15 +32,15 @@ public abstract class CampfireBlockMixin { @Final public static BooleanProperty LIT; - @Inject(method = "onUse", at = @At(value = "INVOKE", - target = "Lnet/minecraft/entity/player/PlayerEntity;incrementStat(Lnet/minecraft/util/Identifier;)V"), - locals = LocalCapture.CAPTURE_FAILEXCEPTION) - public void logCampfireAddItem(BlockState blockState, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit, CallbackInfoReturnable cir, BlockEntity oldBlockEntity) { + @Inject(method = "onUseWithItem", at = @At(value = "INVOKE", + target = "Lnet/minecraft/entity/player/PlayerEntity;incrementStat(Lnet/minecraft/util/Identifier;)V") + ) + public void logCampfireAddItem(ItemStack itemStack, BlockState blockState, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult blockHitResult, CallbackInfoReturnable cir, @Local BlockEntity oldBlockEntity) { BlockChangeCallback.EVENT.invoker().changeBlock(world, pos, blockState, world.getBlockState(pos), oldBlockEntity, world.getBlockEntity(pos), Sources.INSERT, player); } @Inject(method = "extinguish", at = @At(value = "INVOKE", - target = "Lnet/minecraft/world/WorldAccess;emitGameEvent(Lnet/minecraft/entity/Entity;Lnet/minecraft/world/event/GameEvent;Lnet/minecraft/util/math/BlockPos;)V")) + target = "Lnet/minecraft/world/WorldAccess;emitGameEvent(Lnet/minecraft/entity/Entity;Lnet/minecraft/registry/entry/RegistryEntry;Lnet/minecraft/util/math/BlockPos;)V")) private static void logCampfireExtinguish(Entity entity, WorldAccess worldAccess, BlockPos pos, BlockState blockState, CallbackInfo ci) { if (worldAccess instanceof World world) { if (entity instanceof PlayerEntity player) { diff --git a/src/main/java/com/github/quiltservertools/ledger/mixin/blocks/ComparatorBlockMixin.java b/src/main/java/com/github/quiltservertools/ledger/mixin/blocks/ComparatorBlockMixin.java index 1cf958da..698d8c07 100644 --- a/src/main/java/com/github/quiltservertools/ledger/mixin/blocks/ComparatorBlockMixin.java +++ b/src/main/java/com/github/quiltservertools/ledger/mixin/blocks/ComparatorBlockMixin.java @@ -8,7 +8,6 @@ import net.minecraft.entity.player.PlayerEntity; import net.minecraft.state.property.EnumProperty; import net.minecraft.util.ActionResult; -import net.minecraft.util.Hand; import net.minecraft.util.hit.BlockHitResult; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; @@ -26,7 +25,7 @@ public abstract class ComparatorBlockMixin { public static EnumProperty MODE; @Inject(method = "onUse", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/World;setBlockState(Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/block/BlockState;I)Z")) - public void logComparatorInteraction(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit, CallbackInfoReturnable cir) { + public void logComparatorInteraction(BlockState state, World world, BlockPos pos, PlayerEntity player, BlockHitResult hit, CallbackInfoReturnable cir) { BlockChangeCallback.EVENT.invoker().changeBlock(world, pos, state.cycle(MODE), state, world.getBlockEntity(pos), world.getBlockEntity(pos), Sources.INTERACT, player); } } diff --git a/src/main/java/com/github/quiltservertools/ledger/mixin/blocks/DaylightDetectorBlockMixin.java b/src/main/java/com/github/quiltservertools/ledger/mixin/blocks/DaylightDetectorBlockMixin.java index fa99c756..a7b401be 100644 --- a/src/main/java/com/github/quiltservertools/ledger/mixin/blocks/DaylightDetectorBlockMixin.java +++ b/src/main/java/com/github/quiltservertools/ledger/mixin/blocks/DaylightDetectorBlockMixin.java @@ -6,7 +6,6 @@ import net.minecraft.block.DaylightDetectorBlock; import net.minecraft.block.entity.BlockEntity; import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.util.Hand; import net.minecraft.util.hit.BlockHitResult; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; @@ -18,7 +17,7 @@ @Mixin(DaylightDetectorBlock.class) public abstract class DaylightDetectorBlockMixin { @ModifyArgs(method = "onUse", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/World;setBlockState(Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/block/BlockState;I)Z")) - public void logDaylightDetectorToggling(Args args, BlockState oldState, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) { + public void logDaylightDetectorToggling(Args args, BlockState oldState, World world, BlockPos pos, PlayerEntity player, BlockHitResult hit) { BlockState newState = args.get(1); BlockEntity blockEntity = world.getBlockEntity(pos); if (player == null) { diff --git a/src/main/java/com/github/quiltservertools/ledger/mixin/blocks/DoorBlockMixin.java b/src/main/java/com/github/quiltservertools/ledger/mixin/blocks/DoorBlockMixin.java index 46e5476e..72e07366 100644 --- a/src/main/java/com/github/quiltservertools/ledger/mixin/blocks/DoorBlockMixin.java +++ b/src/main/java/com/github/quiltservertools/ledger/mixin/blocks/DoorBlockMixin.java @@ -8,7 +8,6 @@ import net.minecraft.entity.player.PlayerEntity; import net.minecraft.state.property.BooleanProperty; import net.minecraft.util.ActionResult; -import net.minecraft.util.Hand; import net.minecraft.util.hit.BlockHitResult; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; @@ -27,7 +26,7 @@ public abstract class DoorBlockMixin { public static BooleanProperty OPEN; @Inject(method = "onUse", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/World;setBlockState(Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/block/BlockState;I)Z")) - public void logDoorInteraction(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit, CallbackInfoReturnable cir) { + public void logDoorInteraction(BlockState state, World world, BlockPos pos, PlayerEntity player, BlockHitResult hit, CallbackInfoReturnable cir) { BlockChangeCallback.EVENT.invoker().changeBlock(world, pos, state.cycle(OPEN), state, null, null, Sources.INTERACT, player); } diff --git a/src/main/java/com/github/quiltservertools/ledger/mixin/blocks/FenceGateBlockMixin.java b/src/main/java/com/github/quiltservertools/ledger/mixin/blocks/FenceGateBlockMixin.java index 8d995c7c..5fb7f3fd 100644 --- a/src/main/java/com/github/quiltservertools/ledger/mixin/blocks/FenceGateBlockMixin.java +++ b/src/main/java/com/github/quiltservertools/ledger/mixin/blocks/FenceGateBlockMixin.java @@ -8,7 +8,6 @@ import net.minecraft.entity.player.PlayerEntity; import net.minecraft.state.property.BooleanProperty; import net.minecraft.util.ActionResult; -import net.minecraft.util.Hand; import net.minecraft.util.hit.BlockHitResult; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; @@ -27,7 +26,7 @@ public abstract class FenceGateBlockMixin { public static BooleanProperty OPEN; @Inject(method = "onUse", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/World;setBlockState(Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/block/BlockState;I)Z")) - public void logFenceGateInteraction(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit, CallbackInfoReturnable cir) { + public void logFenceGateInteraction(BlockState state, World world, BlockPos pos, PlayerEntity player, BlockHitResult hit, CallbackInfoReturnable cir) { BlockChangeCallback.EVENT.invoker().changeBlock(world, pos, state.cycle(OPEN), state, null, null, Sources.INTERACT, player); } diff --git a/src/main/java/com/github/quiltservertools/ledger/mixin/blocks/FlowerPotBlockMixin.java b/src/main/java/com/github/quiltservertools/ledger/mixin/blocks/FlowerPotBlockMixin.java index 65c76c6f..d706b44b 100644 --- a/src/main/java/com/github/quiltservertools/ledger/mixin/blocks/FlowerPotBlockMixin.java +++ b/src/main/java/com/github/quiltservertools/ledger/mixin/blocks/FlowerPotBlockMixin.java @@ -4,7 +4,6 @@ import net.minecraft.block.BlockState; import net.minecraft.block.FlowerPotBlock; import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.util.Hand; import net.minecraft.util.hit.BlockHitResult; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; @@ -16,7 +15,7 @@ @Mixin(FlowerPotBlock.class) public abstract class FlowerPotBlockMixin { @ModifyArgs(method = "onUse", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/World;setBlockState(Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/block/BlockState;I)Z")) - public void logFlowerPotInteractions(Args args, BlockState oldState, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) { + public void logFlowerPotInteractions(Args args, BlockState oldState, World world, BlockPos pos, PlayerEntity player, BlockHitResult hit) { BlockState state = args.get(1); BlockChangeCallback.EVENT.invoker().changeBlock(world, pos, oldState, state, null, null, player); } diff --git a/src/main/java/com/github/quiltservertools/ledger/mixin/blocks/JukeBoxBlockMixin.java b/src/main/java/com/github/quiltservertools/ledger/mixin/blocks/JukeBoxBlockMixin.java index be915393..8902569c 100644 --- a/src/main/java/com/github/quiltservertools/ledger/mixin/blocks/JukeBoxBlockMixin.java +++ b/src/main/java/com/github/quiltservertools/ledger/mixin/blocks/JukeBoxBlockMixin.java @@ -7,7 +7,6 @@ import net.minecraft.entity.player.PlayerEntity; import net.minecraft.state.property.BooleanProperty; import net.minecraft.util.ActionResult; -import net.minecraft.util.Hand; import net.minecraft.util.hit.BlockHitResult; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; @@ -27,7 +26,7 @@ public abstract class JukeBoxBlockMixin { @Inject(method = "onUse", at = @At(value = "INVOKE", target = "Lnet/minecraft/block/entity/JukeboxBlockEntity;dropRecord()V")) - private void ledgerLogDiscRemoved(BlockState blockState, World world, BlockPos pos, PlayerEntity player, Hand hand, + private void ledgerLogDiscRemoved(BlockState blockState, World world, BlockPos pos, PlayerEntity player, BlockHitResult hit, CallbackInfoReturnable cir) { BlockChangeCallback.EVENT.invoker().changeBlock( world, diff --git a/src/main/java/com/github/quiltservertools/ledger/mixin/blocks/LeverBlockMixin.java b/src/main/java/com/github/quiltservertools/ledger/mixin/blocks/LeverBlockMixin.java index 7771772c..4f5b242a 100644 --- a/src/main/java/com/github/quiltservertools/ledger/mixin/blocks/LeverBlockMixin.java +++ b/src/main/java/com/github/quiltservertools/ledger/mixin/blocks/LeverBlockMixin.java @@ -5,7 +5,6 @@ import net.minecraft.block.LeverBlock; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.util.ActionResult; -import net.minecraft.util.Hand; import net.minecraft.util.hit.BlockHitResult; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; @@ -24,7 +23,7 @@ public abstract class LeverBlockMixin { private PlayerEntity activePlayer; @Inject(method = "onUse", at = @At(value = "INVOKE", target = "Lnet/minecraft/block/LeverBlock;togglePower(Lnet/minecraft/block/BlockState;Lnet/minecraft/world/World;Lnet/minecraft/util/math/BlockPos;)Lnet/minecraft/block/BlockState;")) - public void storePlayer(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit, CallbackInfoReturnable cir) { + public void storePlayer(BlockState state, World world, BlockPos pos, PlayerEntity player, BlockHitResult hit, CallbackInfoReturnable cir) { activePlayer = player; } diff --git a/src/main/java/com/github/quiltservertools/ledger/mixin/blocks/NoteBlockMixin.java b/src/main/java/com/github/quiltservertools/ledger/mixin/blocks/NoteBlockMixin.java index 3a86cadb..a88a80e3 100644 --- a/src/main/java/com/github/quiltservertools/ledger/mixin/blocks/NoteBlockMixin.java +++ b/src/main/java/com/github/quiltservertools/ledger/mixin/blocks/NoteBlockMixin.java @@ -4,7 +4,6 @@ import net.minecraft.block.BlockState; import net.minecraft.block.NoteBlock; import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.util.Hand; import net.minecraft.util.hit.BlockHitResult; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; @@ -16,7 +15,7 @@ @Mixin(NoteBlock.class) public abstract class NoteBlockMixin { @ModifyArgs(method = "onUse", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/World;setBlockState(Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/block/BlockState;I)Z")) - public void logNoteBlockChanges(Args args, BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) { + public void logNoteBlockChanges(Args args, BlockState state, World world, BlockPos pos, PlayerEntity player, BlockHitResult hit) { BlockState newState = args.get(1); BlockChangeCallback.EVENT.invoker().changeBlock(world, pos, state, newState, null, null, player); } diff --git a/src/main/java/com/github/quiltservertools/ledger/mixin/blocks/RepeaterBlockMixin.java b/src/main/java/com/github/quiltservertools/ledger/mixin/blocks/RepeaterBlockMixin.java index 04a02363..82fe04d4 100644 --- a/src/main/java/com/github/quiltservertools/ledger/mixin/blocks/RepeaterBlockMixin.java +++ b/src/main/java/com/github/quiltservertools/ledger/mixin/blocks/RepeaterBlockMixin.java @@ -7,7 +7,6 @@ import net.minecraft.entity.player.PlayerEntity; import net.minecraft.state.property.IntProperty; import net.minecraft.util.ActionResult; -import net.minecraft.util.Hand; import net.minecraft.util.hit.BlockHitResult; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; @@ -25,7 +24,7 @@ public abstract class RepeaterBlockMixin { public static IntProperty DELAY; @Inject(method = "onUse", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/World;setBlockState(Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/block/BlockState;I)Z")) - public void logRepeaterInteraction(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit, CallbackInfoReturnable cir) { + public void logRepeaterInteraction(BlockState state, World world, BlockPos pos, PlayerEntity player, BlockHitResult hit, CallbackInfoReturnable cir) { BlockChangeCallback.EVENT.invoker().changeBlock(world, pos, state, state.cycle(DELAY), null, null, Sources.INTERACT, player); } } diff --git a/src/main/java/com/github/quiltservertools/ledger/mixin/blocks/lectern/ScreenHandlerMixin.java b/src/main/java/com/github/quiltservertools/ledger/mixin/blocks/lectern/ScreenHandlerMixin.java index e778eee9..3ce4580b 100644 --- a/src/main/java/com/github/quiltservertools/ledger/mixin/blocks/lectern/ScreenHandlerMixin.java +++ b/src/main/java/com/github/quiltservertools/ledger/mixin/blocks/lectern/ScreenHandlerMixin.java @@ -11,7 +11,7 @@ @Mixin(ScreenHandler.class) public class ScreenHandlerMixin { - @Inject(method = "onClosed", at = @At(value = "INVOKE")) + @Inject(method = "onClosed", at = @At(value = "HEAD")) public void onClosed(PlayerEntity player, CallbackInfo ci) { if (player.currentScreenHandler instanceof LecternScreenHandler) { PlayerLecternHook.getActiveHandlers().remove(player); diff --git a/src/main/java/com/github/quiltservertools/ledger/mixin/blocks/sign/AbstractSignBlockMixin.java b/src/main/java/com/github/quiltservertools/ledger/mixin/blocks/sign/AbstractSignBlockMixin.java index c1a7ca6d..d18b6052 100644 --- a/src/main/java/com/github/quiltservertools/ledger/mixin/blocks/sign/AbstractSignBlockMixin.java +++ b/src/main/java/com/github/quiltservertools/ledger/mixin/blocks/sign/AbstractSignBlockMixin.java @@ -10,6 +10,7 @@ import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.Item; import net.minecraft.item.SignChangingItem; +import net.minecraft.registry.DynamicRegistryManager; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; import org.jetbrains.annotations.Nullable; @@ -36,7 +37,7 @@ public class AbstractSignBlockMixin { * @return Returns the result of calling {@code original} with this method's parameters. */ @WrapOperation( - method = "onUse", + method = "onUseWithItem", at = @At( value = "INVOKE", target = "Lnet/minecraft/item/SignChangingItem;useOnSign(Lnet/minecraft/world/World;Lnet/minecraft/block/entity/SignBlockEntity;ZLnet/minecraft/entity/player/PlayerEntity;)Z" @@ -53,9 +54,10 @@ private boolean logSignItemInteraction( BlockState state = signBlockEntity.getCachedState(); BlockPos pos = signBlockEntity.getPos(); + DynamicRegistryManager registryManager = world.getRegistryManager(); // a bad hack to copy the old sign block entity for rollbacks - @Nullable BlockEntity oldSignEntity = BlockEntity.createFromNbt(pos, state, signBlockEntity.createNbtWithId()); + @Nullable BlockEntity oldSignEntity = BlockEntity.createFromNbt(pos, state, signBlockEntity.createNbtWithId(registryManager), registryManager); boolean result = original.call(instance, world, signBlockEntity, front, player); if (result && oldSignEntity != null) { diff --git a/src/main/java/com/github/quiltservertools/ledger/mixin/blocks/sign/SignBlockEntityMixin.java b/src/main/java/com/github/quiltservertools/ledger/mixin/blocks/sign/SignBlockEntityMixin.java index f83bc4f6..fd577ae1 100644 --- a/src/main/java/com/github/quiltservertools/ledger/mixin/blocks/sign/SignBlockEntityMixin.java +++ b/src/main/java/com/github/quiltservertools/ledger/mixin/blocks/sign/SignBlockEntityMixin.java @@ -3,19 +3,21 @@ import com.github.quiltservertools.ledger.callbacks.BlockChangeCallback; import com.llamalad7.mixinextras.injector.wrapoperation.Operation; import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; -import java.util.UUID; -import java.util.function.UnaryOperator; import net.minecraft.block.BlockState; import net.minecraft.block.entity.BlockEntity; import net.minecraft.block.entity.SignBlockEntity; import net.minecraft.block.entity.SignText; import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.registry.DynamicRegistryManager; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; import org.jetbrains.annotations.Nullable; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; +import java.util.UUID; +import java.util.function.UnaryOperator; + @Mixin(SignBlockEntity.class) public abstract class SignBlockEntityMixin { @@ -46,16 +48,17 @@ private boolean logSignTextChange( Operation original ) { + World world = instance.getWorld(); + DynamicRegistryManager registryManager = world.getRegistryManager(); BlockPos pos = instance.getPos(); BlockState state = instance.getCachedState(); // a bad hack to copy the old sign block entity for rollbacks - @Nullable BlockEntity oldSignEntity = BlockEntity.createFromNbt(pos, state, instance.createNbtWithId()); + @Nullable BlockEntity oldSignEntity = BlockEntity.createFromNbt(pos, state, instance.createNbtWithId(registryManager), registryManager); boolean result = original.call(instance, textChanger, front); if (result && oldSignEntity != null) { - World world = instance.getWorld(); assert world != null : "World cannot be null, this is already in the target method"; UUID editorID = instance.getEditor(); diff --git a/src/main/kotlin/com/github/quiltservertools/ledger/Ledger.kt b/src/main/kotlin/com/github/quiltservertools/ledger/Ledger.kt index acd8ab2a..a7be1d12 100644 --- a/src/main/kotlin/com/github/quiltservertools/ledger/Ledger.kt +++ b/src/main/kotlin/com/github/quiltservertools/ledger/Ledger.kt @@ -1,6 +1,5 @@ package com.github.quiltservertools.ledger -import com.github.quiltservertools.ledger.config.config as realConfig import com.github.quiltservertools.ledger.actionutils.ActionSearchParams import com.github.quiltservertools.ledger.actionutils.Preview import com.github.quiltservertools.ledger.api.ExtensionManager @@ -16,6 +15,9 @@ import com.github.quiltservertools.ledger.listeners.registerEntityListeners import com.github.quiltservertools.ledger.listeners.registerPlayerListeners import com.github.quiltservertools.ledger.listeners.registerWorldEventListeners import com.github.quiltservertools.ledger.network.Networking +import com.github.quiltservertools.ledger.network.packet.action.ActionS2CPacket +import com.github.quiltservertools.ledger.network.packet.handshake.HandshakeS2CPacket +import com.github.quiltservertools.ledger.network.packet.response.ResponseS2CPacket import com.github.quiltservertools.ledger.registry.ActionRegistry import com.uchuhimo.konf.Config import kotlinx.coroutines.CoroutineScope @@ -28,6 +30,7 @@ import kotlinx.coroutines.withTimeout import net.fabricmc.api.DedicatedServerModInitializer import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents +import net.fabricmc.fabric.api.networking.v1.PayloadTypeRegistry import net.fabricmc.loader.api.FabricLoader import net.minecraft.registry.Registries import net.minecraft.server.MinecraftServer @@ -54,6 +57,7 @@ object Ledger : DedicatedServerModInitializer, CoroutineScope { lateinit var config: Config lateinit var server: MinecraftServer val searchCache = ConcurrentHashMap() + @JvmField // Required for mixin access val previewCache = ConcurrentHashMap() @@ -76,6 +80,9 @@ object Ledger : DedicatedServerModInitializer, CoroutineScope { ServerLifecycleEvents.SERVER_STARTING.register(::serverStarting) ServerLifecycleEvents.SERVER_STOPPED.register(::serverStopped) CommandRegistrationCallback.EVENT.register { dispatcher, _, _ -> registerCommands(dispatcher) } + PayloadTypeRegistry.playS2C().register(ActionS2CPacket.ID, ActionS2CPacket.CODEC) + PayloadTypeRegistry.playS2C().register(HandshakeS2CPacket.ID, HandshakeS2CPacket.CODEC) + PayloadTypeRegistry.playS2C().register(ResponseS2CPacket.ID, ResponseS2CPacket.CODEC) } private fun serverStarting(server: MinecraftServer) { @@ -112,7 +119,8 @@ object Ledger : DedicatedServerModInitializer, CoroutineScope { Ledger.launch(Dispatchers.Default) { while (ActionQueueService.size > 0) { logInfo( - "Database is still busy. If you exit now data WILL be lost. Actions in queue: ${ActionQueueService.size}" + "Database is still busy. If you exit now data WILL be lost. " + + "Actions in queue: ${ActionQueueService.size}" ) delay(config[DatabaseSpec.queueCheckDelaySec].seconds) @@ -122,7 +130,9 @@ object Ledger : DedicatedServerModInitializer, CoroutineScope { logInfo("Successfully drained database queue") } } catch (e: TimeoutCancellationException) { - logWarn("Database drain timed out. ${ActionQueueService.size} actions still in queue. Data may be lost.") + logWarn( + "Database drain timed out. ${ActionQueueService.size} actions still in queue. Data may be lost." + ) } } } diff --git a/src/main/kotlin/com/github/quiltservertools/ledger/actions/AbstractActionType.kt b/src/main/kotlin/com/github/quiltservertools/ledger/actions/AbstractActionType.kt index 7112a204..eda4002a 100644 --- a/src/main/kotlin/com/github/quiltservertools/ledger/actions/AbstractActionType.kt +++ b/src/main/kotlin/com/github/quiltservertools/ledger/actions/AbstractActionType.kt @@ -6,8 +6,8 @@ import com.github.quiltservertools.ledger.utility.Sources import com.github.quiltservertools.ledger.utility.TextColorPallet import com.github.quiltservertools.ledger.utility.literal import com.mojang.authlib.GameProfile -import java.time.Instant import net.minecraft.server.MinecraftServer +import net.minecraft.server.command.ServerCommandSource import net.minecraft.server.network.ServerPlayerEntity import net.minecraft.text.ClickEvent import net.minecraft.text.HoverEvent @@ -17,6 +17,7 @@ import net.minecraft.util.Identifier import net.minecraft.util.Util import net.minecraft.util.math.BlockPos import net.minecraft.world.World +import java.time.Instant import kotlin.time.ExperimentalTime abstract class AbstractActionType : ActionType { @@ -38,13 +39,13 @@ abstract class AbstractActionType : ActionType { override fun restore(server: MinecraftServer): Boolean = false @ExperimentalTime - override fun getMessage(): Text { + override fun getMessage(source: ServerCommandSource): Text { val message = Text.translatable( "text.ledger.action_message", getTimeMessage(), getSourceMessage(), getActionMessage(), - getObjectMessage(), + getObjectMessage(source), getLocationMessage() ) message.style = TextColorPallet.light @@ -81,7 +82,7 @@ abstract class AbstractActionType : ActionType { ) } - open fun getObjectMessage(): Text = Text.translatable( + open fun getObjectMessage(source: ServerCommandSource): Text = Text.translatable( Util.createTranslationKey( this.getTranslationType(), objectIdentifier diff --git a/src/main/kotlin/com/github/quiltservertools/ledger/actions/ActionType.kt b/src/main/kotlin/com/github/quiltservertools/ledger/actions/ActionType.kt index 2445645c..b2720a6d 100644 --- a/src/main/kotlin/com/github/quiltservertools/ledger/actions/ActionType.kt +++ b/src/main/kotlin/com/github/quiltservertools/ledger/actions/ActionType.kt @@ -4,12 +4,13 @@ import com.github.quiltservertools.ledger.actionutils.Preview import com.github.quiltservertools.ledger.config.ActionsSpec import com.github.quiltservertools.ledger.config.config import com.mojang.authlib.GameProfile -import java.time.Instant import net.minecraft.server.MinecraftServer +import net.minecraft.server.command.ServerCommandSource import net.minecraft.server.network.ServerPlayerEntity import net.minecraft.text.Text import net.minecraft.util.Identifier import net.minecraft.util.math.BlockPos +import java.time.Instant import kotlin.time.ExperimentalTime interface ActionType { @@ -33,7 +34,7 @@ interface ActionType { fun getTranslationType(): String @ExperimentalTime - fun getMessage(): Text + fun getMessage(source: ServerCommandSource): Text fun isBlacklisted() = config[ActionsSpec.typeBlacklist].contains(identifier) || config[ActionsSpec.objectBlacklist].contains(objectIdentifier) || diff --git a/src/main/kotlin/com/github/quiltservertools/ledger/actions/BlockBreakActionType.kt b/src/main/kotlin/com/github/quiltservertools/ledger/actions/BlockBreakActionType.kt index 4ee9e30a..e6a7052c 100644 --- a/src/main/kotlin/com/github/quiltservertools/ledger/actions/BlockBreakActionType.kt +++ b/src/main/kotlin/com/github/quiltservertools/ledger/actions/BlockBreakActionType.kt @@ -2,6 +2,7 @@ package com.github.quiltservertools.ledger.actions import com.github.quiltservertools.ledger.utility.TextColorPallet import com.github.quiltservertools.ledger.utility.literal +import net.minecraft.server.command.ServerCommandSource import net.minecraft.text.HoverEvent import net.minecraft.text.Text import net.minecraft.util.Util @@ -9,7 +10,7 @@ import net.minecraft.util.Util class BlockBreakActionType : BlockChangeActionType() { override val identifier = "block-break" - override fun getObjectMessage(): Text = Text.translatable( + override fun getObjectMessage(source: ServerCommandSource): Text = Text.translatable( Util.createTranslationKey( this.getTranslationType(), oldObjectIdentifier diff --git a/src/main/kotlin/com/github/quiltservertools/ledger/actions/BlockChangeActionType.kt b/src/main/kotlin/com/github/quiltservertools/ledger/actions/BlockChangeActionType.kt index c50a6459..33f44578 100644 --- a/src/main/kotlin/com/github/quiltservertools/ledger/actions/BlockChangeActionType.kt +++ b/src/main/kotlin/com/github/quiltservertools/ledger/actions/BlockChangeActionType.kt @@ -12,6 +12,7 @@ import net.minecraft.nbt.StringNbtReader import net.minecraft.network.packet.s2c.play.BlockUpdateS2CPacket import net.minecraft.registry.Registries import net.minecraft.server.MinecraftServer +import net.minecraft.server.command.ServerCommandSource import net.minecraft.server.network.ServerPlayerEntity import net.minecraft.text.HoverEvent import net.minecraft.text.Text @@ -24,8 +25,7 @@ open class BlockChangeActionType : AbstractActionType() { override fun rollback(server: MinecraftServer): Boolean { val world = server.getWorld(world) world?.setBlockState(pos, oldBlockState()) - - world?.getBlockEntity(pos)?.readNbt(StringNbtReader.parse(extraData)) + world?.getBlockEntity(pos)?.read(StringNbtReader.parse(extraData), server.registryManager) world?.chunkManager?.markForUpdate(pos) return true @@ -55,7 +55,7 @@ open class BlockChangeActionType : AbstractActionType() { override fun getTranslationType() = "block" - override fun getObjectMessage(): Text { + override fun getObjectMessage(source: ServerCommandSource): Text { val text = Text.literal("") text.append( Text.translatable( @@ -70,7 +70,8 @@ open class BlockChangeActionType : AbstractActionType() { oldObjectIdentifier.toString().literal() ) ) - }) + } + ) if (oldObjectIdentifier != objectIdentifier) { text.append(" → ".literal()) text.append( @@ -86,24 +87,31 @@ open class BlockChangeActionType : AbstractActionType() { objectIdentifier.toString().literal() ) ) - }) + } + ) } return text } - fun oldBlockState() = checkForBlockState(oldObjectIdentifier, oldObjectState?.let { + fun oldBlockState() = checkForBlockState( + oldObjectIdentifier, + oldObjectState?.let { NbtUtils.blockStateFromProperties( StringNbtReader.parse(it), oldObjectIdentifier ) - }) + } + ) - fun newBlockState() = checkForBlockState(objectIdentifier, objectState?.let { + fun newBlockState() = checkForBlockState( + objectIdentifier, + objectState?.let { NbtUtils.blockStateFromProperties( StringNbtReader.parse(it), objectIdentifier ) - }) + } + ) private fun checkForBlockState(identifier: Identifier, checkState: BlockState?): BlockState { val block = Registries.BLOCK.getOrEmpty(identifier) diff --git a/src/main/kotlin/com/github/quiltservertools/ledger/actions/BlockPlaceActionType.kt b/src/main/kotlin/com/github/quiltservertools/ledger/actions/BlockPlaceActionType.kt index ca85bed5..c6c0c9d1 100644 --- a/src/main/kotlin/com/github/quiltservertools/ledger/actions/BlockPlaceActionType.kt +++ b/src/main/kotlin/com/github/quiltservertools/ledger/actions/BlockPlaceActionType.kt @@ -5,6 +5,7 @@ import com.github.quiltservertools.ledger.utility.getWorld import com.github.quiltservertools.ledger.utility.literal import net.minecraft.nbt.StringNbtReader import net.minecraft.server.MinecraftServer +import net.minecraft.server.command.ServerCommandSource import net.minecraft.text.HoverEvent import net.minecraft.text.Text import net.minecraft.util.Util @@ -25,13 +26,13 @@ class BlockPlaceActionType : BlockChangeActionType() { val state = newBlockState() world?.setBlockState(pos, state) if (state.hasBlockEntity()) { - world?.getBlockEntity(pos)?.readNbt(StringNbtReader.parse(extraData)) + world?.getBlockEntity(pos)?.read(StringNbtReader.parse(extraData), server.registryManager) } return true } - override fun getObjectMessage(): Text = Text.translatable( + override fun getObjectMessage(source: ServerCommandSource): Text = Text.translatable( Util.createTranslationKey( this.getTranslationType(), objectIdentifier diff --git a/src/main/kotlin/com/github/quiltservertools/ledger/actions/EntityChangeActionType.kt b/src/main/kotlin/com/github/quiltservertools/ledger/actions/EntityChangeActionType.kt index b404fcf6..5deb2083 100644 --- a/src/main/kotlin/com/github/quiltservertools/ledger/actions/EntityChangeActionType.kt +++ b/src/main/kotlin/com/github/quiltservertools/ledger/actions/EntityChangeActionType.kt @@ -1,6 +1,5 @@ package com.github.quiltservertools.ledger.actions -import com.github.quiltservertools.ledger.utility.NbtUtils import com.github.quiltservertools.ledger.utility.TextColorPallet import com.github.quiltservertools.ledger.utility.UUID import com.github.quiltservertools.ledger.utility.getWorld @@ -14,6 +13,7 @@ import net.minecraft.item.ItemStack import net.minecraft.nbt.StringNbtReader import net.minecraft.registry.Registries import net.minecraft.server.MinecraftServer +import net.minecraft.server.command.ServerCommandSource import net.minecraft.text.HoverEvent import net.minecraft.text.Text import net.minecraft.util.Identifier @@ -31,7 +31,7 @@ class EntityChangeActionType : AbstractActionType() { } } - override fun getObjectMessage(): Text { + override fun getObjectMessage(source: ServerCommandSource): Text { val text = Text.literal("") text.append( Text.translatable( @@ -46,10 +46,11 @@ class EntityChangeActionType : AbstractActionType() { objectIdentifier.toString().literal() ) ) - }) + } + ) if (extraData != null && Identifier(extraData) != Identifier.tryParse("minecraft:air")) { - val stack = NbtUtils.itemFromProperties(null, Identifier(extraData)) + val stack = ItemStack(Registries.ITEM.get(Identifier(extraData))) text.append(Text.literal(" ").append(Text.translatable("text.ledger.action_message.with")).append(" ")) text.append( Text.translatable( @@ -64,7 +65,8 @@ class EntityChangeActionType : AbstractActionType() { HoverEvent.ItemStackContent(stack) ) ) - }) + } + ) } return text } @@ -89,7 +91,6 @@ class EntityChangeActionType : AbstractActionType() { return false } - override fun restore(server: MinecraftServer): Boolean { val world = server.getWorld(world) val newEntity = StringNbtReader.parse(objectState) diff --git a/src/main/kotlin/com/github/quiltservertools/ledger/actions/EntityKillActionType.kt b/src/main/kotlin/com/github/quiltservertools/ledger/actions/EntityKillActionType.kt index 8ad25059..a0924f88 100644 --- a/src/main/kotlin/com/github/quiltservertools/ledger/actions/EntityKillActionType.kt +++ b/src/main/kotlin/com/github/quiltservertools/ledger/actions/EntityKillActionType.kt @@ -57,7 +57,7 @@ class EntityKillActionType : AbstractActionType() { entity.readNbt(StringNbtReader.parse(extraData)) entity.velocity = Vec3d.ZERO entity.fireTicks = 0 - if (entity is LivingEntity) { entity.health = entity.defaultMaxHealth.toFloat() } + if (entity is LivingEntity) entity.health = entity.defaultMaxHealth.toFloat() world?.spawnEntity(entity) diff --git a/src/main/kotlin/com/github/quiltservertools/ledger/actions/ItemChangeActionType.kt b/src/main/kotlin/com/github/quiltservertools/ledger/actions/ItemChangeActionType.kt index 66a6789d..ca379df7 100644 --- a/src/main/kotlin/com/github/quiltservertools/ledger/actions/ItemChangeActionType.kt +++ b/src/main/kotlin/com/github/quiltservertools/ledger/actions/ItemChangeActionType.kt @@ -19,6 +19,7 @@ import net.minecraft.item.ItemStack import net.minecraft.item.Items import net.minecraft.registry.Registries import net.minecraft.server.MinecraftServer +import net.minecraft.server.command.ServerCommandSource import net.minecraft.server.network.ServerPlayerEntity import net.minecraft.server.world.ServerWorld import net.minecraft.text.HoverEvent @@ -36,8 +37,14 @@ abstract class ItemChangeActionType : AbstractActionType() { } } - override fun getObjectMessage(): Text { - val stack = NbtUtils.itemFromProperties(extraData, objectIdentifier) + private fun getStack(server: MinecraftServer) = NbtUtils.itemFromProperties( + extraData, + objectIdentifier, + server.registryManager + ) + + override fun getObjectMessage(source: ServerCommandSource): Text { + val stack = getStack(source.server) return "${stack.count} ".literal().append( Text.translatable( @@ -63,17 +70,17 @@ abstract class ItemChangeActionType : AbstractActionType() { if (it) { val otherPos = getOtherChestSide(state, pos) if (otherPos != null) { - addPreview(preview, otherPos, insert) + addPreview(preview, player, otherPos, insert) } } } - addPreview(preview, pos, insert) + addPreview(preview, player, pos, insert) } - private fun addPreview(preview: Preview, pos: BlockPos, insert: Boolean) { + private fun addPreview(preview: Preview, player: ServerPlayerEntity, pos: BlockPos, insert: Boolean) { preview.modifiedItems.compute(pos) { _, list -> list ?: mutableListOf() - }?.add(Pair(NbtUtils.itemFromProperties(extraData, objectIdentifier), insert)) + }?.add(Pair(getStack(player.server), insert)) } private fun getInventory(world: ServerWorld): Inventory? { @@ -100,7 +107,7 @@ abstract class ItemChangeActionType : AbstractActionType() { val inventory = world?.let { getInventory(it) } if (world != null) { - val rollbackStack = NbtUtils.itemFromProperties(extraData, objectIdentifier) + val rollbackStack = getStack(server) if (inventory != null) { for (i in 0 until inventory.size()) { @@ -128,7 +135,7 @@ abstract class ItemChangeActionType : AbstractActionType() { val inventory = world?.let { getInventory(it) } if (world != null) { - val rollbackStack = NbtUtils.itemFromProperties(extraData, objectIdentifier) + val rollbackStack = getStack(server) if (inventory != null) { for (i in 0 until inventory.size()) { diff --git a/src/main/kotlin/com/github/quiltservertools/ledger/actions/ItemDropActionType.kt b/src/main/kotlin/com/github/quiltservertools/ledger/actions/ItemDropActionType.kt index 6af0b5e9..4c1882df 100644 --- a/src/main/kotlin/com/github/quiltservertools/ledger/actions/ItemDropActionType.kt +++ b/src/main/kotlin/com/github/quiltservertools/ledger/actions/ItemDropActionType.kt @@ -13,6 +13,7 @@ import net.minecraft.item.BlockItem import net.minecraft.nbt.StringNbtReader import net.minecraft.registry.Registries import net.minecraft.server.MinecraftServer +import net.minecraft.server.command.ServerCommandSource import net.minecraft.text.HoverEvent import net.minecraft.text.Text import net.minecraft.util.Util @@ -29,19 +30,27 @@ open class ItemDropActionType : AbstractActionType() { } } - override fun getObjectMessage(): Text { - val stack = NbtUtils.itemFromProperties(extraData, objectIdentifier) + private fun getStack(server: MinecraftServer) = NbtUtils.itemFromProperties( + extraData, + objectIdentifier, + server.registryManager + ) + + override fun getObjectMessage(source: ServerCommandSource): Text { + val stack = getStack(source.server) return "${stack.count} ".literal().append( Text.translatable( Util.createTranslationKey( - getTranslationType(), objectIdentifier + getTranslationType(), + objectIdentifier ) ) ).setStyle(TextColorPallet.secondaryVariant).styled { it.withHoverEvent( HoverEvent( - HoverEvent.Action.SHOW_ITEM, HoverEvent.ItemStackContent(stack) + HoverEvent.Action.SHOW_ITEM, + HoverEvent.ItemStackContent(stack) ) ) } diff --git a/src/main/kotlin/com/github/quiltservertools/ledger/actions/ItemPickUpActionType.kt b/src/main/kotlin/com/github/quiltservertools/ledger/actions/ItemPickUpActionType.kt index 29d6c811..69ddd238 100644 --- a/src/main/kotlin/com/github/quiltservertools/ledger/actions/ItemPickUpActionType.kt +++ b/src/main/kotlin/com/github/quiltservertools/ledger/actions/ItemPickUpActionType.kt @@ -13,6 +13,7 @@ import net.minecraft.item.BlockItem import net.minecraft.nbt.StringNbtReader import net.minecraft.registry.Registries import net.minecraft.server.MinecraftServer +import net.minecraft.server.command.ServerCommandSource import net.minecraft.text.HoverEvent import net.minecraft.text.Text import net.minecraft.util.Util @@ -29,19 +30,27 @@ open class ItemPickUpActionType : AbstractActionType() { } } - override fun getObjectMessage(): Text { - val stack = NbtUtils.itemFromProperties(extraData, objectIdentifier) + private fun getStack(server: MinecraftServer) = NbtUtils.itemFromProperties( + extraData, + objectIdentifier, + server.registryManager + ) + + override fun getObjectMessage(source: ServerCommandSource): Text { + val stack = getStack(source.server) return "${stack.count} ".literal().append( Text.translatable( Util.createTranslationKey( - getTranslationType(), objectIdentifier + getTranslationType(), + objectIdentifier ) ) ).setStyle(TextColorPallet.secondaryVariant).styled { it.withHoverEvent( HoverEvent( - HoverEvent.Action.SHOW_ITEM, HoverEvent.ItemStackContent(stack) + HoverEvent.Action.SHOW_ITEM, + HoverEvent.ItemStackContent(stack) ) ) } diff --git a/src/main/kotlin/com/github/quiltservertools/ledger/actionutils/ActionFactory.kt b/src/main/kotlin/com/github/quiltservertools/ledger/actionutils/ActionFactory.kt index 9b8f160d..212b8fbe 100644 --- a/src/main/kotlin/com/github/quiltservertools/ledger/actionutils/ActionFactory.kt +++ b/src/main/kotlin/com/github/quiltservertools/ledger/actionutils/ActionFactory.kt @@ -96,7 +96,7 @@ object ActionFactory { action.objectState = NbtUtils.blockStateToProperties(state)?.asString() action.oldObjectState = NbtUtils.blockStateToProperties(oldState)?.asString() action.sourceName = source - action.extraData = entity?.createNbt()?.asString() + action.extraData = entity?.createNbt(world.registryManager)?.asString() } fun itemInsertAction(world: World, stack: ItemStack, pos: BlockPos, source: String): ItemInsertActionType { @@ -193,7 +193,7 @@ object ActionFactory { action.world = world.registryKey.value action.objectIdentifier = Registries.ITEM.getId(stack.item) action.sourceName = source - action.extraData = NbtUtils.itemToProperties(stack)?.asString() + action.extraData = stack.encode(world.registryManager)?.asString() } fun entityKillAction(world: World, pos: BlockPos, entity: Entity, cause: DamageSource): EntityKillActionType { @@ -209,7 +209,9 @@ object ActionFactory { val source = Registries.ENTITY_TYPE.getId(killer.type).path setEntityData(action, pos, world, entity, source) } - else -> setEntityData(action, pos, world, entity, cause.name) + else -> { + setEntityData(action, pos, world, entity, cause.name) + } } return action diff --git a/src/main/kotlin/com/github/quiltservertools/ledger/actionutils/ActionSearchParams.kt b/src/main/kotlin/com/github/quiltservertools/ledger/actionutils/ActionSearchParams.kt index 26c95e1f..7495ebfa 100644 --- a/src/main/kotlin/com/github/quiltservertools/ledger/actionutils/ActionSearchParams.kt +++ b/src/main/kotlin/com/github/quiltservertools/ledger/actionutils/ActionSearchParams.kt @@ -29,7 +29,17 @@ data class ActionSearchParams( builder.worlds ) - fun isEmpty() = listOf(bounds, before, after, actions, objects, sourceNames, sourcePlayerIds, worlds, rolledBack).all { it == null } + fun isEmpty() = listOf( + bounds, + before, + after, + actions, + objects, + sourceNames, + sourcePlayerIds, + worlds, + rolledBack + ).all { it == null } companion object { inline fun build(block: Builder.() -> Unit) = Builder().apply(block).build() diff --git a/src/main/kotlin/com/github/quiltservertools/ledger/actionutils/Preview.kt b/src/main/kotlin/com/github/quiltservertools/ledger/actionutils/Preview.kt index f60cfa55..8e8c36bd 100644 --- a/src/main/kotlin/com/github/quiltservertools/ledger/actionutils/Preview.kt +++ b/src/main/kotlin/com/github/quiltservertools/ledger/actionutils/Preview.kt @@ -30,7 +30,6 @@ class Preview( // Preview items that should be modified in screen handlers (true = added, false = removed) val modifiedItems = mutableMapOf>>() - init { player.sendMessage( Text.translatable( diff --git a/src/main/kotlin/com/github/quiltservertools/ledger/callbacks/BlockChangeCallback.kt b/src/main/kotlin/com/github/quiltservertools/ledger/callbacks/BlockChangeCallback.kt index a7fa85ee..ec6f815c 100644 --- a/src/main/kotlin/com/github/quiltservertools/ledger/callbacks/BlockChangeCallback.kt +++ b/src/main/kotlin/com/github/quiltservertools/ledger/callbacks/BlockChangeCallback.kt @@ -21,10 +21,26 @@ fun interface BlockChangeCallback { player: PlayerEntity? ) - fun changeBlock(world: World, pos: BlockPos, oldState: BlockState, newState: BlockState, oldBlockEntity: BlockEntity?, newBlockEntity: BlockEntity?, player: PlayerEntity) = + fun changeBlock( + world: World, + pos: BlockPos, + oldState: BlockState, + newState: BlockState, + oldBlockEntity: BlockEntity?, + newBlockEntity: BlockEntity?, + player: PlayerEntity + ) = changeBlock(world, pos, oldState, newState, oldBlockEntity, newBlockEntity, Sources.PLAYER, player) - fun changeBlock(world: World, pos: BlockPos, oldState: BlockState, newState: BlockState, oldBlockEntity: BlockEntity?, newBlockEntity: BlockEntity?, source: String) = + fun changeBlock( + world: World, + pos: BlockPos, + oldState: BlockState, + newState: BlockState, + oldBlockEntity: BlockEntity?, + newBlockEntity: BlockEntity?, + source: String + ) = changeBlock(world, pos, oldState, newState, oldBlockEntity, newBlockEntity, source, null) companion object { @@ -33,7 +49,16 @@ fun interface BlockChangeCallback { EventFactory.createArrayBacked(BlockChangeCallback::class.java) { listeners -> BlockChangeCallback { world, pos, oldState, newState, oldBlockEntity, newBlockEntity, source, player -> for (listener in listeners) { - listener.changeBlock(world, pos, oldState, newState, oldBlockEntity, newBlockEntity, source, player) + listener.changeBlock( + world, + pos, + oldState, + newState, + oldBlockEntity, + newBlockEntity, + source, + player + ) } } } diff --git a/src/main/kotlin/com/github/quiltservertools/ledger/commands/parameters/ObjectParameter.kt b/src/main/kotlin/com/github/quiltservertools/ledger/commands/parameters/ObjectParameter.kt index 66d203cc..a7772a33 100644 --- a/src/main/kotlin/com/github/quiltservertools/ledger/commands/parameters/ObjectParameter.kt +++ b/src/main/kotlin/com/github/quiltservertools/ledger/commands/parameters/ObjectParameter.kt @@ -27,13 +27,21 @@ class ObjectParameter : SimpleParameter>() { val tagId = IdentifierArgumentType.identifier().parse(stringReader) val blockTag = TagKey.of(RegistryKeys.BLOCK, tagId) - if (blockTag != null) return Registries.BLOCK.iterateEntries(blockTag).map { Registries.BLOCK.getId(it.value()) } + if (blockTag != null) { + return Registries.BLOCK.iterateEntries( + blockTag + ).map { Registries.BLOCK.getId(it.value()) } + } val itemTag = TagKey.of(RegistryKeys.ITEM, tagId) if (itemTag != null) Registries.ITEM.iterateEntries(itemTag).map { Registries.ITEM.getId(it.value()) } val entityTag = TagKey.of(RegistryKeys.ENTITY_TYPE, tagId) - if (entityTag != null) return Registries.ENTITY_TYPE.iterateEntries(entityTag).map { Registries.ENTITY_TYPE.getId(it.value()) } + if (entityTag != null) { + return Registries.ENTITY_TYPE.iterateEntries(entityTag).map { + Registries.ENTITY_TYPE.getId(it.value()) + } + } } return listOf(IdentifierArgumentType.identifier().parse(stringReader)) diff --git a/src/main/kotlin/com/github/quiltservertools/ledger/commands/subcommands/PlayerCommand.kt b/src/main/kotlin/com/github/quiltservertools/ledger/commands/subcommands/PlayerCommand.kt index c6b662a9..260580c5 100644 --- a/src/main/kotlin/com/github/quiltservertools/ledger/commands/subcommands/PlayerCommand.kt +++ b/src/main/kotlin/com/github/quiltservertools/ledger/commands/subcommands/PlayerCommand.kt @@ -18,15 +18,16 @@ object PlayerCommand : BuildableCommand { override fun build(): LiteralNode { return literal("player") .requires(Permissions.require("ledger.commands.player", CommandConsts.PERMISSION_LEVEL)) - .then(argument("player", GameProfileArgumentType.gameProfile()) + .then( + argument("player", GameProfileArgumentType.gameProfile()) .executes { return@executes lookupPlayer(GameProfileArgumentType.getProfileArgument(it, "player"), it.source) - }) + } + ) .build() } private fun lookupPlayer(profiles: MutableCollection, source: ServerCommandSource): Int { - Ledger.launch { val players = DatabaseManager.searchPlayers(profiles.toSet()) MessageUtils.sendPlayerMessage(source, players) diff --git a/src/main/kotlin/com/github/quiltservertools/ledger/commands/subcommands/PreviewCommand.kt b/src/main/kotlin/com/github/quiltservertools/ledger/commands/subcommands/PreviewCommand.kt index 180700c5..9e85b622 100644 --- a/src/main/kotlin/com/github/quiltservertools/ledger/commands/subcommands/PreviewCommand.kt +++ b/src/main/kotlin/com/github/quiltservertools/ledger/commands/subcommands/PreviewCommand.kt @@ -20,7 +20,8 @@ object PreviewCommand : BuildableCommand { override fun build(): LiteralNode { return CommandManager.literal("preview") .requires(Permissions.require("ledger.commands.preview", CommandConsts.PERMISSION_LEVEL)) - .then(CommandManager.literal("rollback") + .then( + CommandManager.literal("rollback") .then( SearchParamArgument.argument(CommandConsts.PARAMS) .executes { @@ -32,7 +33,8 @@ object PreviewCommand : BuildableCommand { } ) ) - .then(CommandManager.literal("restore") + .then( + CommandManager.literal("restore") .then( SearchParamArgument.argument(CommandConsts.PARAMS) .executes { diff --git a/src/main/kotlin/com/github/quiltservertools/ledger/commands/subcommands/PurgeCommand.kt b/src/main/kotlin/com/github/quiltservertools/ledger/commands/subcommands/PurgeCommand.kt index 576d5c75..5e205f1d 100644 --- a/src/main/kotlin/com/github/quiltservertools/ledger/commands/subcommands/PurgeCommand.kt +++ b/src/main/kotlin/com/github/quiltservertools/ledger/commands/subcommands/PurgeCommand.kt @@ -20,9 +20,11 @@ object PurgeCommand : BuildableCommand { override fun build(): LiteralNode { return literal("purge") .requires(Permissions.require("ledger.commands.purge", config[SearchSpec.purgePermissionLevel])) - .then(SearchParamArgument.argument(CommandConsts.PARAMS).executes { + .then( + SearchParamArgument.argument(CommandConsts.PARAMS).executes { runPurge(it, SearchParamArgument.get(it, CommandConsts.PARAMS)) - }) + } + ) .build() } diff --git a/src/main/kotlin/com/github/quiltservertools/ledger/commands/subcommands/SearchCommand.kt b/src/main/kotlin/com/github/quiltservertools/ledger/commands/subcommands/SearchCommand.kt index 8ff8b744..a3ecda8c 100644 --- a/src/main/kotlin/com/github/quiltservertools/ledger/commands/subcommands/SearchCommand.kt +++ b/src/main/kotlin/com/github/quiltservertools/ledger/commands/subcommands/SearchCommand.kt @@ -1,8 +1,5 @@ package com.github.quiltservertools.ledger.commands.subcommands -import kotlinx.coroutines.launch -import me.lucko.fabric.api.permissions.v0.Permissions -import net.minecraft.server.command.CommandManager.literal import com.github.quiltservertools.ledger.Ledger import com.github.quiltservertools.ledger.actionutils.ActionSearchParams import com.github.quiltservertools.ledger.commands.BuildableCommand @@ -13,6 +10,9 @@ import com.github.quiltservertools.ledger.utility.Context import com.github.quiltservertools.ledger.utility.LiteralNode import com.github.quiltservertools.ledger.utility.MessageUtils import com.github.quiltservertools.ledger.utility.TextColorPallet +import kotlinx.coroutines.launch +import me.lucko.fabric.api.permissions.v0.Permissions +import net.minecraft.server.command.CommandManager.literal import net.minecraft.text.Text object SearchCommand : BuildableCommand { diff --git a/src/main/kotlin/com/github/quiltservertools/ledger/commands/subcommands/StatusCommand.kt b/src/main/kotlin/com/github/quiltservertools/ledger/commands/subcommands/StatusCommand.kt index e734471d..b3e9fad6 100644 --- a/src/main/kotlin/com/github/quiltservertools/ledger/commands/subcommands/StatusCommand.kt +++ b/src/main/kotlin/com/github/quiltservertools/ledger/commands/subcommands/StatusCommand.kt @@ -80,7 +80,8 @@ object StatusCommand : BuildableCommand { ) } ).setStyle(TextColorPallet.secondary) - }, false + }, + false ) source.sendFeedback( { @@ -97,7 +98,8 @@ object StatusCommand : BuildableCommand { ) } ).setStyle(TextColorPallet.secondary) - }, false + }, + false ) } diff --git a/src/main/kotlin/com/github/quiltservertools/ledger/commands/subcommands/TeleportCommand.kt b/src/main/kotlin/com/github/quiltservertools/ledger/commands/subcommands/TeleportCommand.kt index ef3b2b26..4fc652b9 100644 --- a/src/main/kotlin/com/github/quiltservertools/ledger/commands/subcommands/TeleportCommand.kt +++ b/src/main/kotlin/com/github/quiltservertools/ledger/commands/subcommands/TeleportCommand.kt @@ -1,15 +1,15 @@ package com.github.quiltservertools.ledger.commands.subcommands +import com.github.quiltservertools.ledger.commands.BuildableCommand +import com.github.quiltservertools.ledger.commands.CommandConsts +import com.github.quiltservertools.ledger.utility.Context +import com.github.quiltservertools.ledger.utility.LiteralNode import me.lucko.fabric.api.permissions.v0.Permissions import net.minecraft.command.argument.DimensionArgumentType import net.minecraft.command.argument.PosArgument import net.minecraft.command.argument.Vec3ArgumentType import net.minecraft.server.command.CommandManager import net.minecraft.server.world.ServerWorld -import com.github.quiltservertools.ledger.commands.BuildableCommand -import com.github.quiltservertools.ledger.commands.CommandConsts -import com.github.quiltservertools.ledger.utility.Context -import com.github.quiltservertools.ledger.utility.LiteralNode object TeleportCommand : BuildableCommand { override fun build(): LiteralNode = diff --git a/src/main/kotlin/com/github/quiltservertools/ledger/database/DatabaseManager.kt b/src/main/kotlin/com/github/quiltservertools/ledger/database/DatabaseManager.kt index 13cf4c7d..106abca7 100644 --- a/src/main/kotlin/com/github/quiltservertools/ledger/database/DatabaseManager.kt +++ b/src/main/kotlin/com/github/quiltservertools/ledger/database/DatabaseManager.kt @@ -528,7 +528,7 @@ object DatabaseManager { .toSet() // SQLite doesn't support update where so select by ID. Might not be as efficent actions.addAll(getActionsFromQuery(selectQuery)) - val updateQuery = Tables.Actions + Tables.Actions .update({ Tables.Actions.id inList actionIds and (Tables.Actions.rolledBack eq false) }) { it[rolledBack] = true } @@ -555,7 +555,7 @@ object DatabaseManager { val actionIds = selectQuery.map { it[Tables.Actions.id] }.toSet() actions.addAll(getActionsFromQuery(selectQuery)) - val updateQuery = Tables.Actions + Tables.Actions .update({ Tables.Actions.id inList actionIds and (Tables.Actions.rolledBack eq true) }) { it[rolledBack] = false } @@ -695,5 +695,4 @@ object DatabaseManager { return Tables.Player.wrapRows(query).toList().map { PlayerResult.fromRow(it) } } - } diff --git a/src/main/kotlin/com/github/quiltservertools/ledger/database/Tables.kt b/src/main/kotlin/com/github/quiltservertools/ledger/database/Tables.kt index 13a0b9d0..092ca735 100644 --- a/src/main/kotlin/com/github/quiltservertools/ledger/database/Tables.kt +++ b/src/main/kotlin/com/github/quiltservertools/ledger/database/Tables.kt @@ -72,7 +72,6 @@ object Tables { init { index("actions_by_location", false, x, y, z, world) } - } class Action(id: EntityID) : IntEntity(id) { diff --git a/src/main/kotlin/com/github/quiltservertools/ledger/listeners/BlockEventListener.kt b/src/main/kotlin/com/github/quiltservertools/ledger/listeners/BlockEventListener.kt index 63c208db..2f52c8d6 100644 --- a/src/main/kotlin/com/github/quiltservertools/ledger/listeners/BlockEventListener.kt +++ b/src/main/kotlin/com/github/quiltservertools/ledger/listeners/BlockEventListener.kt @@ -15,7 +15,6 @@ import net.minecraft.entity.player.PlayerEntity import net.minecraft.util.math.BlockPos import net.minecraft.world.World - fun registerBlockListeners() { BlockMeltCallback.EVENT.register(::onMelt) BlockPlaceCallback.EVENT.register(::onBlockPlace) diff --git a/src/main/kotlin/com/github/quiltservertools/ledger/listeners/EntityCallbackListener.kt b/src/main/kotlin/com/github/quiltservertools/ledger/listeners/EntityCallbackListener.kt index 3a13e7fd..3818d69d 100644 --- a/src/main/kotlin/com/github/quiltservertools/ledger/listeners/EntityCallbackListener.kt +++ b/src/main/kotlin/com/github/quiltservertools/ledger/listeners/EntityCallbackListener.kt @@ -11,7 +11,6 @@ import net.minecraft.nbt.NbtCompound import net.minecraft.util.math.BlockPos import net.minecraft.world.World - fun registerEntityListeners() { EntityKillCallback.EVENT.register(::onKill) EntityModifyCallback.EVENT.register(::onModify) diff --git a/src/main/kotlin/com/github/quiltservertools/ledger/listeners/PlayerEventListener.kt b/src/main/kotlin/com/github/quiltservertools/ledger/listeners/PlayerEventListener.kt index e37e8568..595ad5df 100644 --- a/src/main/kotlin/com/github/quiltservertools/ledger/listeners/PlayerEventListener.kt +++ b/src/main/kotlin/com/github/quiltservertools/ledger/listeners/PlayerEventListener.kt @@ -74,7 +74,6 @@ private fun onBlockAttack( return ActionResult.PASS } - private fun onJoin(networkHandler: ServerPlayNetworkHandler, packetSender: PacketSender, server: MinecraftServer) { Ledger.launch { DatabaseManager.logPlayer(networkHandler.player.uuid, networkHandler.player.nameForScoreboard) diff --git a/src/main/kotlin/com/github/quiltservertools/ledger/network/Networking.kt b/src/main/kotlin/com/github/quiltservertools/ledger/network/Networking.kt index cf722c50..b512b47e 100644 --- a/src/main/kotlin/com/github/quiltservertools/ledger/network/Networking.kt +++ b/src/main/kotlin/com/github/quiltservertools/ledger/network/Networking.kt @@ -2,20 +2,14 @@ package com.github.quiltservertools.ledger.network import com.github.quiltservertools.ledger.config.NetworkingSpec import com.github.quiltservertools.ledger.config.config -import com.github.quiltservertools.ledger.network.packet.LedgerPacketTypes -import com.github.quiltservertools.ledger.network.packet.Receiver -import com.github.quiltservertools.ledger.network.packet.receiver.HandshakePacketReceiver -import com.github.quiltservertools.ledger.network.packet.receiver.InspectReceiver -import com.github.quiltservertools.ledger.network.packet.receiver.PurgeReceiver -import com.github.quiltservertools.ledger.network.packet.receiver.RollbackReceiver -import com.github.quiltservertools.ledger.network.packet.receiver.SearchReceiver -import net.fabricmc.fabric.api.networking.v1.PacketSender +import com.github.quiltservertools.ledger.network.packet.receiver.HandshakeC2SPacket +import com.github.quiltservertools.ledger.network.packet.receiver.InspectC2SPacket +import com.github.quiltservertools.ledger.network.packet.receiver.PurgeC2SPacket +import com.github.quiltservertools.ledger.network.packet.receiver.RollbackC2SPacket +import com.github.quiltservertools.ledger.network.packet.receiver.SearchC2SPacket +import net.fabricmc.fabric.api.networking.v1.PayloadTypeRegistry import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking -import net.minecraft.network.PacketByteBuf -import net.minecraft.server.MinecraftServer -import net.minecraft.server.network.ServerPlayNetworkHandler import net.minecraft.server.network.ServerPlayerEntity -import net.minecraft.util.Identifier object Networking { // List of players who have a compatible client mod @@ -24,23 +18,20 @@ object Networking { init { if (config[NetworkingSpec.networking]) { - register(LedgerPacketTypes.INSPECT_POS.id, InspectReceiver()) - register(LedgerPacketTypes.SEARCH.id, SearchReceiver()) - register(LedgerPacketTypes.HANDSHAKE.id, HandshakePacketReceiver()) - register(LedgerPacketTypes.ROLLBACK.id, RollbackReceiver()) - register(LedgerPacketTypes.PURGE.id, PurgeReceiver()) - } - } + PayloadTypeRegistry.playC2S().register(InspectC2SPacket.ID, InspectC2SPacket.CODEC) + ServerPlayNetworking.registerGlobalReceiver(InspectC2SPacket.ID, InspectC2SPacket) + + PayloadTypeRegistry.playC2S().register(SearchC2SPacket.ID, SearchC2SPacket.CODEC) + ServerPlayNetworking.registerGlobalReceiver(SearchC2SPacket.ID, SearchC2SPacket) - private fun register(channel: Identifier, receiver: Receiver) { - ServerPlayNetworking.registerGlobalReceiver(channel) { - server: MinecraftServer, - player: ServerPlayerEntity, - handler: ServerPlayNetworkHandler, - buf: PacketByteBuf, - sender: PacketSender -> + PayloadTypeRegistry.playC2S().register(HandshakeC2SPacket.ID, HandshakeC2SPacket.CODEC) + ServerPlayNetworking.registerGlobalReceiver(HandshakeC2SPacket.ID, HandshakeC2SPacket) - receiver.receive(server, player, handler, buf, sender) + PayloadTypeRegistry.playC2S().register(RollbackC2SPacket.ID, RollbackC2SPacket.CODEC) + ServerPlayNetworking.registerGlobalReceiver(RollbackC2SPacket.ID, RollbackC2SPacket) + + PayloadTypeRegistry.playC2S().register(PurgeC2SPacket.ID, PurgeC2SPacket.CODEC) + ServerPlayNetworking.registerGlobalReceiver(PurgeC2SPacket.ID, PurgeC2SPacket) } } @@ -50,4 +41,3 @@ object Networking { fun ServerPlayerEntity.disableNetworking() = networkedPlayers.remove(this) } - diff --git a/src/main/kotlin/com/github/quiltservertools/ledger/network/packet/LedgerPacket.kt b/src/main/kotlin/com/github/quiltservertools/ledger/network/packet/LedgerPacket.kt deleted file mode 100644 index d358710d..00000000 --- a/src/main/kotlin/com/github/quiltservertools/ledger/network/packet/LedgerPacket.kt +++ /dev/null @@ -1,10 +0,0 @@ -package com.github.quiltservertools.ledger.network.packet - -import net.minecraft.network.PacketByteBuf -import net.minecraft.util.Identifier - -interface LedgerPacket { - val channel: Identifier - var buf: PacketByteBuf - fun populate(content: T) -} diff --git a/src/main/kotlin/com/github/quiltservertools/ledger/network/packet/action/ActionPacket.kt b/src/main/kotlin/com/github/quiltservertools/ledger/network/packet/action/ActionPacket.kt deleted file mode 100644 index ba46f739..00000000 --- a/src/main/kotlin/com/github/quiltservertools/ledger/network/packet/action/ActionPacket.kt +++ /dev/null @@ -1,33 +0,0 @@ -package com.github.quiltservertools.ledger.network.packet.action - -import com.github.quiltservertools.ledger.actions.ActionType -import com.github.quiltservertools.ledger.network.packet.LedgerPacket -import com.github.quiltservertools.ledger.network.packet.LedgerPacketTypes -import net.fabricmc.fabric.api.networking.v1.PacketByteBufs -import net.minecraft.network.PacketByteBuf -import net.minecraft.util.Identifier - -class ActionPacket: LedgerPacket { - override val channel: Identifier = LedgerPacketTypes.ACTION.id - override var buf: PacketByteBuf = PacketByteBufs.create() - - override fun populate(content: ActionType) { - // Position - buf.writeBlockPos(content.pos) - // Type - buf.writeString(content.identifier) - // Dimension - buf.writeIdentifier(content.world) - // Objects - buf.writeIdentifier(content.oldObjectIdentifier) - buf.writeIdentifier(content.objectIdentifier) - // Source - buf.writeString(content.sourceProfile?.name ?: "@" + content.sourceName) - // Epoch second of event, sent as a long - buf.writeLong(content.timestamp.epochSecond) - // Has been rolled back? - buf.writeBoolean(content.rolledBack) - // NBT - buf.writeString(content.extraData ?: "") - } -} diff --git a/src/main/kotlin/com/github/quiltservertools/ledger/network/packet/action/ActionS2CPacket.kt b/src/main/kotlin/com/github/quiltservertools/ledger/network/packet/action/ActionS2CPacket.kt new file mode 100644 index 00000000..05e16ccd --- /dev/null +++ b/src/main/kotlin/com/github/quiltservertools/ledger/network/packet/action/ActionS2CPacket.kt @@ -0,0 +1,39 @@ +package com.github.quiltservertools.ledger.network.packet.action + +import com.github.quiltservertools.ledger.actions.ActionType +import com.github.quiltservertools.ledger.network.packet.LedgerPacketTypes +import net.minecraft.network.PacketByteBuf +import net.minecraft.network.codec.PacketCodec +import net.minecraft.network.packet.CustomPayload +import net.minecraft.network.packet.CustomPayload.Id + +data class ActionS2CPacket(val content: ActionType) : CustomPayload { + private fun write(buf: PacketByteBuf?) { + // Position + buf?.writeBlockPos(content.pos) + // Type + buf?.writeString(content.identifier) + // Dimension + buf?.writeIdentifier(content.world) + // Objects + buf?.writeIdentifier(content.oldObjectIdentifier) + buf?.writeIdentifier(content.objectIdentifier) + // Source + buf?.writeString(content.sourceProfile?.name ?: "@" + content.sourceName) + // Epoch second of event, sent as a long + buf?.writeLong(content.timestamp.epochSecond) + // Has been rolled back? + buf?.writeBoolean(content.rolledBack) + // NBT + buf?.writeString(content.extraData ?: "") + } + + override fun getId() = ID + + companion object { + val ID: Id = Id(LedgerPacketTypes.ACTION.id) + val CODEC: PacketCodec = CustomPayload.codecOf( + ActionS2CPacket::write + ) { _: PacketByteBuf? -> TODO() } + } +} diff --git a/src/main/kotlin/com/github/quiltservertools/ledger/network/packet/handshake/HandshakePacket.kt b/src/main/kotlin/com/github/quiltservertools/ledger/network/packet/handshake/HandshakePacket.kt deleted file mode 100644 index 9c0ebb46..00000000 --- a/src/main/kotlin/com/github/quiltservertools/ledger/network/packet/handshake/HandshakePacket.kt +++ /dev/null @@ -1,27 +0,0 @@ -package com.github.quiltservertools.ledger.network.packet.handshake - -import com.github.quiltservertools.ledger.network.packet.LedgerPacket -import com.github.quiltservertools.ledger.network.packet.LedgerPacketTypes -import net.fabricmc.fabric.api.networking.v1.PacketByteBufs -import net.minecraft.network.PacketByteBuf -import net.minecraft.util.Identifier - -class HandshakePacket: LedgerPacket { - override val channel: Identifier = LedgerPacketTypes.HANDSHAKE.id - override var buf: PacketByteBuf = PacketByteBufs.create() - override fun populate(content: HandshakeContent) { - // Ledger information - // Protocol Version - buf.writeInt(content.protocolVersion) - - // Ledger Version - buf.writeString(content.ledgerVersion) - - // We tell the client mod how many actions we are writing - buf.writeInt(content.actions.size) - - for (action in content.actions) { - buf.writeString(action) - } - } -} diff --git a/src/main/kotlin/com/github/quiltservertools/ledger/network/packet/handshake/HandshakeS2CPacket.kt b/src/main/kotlin/com/github/quiltservertools/ledger/network/packet/handshake/HandshakeS2CPacket.kt new file mode 100644 index 00000000..433023f2 --- /dev/null +++ b/src/main/kotlin/com/github/quiltservertools/ledger/network/packet/handshake/HandshakeS2CPacket.kt @@ -0,0 +1,33 @@ +package com.github.quiltservertools.ledger.network.packet.handshake + +import com.github.quiltservertools.ledger.network.packet.LedgerPacketTypes +import net.minecraft.network.PacketByteBuf +import net.minecraft.network.codec.PacketCodec +import net.minecraft.network.packet.CustomPayload + +data class HandshakeS2CPacket(val content: HandshakeContent) : CustomPayload { + fun write(buf: PacketByteBuf?) { + // Ledger information + // Protocol Version + buf?.writeInt(content.protocolVersion) + + // Ledger Version + buf?.writeString(content.ledgerVersion) + + // We tell the client mod how many actions we are writing + buf?.writeInt(content.actions.size) + + for (action in content.actions) { + buf?.writeString(action) + } + } + + override fun getId() = ID + + companion object { + val ID: CustomPayload.Id = CustomPayload.Id(LedgerPacketTypes.HANDSHAKE.id) + val CODEC: PacketCodec = CustomPayload.codecOf( + HandshakeS2CPacket::write + ) { _: PacketByteBuf? -> TODO() } + } +} diff --git a/src/main/kotlin/com/github/quiltservertools/ledger/network/packet/handshake/ModInfo.kt b/src/main/kotlin/com/github/quiltservertools/ledger/network/packet/handshake/ModInfo.kt index 8e0670e9..53f0c1c5 100644 --- a/src/main/kotlin/com/github/quiltservertools/ledger/network/packet/handshake/ModInfo.kt +++ b/src/main/kotlin/com/github/quiltservertools/ledger/network/packet/handshake/ModInfo.kt @@ -1,3 +1,3 @@ package com.github.quiltservertools.ledger.network.packet.handshake -data class ModInfo (val modid: String, val version: String, val protocolVersion: Int) +data class ModInfo(val modid: String, val version: String, val protocolVersion: Int) diff --git a/src/main/kotlin/com/github/quiltservertools/ledger/network/packet/receiver/HandshakeC2SPacket.kt b/src/main/kotlin/com/github/quiltservertools/ledger/network/packet/receiver/HandshakeC2SPacket.kt new file mode 100644 index 00000000..66acdbd6 --- /dev/null +++ b/src/main/kotlin/com/github/quiltservertools/ledger/network/packet/receiver/HandshakeC2SPacket.kt @@ -0,0 +1,87 @@ +package com.github.quiltservertools.ledger.network.packet.receiver + +import com.github.quiltservertools.ledger.Ledger +import com.github.quiltservertools.ledger.commands.CommandConsts +import com.github.quiltservertools.ledger.logInfo +import com.github.quiltservertools.ledger.network.Networking +import com.github.quiltservertools.ledger.network.Networking.enableNetworking +import com.github.quiltservertools.ledger.network.packet.LedgerPacketTypes +import com.github.quiltservertools.ledger.network.packet.handshake.HandshakeContent +import com.github.quiltservertools.ledger.network.packet.handshake.ModInfo +import com.github.quiltservertools.ledger.registry.ActionRegistry +import me.lucko.fabric.api.permissions.v0.Permissions +import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking +import net.fabricmc.loader.api.FabricLoader +import net.minecraft.nbt.NbtCompound +import net.minecraft.network.PacketByteBuf +import net.minecraft.network.codec.PacketCodec +import net.minecraft.network.packet.CustomPayload +import net.minecraft.text.Text +import java.util.* + +data class HandshakeC2SPacket(val nbt: NbtCompound?) : CustomPayload { + + override fun getId() = ID + + companion object : ServerPlayNetworking.PlayPayloadHandler { + val ID: CustomPayload.Id = CustomPayload.Id(LedgerPacketTypes.HANDSHAKE.id) + val CODEC: PacketCodec = CustomPayload.codecOf({ _, _ -> TODO() }, { + HandshakeC2SPacket(it.readNbt()) + }) + + override fun receive(payload: HandshakeC2SPacket, context: ServerPlayNetworking.Context) { + val player = context.player() + if (!Permissions.check(player, "ledger.networking", CommandConsts.PERMISSION_LEVEL)) return + // This should be sent by the client whenever a player joins with a client mod + // We do some validation on the packet to make sure it's complete and intact + val info = readInfo(payload.nbt) + if (info.isPresent) { + val modid = info.get().modid + val modVersion = info.get().version + val ledgerVersion = FabricLoader.getInstance().getModContainer( + Ledger.MOD_ID + ).get().metadata.version.friendlyString + if (Networking.PROTOCOL_VERSION == info.get().protocolVersion) { + logInfo("${player.name.string} joined the server with a Ledger compatible client mod") + logInfo("Mod: $modid, Version: $modVersion") + + // Player has networking permissions so we send a response + val packet = com.github.quiltservertools.ledger.network.packet.handshake.HandshakeS2CPacket( + HandshakeContent( + Networking.PROTOCOL_VERSION, + ledgerVersion, + ActionRegistry.getTypes().toList() + ) + ) + ServerPlayNetworking.send(player, packet) + player.enableNetworking() + } else { + player.sendMessage( + Text.translatable( + "text.ledger.network.protocols_mismatched", + Networking.PROTOCOL_VERSION, + info.get().protocolVersion + ), + false + ) + logInfo( + "${player.name.string} joined the server with a Ledger compatible client mod, " + + "but has a mismatched protocol: Ledger protocol version: ${Networking.PROTOCOL_VERSION}" + + ", Client mod protocol version ${info.get().protocolVersion}" + ) + } + } else { + player.sendMessage(Text.translatable("text.ledger.network.no_mod_info"), false) + } + } + private fun readInfo(nbt: NbtCompound?): Optional { + if (nbt == null) { + return Optional.empty() + } + + return Optional.of( + ModInfo(nbt.getString("modid"), nbt.getString("version"), nbt.getInt("protocol_version")) + ) + } + } +} diff --git a/src/main/kotlin/com/github/quiltservertools/ledger/network/packet/receiver/HandshakePacketReceiver.kt b/src/main/kotlin/com/github/quiltservertools/ledger/network/packet/receiver/HandshakePacketReceiver.kt deleted file mode 100644 index a871258c..00000000 --- a/src/main/kotlin/com/github/quiltservertools/ledger/network/packet/receiver/HandshakePacketReceiver.kt +++ /dev/null @@ -1,75 +0,0 @@ -package com.github.quiltservertools.ledger.network.packet.receiver - -import com.github.quiltservertools.ledger.Ledger -import com.github.quiltservertools.ledger.commands.CommandConsts -import com.github.quiltservertools.ledger.logInfo -import com.github.quiltservertools.ledger.network.Networking -import com.github.quiltservertools.ledger.network.Networking.enableNetworking -import com.github.quiltservertools.ledger.network.packet.Receiver -import com.github.quiltservertools.ledger.network.packet.handshake.HandshakeContent -import com.github.quiltservertools.ledger.network.packet.handshake.HandshakePacket -import com.github.quiltservertools.ledger.network.packet.handshake.ModInfo -import com.github.quiltservertools.ledger.registry.ActionRegistry -import me.lucko.fabric.api.permissions.v0.Permissions -import net.fabricmc.fabric.api.networking.v1.PacketSender -import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking -import net.fabricmc.loader.api.FabricLoader -import net.minecraft.nbt.NbtCompound -import net.minecraft.network.PacketByteBuf -import net.minecraft.server.MinecraftServer -import net.minecraft.server.network.ServerPlayNetworkHandler -import net.minecraft.server.network.ServerPlayerEntity -import net.minecraft.text.Text -import java.util.* - -class HandshakePacketReceiver : Receiver { - override fun receive( - server: MinecraftServer, - player: ServerPlayerEntity, - handler: ServerPlayNetworkHandler, - buf: PacketByteBuf, - sender: PacketSender - ) { - if (!Permissions.check(player, "ledger.networking", CommandConsts.PERMISSION_LEVEL)) return - // This should be sent by the client whenever a player joins with a client mod - val nbt = buf.readNbt() - // We do some validation on the packet to make sure it's complete and intact - val info = readInfo(nbt) - if (info.isPresent) { - val modid = info.get().modid - val modVersion = info.get().version - val ledgerVersion = FabricLoader.getInstance().getModContainer( - Ledger.MOD_ID).get().metadata.version.friendlyString - if (Networking.PROTOCOL_VERSION == info.get().protocolVersion) { - logInfo("${player.name.string} joined the server with a Ledger compatible client mod") - logInfo("Mod: $modid, Version: $modVersion") - - // Player has networking permissions so we send a response - val packet = HandshakePacket() - packet.populate(HandshakeContent(Networking.PROTOCOL_VERSION, ledgerVersion, ActionRegistry.getTypes().toList())) - ServerPlayNetworking.send(player, packet.channel, packet.buf) - player.enableNetworking() - } else { - player.sendMessage( - Text.translatable( - "text.ledger.network.protocols_mismatched", - Networking.PROTOCOL_VERSION, info.get().protocolVersion - ), false - ) - logInfo("${player.name.string} joined the server with a Ledger compatible client mod, " + - "but has a mismatched protocol: Ledger protocol version: ${Networking.PROTOCOL_VERSION}" + - ", Client mod protocol version ${info.get().protocolVersion}") - } - } else { - player.sendMessage(Text.translatable("text.ledger.network.no_mod_info"), false) - } - } - - private fun readInfo(nbt: NbtCompound?): Optional { - if (nbt == null) { - return Optional.empty() - } - - return Optional.of(ModInfo(nbt.getString("modid"), nbt.getString("version"), nbt.getInt("protocol_version"))) - } -} diff --git a/src/main/kotlin/com/github/quiltservertools/ledger/network/packet/receiver/InspectC2SPacket.kt b/src/main/kotlin/com/github/quiltservertools/ledger/network/packet/receiver/InspectC2SPacket.kt new file mode 100644 index 00000000..0c1c0c21 --- /dev/null +++ b/src/main/kotlin/com/github/quiltservertools/ledger/network/packet/receiver/InspectC2SPacket.kt @@ -0,0 +1,65 @@ +package com.github.quiltservertools.ledger.network.packet.receiver + +import com.github.quiltservertools.ledger.Ledger +import com.github.quiltservertools.ledger.commands.CommandConsts +import com.github.quiltservertools.ledger.database.DatabaseManager +import com.github.quiltservertools.ledger.network.packet.LedgerPacketTypes +import com.github.quiltservertools.ledger.network.packet.action.ActionS2CPacket +import com.github.quiltservertools.ledger.network.packet.response.ResponseCodes +import com.github.quiltservertools.ledger.network.packet.response.ResponseContent +import com.github.quiltservertools.ledger.network.packet.response.ResponseS2CPacket +import com.github.quiltservertools.ledger.utility.getInspectResults +import kotlinx.coroutines.launch +import me.lucko.fabric.api.permissions.v0.Permissions +import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking +import net.minecraft.network.PacketByteBuf +import net.minecraft.network.codec.PacketCodec +import net.minecraft.network.packet.CustomPayload +import net.minecraft.util.math.BlockPos + +data class InspectC2SPacket(val pos: BlockPos, val pages: Int) : CustomPayload { + + override fun getId() = ID + + companion object : ServerPlayNetworking.PlayPayloadHandler { + val ID: CustomPayload.Id = CustomPayload.Id(LedgerPacketTypes.INSPECT_POS.id) + val CODEC: PacketCodec = CustomPayload.codecOf({ _, _ -> TODO() }, { + InspectC2SPacket(it.readBlockPos(), it.readInt()) + }) + + override fun receive(payload: InspectC2SPacket, context: ServerPlayNetworking.Context) { + val player = context.player() + val sender = context.responseSender() + if (!Permissions.check(player, "ledger.networking", CommandConsts.PERMISSION_LEVEL) || + !Permissions.check(player, "ledger.commands.inspect", CommandConsts.PERMISSION_LEVEL) + ) { + ResponseS2CPacket.sendResponse( + ResponseContent( + LedgerPacketTypes.INSPECT_POS.id, + ResponseCodes.NO_PERMISSION.code + ), + sender + ) + return + } + ResponseS2CPacket.sendResponse( + ResponseContent(LedgerPacketTypes.INSPECT_POS.id, ResponseCodes.EXECUTING.code), + sender + ) + + Ledger.launch { + val results = player.getInspectResults(payload.pos) + for (i in 1..payload.pages) { + val page = DatabaseManager.searchActions(results.searchParams, i) + page.actions.forEach { action -> + sender.sendPacket(ActionS2CPacket(action)) + } + } + ResponseS2CPacket.sendResponse( + ResponseContent(LedgerPacketTypes.INSPECT_POS.id, ResponseCodes.COMPLETED.code), + sender + ) + } + } + } +} diff --git a/src/main/kotlin/com/github/quiltservertools/ledger/network/packet/receiver/InspectReceiver.kt b/src/main/kotlin/com/github/quiltservertools/ledger/network/packet/receiver/InspectReceiver.kt deleted file mode 100644 index b4045503..00000000 --- a/src/main/kotlin/com/github/quiltservertools/ledger/network/packet/receiver/InspectReceiver.kt +++ /dev/null @@ -1,54 +0,0 @@ -package com.github.quiltservertools.ledger.network.packet.receiver - -import com.github.quiltservertools.ledger.Ledger -import com.github.quiltservertools.ledger.commands.CommandConsts -import com.github.quiltservertools.ledger.database.DatabaseManager -import com.github.quiltservertools.ledger.network.packet.LedgerPacketTypes -import com.github.quiltservertools.ledger.network.packet.Receiver -import com.github.quiltservertools.ledger.network.packet.action.ActionPacket -import com.github.quiltservertools.ledger.network.packet.response.ResponseCodes -import com.github.quiltservertools.ledger.network.packet.response.ResponseContent -import com.github.quiltservertools.ledger.network.packet.response.ResponsePacket -import com.github.quiltservertools.ledger.utility.getInspectResults -import kotlinx.coroutines.launch -import me.lucko.fabric.api.permissions.v0.Permissions -import net.fabricmc.fabric.api.networking.v1.PacketSender -import net.minecraft.network.PacketByteBuf -import net.minecraft.server.MinecraftServer -import net.minecraft.server.network.ServerPlayNetworkHandler -import net.minecraft.server.network.ServerPlayerEntity - -class InspectReceiver : Receiver { - override fun receive( - server: MinecraftServer, - player: ServerPlayerEntity, - handler: ServerPlayNetworkHandler, - buf: PacketByteBuf, - sender: PacketSender - ) { - if (!Permissions.check(player, "ledger.networking", CommandConsts.PERMISSION_LEVEL) || - !Permissions.check(player, "ledger.commands.inspect", CommandConsts.PERMISSION_LEVEL) - ) { - ResponsePacket.sendResponse(ResponseContent(LedgerPacketTypes.INSPECT_POS.id, ResponseCodes.NO_PERMISSION.code), sender) - return - } - - val pos = buf.readBlockPos() - ResponsePacket.sendResponse(ResponseContent(LedgerPacketTypes.INSPECT_POS.id, ResponseCodes.EXECUTING.code), sender) - - val pages = buf.readInt() - - Ledger.launch { - val results = player.getInspectResults(pos) - for (i in 1..pages) { - val page = DatabaseManager.searchActions(results.searchParams, i) - page.actions.forEach { action -> - val packet = ActionPacket() - packet.populate(action) - sender.sendPacket(packet.channel, packet.buf) - } - } - ResponsePacket.sendResponse(ResponseContent(LedgerPacketTypes.INSPECT_POS.id, ResponseCodes.COMPLETED.code), sender) - } - } -} diff --git a/src/main/kotlin/com/github/quiltservertools/ledger/network/packet/receiver/PurgeC2SPacket.kt b/src/main/kotlin/com/github/quiltservertools/ledger/network/packet/receiver/PurgeC2SPacket.kt new file mode 100644 index 00000000..10e2e2c4 --- /dev/null +++ b/src/main/kotlin/com/github/quiltservertools/ledger/network/packet/receiver/PurgeC2SPacket.kt @@ -0,0 +1,65 @@ +package com.github.quiltservertools.ledger.network.packet.receiver + +import com.github.quiltservertools.ledger.Ledger +import com.github.quiltservertools.ledger.commands.CommandConsts +import com.github.quiltservertools.ledger.database.DatabaseManager +import com.github.quiltservertools.ledger.network.packet.LedgerPacketTypes +import com.github.quiltservertools.ledger.network.packet.action.ActionS2CPacket +import com.github.quiltservertools.ledger.network.packet.response.ResponseCodes +import com.github.quiltservertools.ledger.network.packet.response.ResponseContent +import com.github.quiltservertools.ledger.network.packet.response.ResponseS2CPacket +import com.github.quiltservertools.ledger.utility.getInspectResults +import kotlinx.coroutines.launch +import me.lucko.fabric.api.permissions.v0.Permissions +import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking +import net.minecraft.network.PacketByteBuf +import net.minecraft.network.codec.PacketCodec +import net.minecraft.network.packet.CustomPayload +import net.minecraft.util.math.BlockPos + +data class PurgeC2SPacket(val pos: BlockPos, val pages: Int) : CustomPayload { + + override fun getId() = ID + + companion object : ServerPlayNetworking.PlayPayloadHandler { + val ID: CustomPayload.Id = CustomPayload.Id(LedgerPacketTypes.PURGE.id) + val CODEC: PacketCodec = CustomPayload.codecOf({ _, _ -> TODO() }, { + PurgeC2SPacket(it.readBlockPos(), it.readInt()) + }) + + override fun receive(payload: PurgeC2SPacket, context: ServerPlayNetworking.Context) { + val player = context.player() + val sender = context.responseSender() + if (!Permissions.check(player, "ledger.networking", CommandConsts.PERMISSION_LEVEL) || + !Permissions.check(player, "ledger.commands.inspect", CommandConsts.PERMISSION_LEVEL) + ) { + ResponseS2CPacket.sendResponse( + ResponseContent( + LedgerPacketTypes.INSPECT_POS.id, + ResponseCodes.NO_PERMISSION.code + ), + sender + ) + return + } + ResponseS2CPacket.sendResponse( + ResponseContent(LedgerPacketTypes.INSPECT_POS.id, ResponseCodes.EXECUTING.code), + sender + ) + + Ledger.launch { + val results = player.getInspectResults(payload.pos) + for (i in 1..payload.pages) { + val page = DatabaseManager.searchActions(results.searchParams, i) + page.actions.forEach { action -> + sender.sendPacket(ActionS2CPacket(action)) + } + } + ResponseS2CPacket.sendResponse( + ResponseContent(LedgerPacketTypes.INSPECT_POS.id, ResponseCodes.COMPLETED.code), + sender + ) + } + } + } +} diff --git a/src/main/kotlin/com/github/quiltservertools/ledger/network/packet/receiver/PurgeReceiver.kt b/src/main/kotlin/com/github/quiltservertools/ledger/network/packet/receiver/PurgeReceiver.kt deleted file mode 100644 index ac264442..00000000 --- a/src/main/kotlin/com/github/quiltservertools/ledger/network/packet/receiver/PurgeReceiver.kt +++ /dev/null @@ -1,45 +0,0 @@ -package com.github.quiltservertools.ledger.network.packet.receiver - -import com.github.quiltservertools.ledger.Ledger -import com.github.quiltservertools.ledger.commands.CommandConsts -import com.github.quiltservertools.ledger.commands.arguments.SearchParamArgument -import com.github.quiltservertools.ledger.database.DatabaseManager -import com.github.quiltservertools.ledger.network.packet.LedgerPacketTypes -import com.github.quiltservertools.ledger.network.packet.Receiver -import com.github.quiltservertools.ledger.network.packet.response.ResponseCodes -import com.github.quiltservertools.ledger.network.packet.response.ResponseContent -import com.github.quiltservertools.ledger.network.packet.response.ResponsePacket -import kotlinx.coroutines.launch -import me.lucko.fabric.api.permissions.v0.Permissions -import net.fabricmc.fabric.api.networking.v1.PacketSender -import net.minecraft.network.PacketByteBuf -import net.minecraft.server.MinecraftServer -import net.minecraft.server.network.ServerPlayNetworkHandler -import net.minecraft.server.network.ServerPlayerEntity - -class PurgeReceiver : Receiver { - override fun receive( - server: MinecraftServer, - player: ServerPlayerEntity, - handler: ServerPlayNetworkHandler, - buf: PacketByteBuf, - sender: PacketSender - ) { - if (!Permissions.check(player, "ledger.networking", CommandConsts.PERMISSION_LEVEL) || - !Permissions.check(player, "ledger.commands.purge", CommandConsts.PERMISSION_LEVEL)) { - ResponsePacket.sendResponse(ResponseContent(LedgerPacketTypes.PURGE.id, ResponseCodes.NO_PERMISSION.code), sender) - return - } - - val params = SearchParamArgument.get(buf.readString(), player.commandSource) - - ResponsePacket.sendResponse(ResponseContent(LedgerPacketTypes.PURGE.id, ResponseCodes.EXECUTING.code), sender) - - Ledger.launch { - - DatabaseManager.purgeActions(params) - - ResponsePacket.sendResponse(ResponseContent(LedgerPacketTypes.PURGE.id, ResponseCodes.COMPLETED.code), sender) - } - } -} diff --git a/src/main/kotlin/com/github/quiltservertools/ledger/network/packet/receiver/RollbackC2SPacket.kt b/src/main/kotlin/com/github/quiltservertools/ledger/network/packet/receiver/RollbackC2SPacket.kt new file mode 100644 index 00000000..19e93a9a --- /dev/null +++ b/src/main/kotlin/com/github/quiltservertools/ledger/network/packet/receiver/RollbackC2SPacket.kt @@ -0,0 +1,58 @@ +package com.github.quiltservertools.ledger.network.packet.receiver + +import com.github.quiltservertools.ledger.Ledger +import com.github.quiltservertools.ledger.commands.CommandConsts +import com.github.quiltservertools.ledger.commands.arguments.SearchParamArgument +import com.github.quiltservertools.ledger.database.DatabaseManager +import com.github.quiltservertools.ledger.network.packet.LedgerPacketTypes +import com.github.quiltservertools.ledger.network.packet.response.ResponseCodes +import com.github.quiltservertools.ledger.network.packet.response.ResponseContent +import com.github.quiltservertools.ledger.network.packet.response.ResponseS2CPacket +import kotlinx.coroutines.launch +import me.lucko.fabric.api.permissions.v0.Permissions +import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking +import net.minecraft.network.PacketByteBuf +import net.minecraft.network.codec.PacketCodec +import net.minecraft.network.packet.CustomPayload + +data class RollbackC2SPacket(val input: String) : CustomPayload { + + override fun getId() = ID + + companion object : ServerPlayNetworking.PlayPayloadHandler { + val ID: CustomPayload.Id = CustomPayload.Id(LedgerPacketTypes.ROLLBACK.id) + val CODEC: PacketCodec = CustomPayload.codecOf({ _, _ -> TODO() }, { + RollbackC2SPacket(it.readString()) + }) + + override fun receive(payload: RollbackC2SPacket, context: ServerPlayNetworking.Context) { + val player = context.player() + val sender = context.responseSender() + if (!Permissions.check(player, "ledger.networking", CommandConsts.PERMISSION_LEVEL) || + !Permissions.check(player, "ledger.commands.purge", CommandConsts.PERMISSION_LEVEL) + ) { + ResponseS2CPacket.sendResponse( + ResponseContent(LedgerPacketTypes.PURGE.id, ResponseCodes.NO_PERMISSION.code), + sender + ) + return + } + + val params = SearchParamArgument.get(payload.input, player.commandSource) + + ResponseS2CPacket.sendResponse( + ResponseContent(LedgerPacketTypes.PURGE.id, ResponseCodes.EXECUTING.code), + sender + ) + + Ledger.launch { + DatabaseManager.purgeActions(params) + + ResponseS2CPacket.sendResponse( + ResponseContent(LedgerPacketTypes.PURGE.id, ResponseCodes.COMPLETED.code), + sender + ) + } + } + } +} diff --git a/src/main/kotlin/com/github/quiltservertools/ledger/network/packet/receiver/RollbackReceiver.kt b/src/main/kotlin/com/github/quiltservertools/ledger/network/packet/receiver/RollbackReceiver.kt deleted file mode 100644 index c158667c..00000000 --- a/src/main/kotlin/com/github/quiltservertools/ledger/network/packet/receiver/RollbackReceiver.kt +++ /dev/null @@ -1,76 +0,0 @@ -package com.github.quiltservertools.ledger.network.packet.receiver - -import com.github.quiltservertools.ledger.Ledger -import com.github.quiltservertools.ledger.commands.CommandConsts -import com.github.quiltservertools.ledger.commands.arguments.SearchParamArgument -import com.github.quiltservertools.ledger.database.DatabaseManager -import com.github.quiltservertools.ledger.network.packet.LedgerPacketTypes -import com.github.quiltservertools.ledger.network.packet.Receiver -import com.github.quiltservertools.ledger.network.packet.response.ResponseCodes -import com.github.quiltservertools.ledger.network.packet.response.ResponseContent -import com.github.quiltservertools.ledger.network.packet.response.ResponsePacket -import com.github.quiltservertools.ledger.utility.MessageUtils -import com.github.quiltservertools.ledger.utility.launchMain -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.launch -import me.lucko.fabric.api.permissions.v0.Permissions -import net.fabricmc.fabric.api.networking.v1.PacketSender -import net.minecraft.network.PacketByteBuf -import net.minecraft.server.MinecraftServer -import net.minecraft.server.network.ServerPlayNetworkHandler -import net.minecraft.server.network.ServerPlayerEntity - -class RollbackReceiver : Receiver { - override fun receive( - server: MinecraftServer, - player: ServerPlayerEntity, - handler: ServerPlayNetworkHandler, - buf: PacketByteBuf, - sender: PacketSender - ) { - if (!Permissions.check(player, "ledger.networking", CommandConsts.PERMISSION_LEVEL) || - !Permissions.check(player, "ledger.commands.rollback", CommandConsts.PERMISSION_LEVEL) - ) { - ResponsePacket.sendResponse(ResponseContent(LedgerPacketTypes.ROLLBACK.id, ResponseCodes.NO_PERMISSION.code), sender) - return - } - - val source = player.commandSource - val restore = buf.readBoolean() - val args = buf.readString() - - val params = SearchParamArgument.get(args, source) - - ResponsePacket.sendResponse(ResponseContent(LedgerPacketTypes.ROLLBACK.id, ResponseCodes.EXECUTING.code), sender) - - Ledger.launch(Dispatchers.IO) { - MessageUtils.warnBusy(source) - if (restore) { - val actions = DatabaseManager.restoreActions(params) - - source.world.launchMain { - - for (action in actions) { - action.restore(source.server) - action.rolledBack = false - } - - ResponsePacket.sendResponse(ResponseContent(LedgerPacketTypes.ROLLBACK.id, ResponseCodes.COMPLETED.code), sender) - } - } else { - val actions = DatabaseManager.rollbackActions(params) - - source.world.launchMain { - - for (action in actions) { - action.rollback(source.server) - action.rolledBack = true - } - - ResponsePacket.sendResponse(ResponseContent(LedgerPacketTypes.ROLLBACK.id, ResponseCodes.COMPLETED.code), sender) - } - } - } - - } -} diff --git a/src/main/kotlin/com/github/quiltservertools/ledger/network/packet/receiver/SearchC2SPacket.kt b/src/main/kotlin/com/github/quiltservertools/ledger/network/packet/receiver/SearchC2SPacket.kt new file mode 100644 index 00000000..2102067a --- /dev/null +++ b/src/main/kotlin/com/github/quiltservertools/ledger/network/packet/receiver/SearchC2SPacket.kt @@ -0,0 +1,96 @@ +package com.github.quiltservertools.ledger.network.packet.receiver + +import com.github.quiltservertools.ledger.Ledger +import com.github.quiltservertools.ledger.commands.CommandConsts +import com.github.quiltservertools.ledger.commands.arguments.SearchParamArgument +import com.github.quiltservertools.ledger.database.DatabaseManager +import com.github.quiltservertools.ledger.network.packet.LedgerPacketTypes +import com.github.quiltservertools.ledger.network.packet.response.ResponseCodes +import com.github.quiltservertools.ledger.network.packet.response.ResponseContent +import com.github.quiltservertools.ledger.network.packet.response.ResponseS2CPacket +import com.github.quiltservertools.ledger.utility.MessageUtils +import com.github.quiltservertools.ledger.utility.launchMain +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import me.lucko.fabric.api.permissions.v0.Permissions +import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking +import net.minecraft.network.PacketByteBuf +import net.minecraft.network.codec.PacketCodec +import net.minecraft.network.packet.CustomPayload + +data class SearchC2SPacket(val restore: Boolean, val args: String) : CustomPayload { + + override fun getId() = ID + + companion object : ServerPlayNetworking.PlayPayloadHandler { + val ID: CustomPayload.Id = CustomPayload.Id(LedgerPacketTypes.SEARCH.id) + val CODEC: PacketCodec = CustomPayload.codecOf({ _, _ -> TODO() }, { + SearchC2SPacket(it.readBoolean(), it.readString()) + }) + + override fun receive(payload: SearchC2SPacket, context: ServerPlayNetworking.Context) { + val player = context.player() + val sender = context.responseSender() + if (!Permissions.check(player, "ledger.networking", CommandConsts.PERMISSION_LEVEL) || + !Permissions.check(player, "ledger.commands.rollback", CommandConsts.PERMISSION_LEVEL) + ) { + ResponseS2CPacket.sendResponse( + ResponseContent( + LedgerPacketTypes.ROLLBACK.id, + ResponseCodes.NO_PERMISSION.code + ), + sender + ) + return + } + + val source = player.commandSource + + val params = SearchParamArgument.get(payload.args, source) + + ResponseS2CPacket.sendResponse( + ResponseContent(LedgerPacketTypes.ROLLBACK.id, ResponseCodes.EXECUTING.code), + sender + ) + + Ledger.launch(Dispatchers.IO) { + MessageUtils.warnBusy(source) + if (payload.restore) { + val actions = DatabaseManager.restoreActions(params) + + source.world.launchMain { + for (action in actions) { + action.restore(source.server) + action.rolledBack = false + } + + ResponseS2CPacket.sendResponse( + ResponseContent( + LedgerPacketTypes.ROLLBACK.id, + ResponseCodes.COMPLETED.code + ), + sender + ) + } + } else { + val actions = DatabaseManager.rollbackActions(params) + + source.world.launchMain { + for (action in actions) { + action.rollback(source.server) + action.rolledBack = true + } + + ResponseS2CPacket.sendResponse( + ResponseContent( + LedgerPacketTypes.ROLLBACK.id, + ResponseCodes.COMPLETED.code + ), + sender + ) + } + } + } + } + } +} diff --git a/src/main/kotlin/com/github/quiltservertools/ledger/network/packet/receiver/SearchReceiver.kt b/src/main/kotlin/com/github/quiltservertools/ledger/network/packet/receiver/SearchReceiver.kt deleted file mode 100644 index 5cf41845..00000000 --- a/src/main/kotlin/com/github/quiltservertools/ledger/network/packet/receiver/SearchReceiver.kt +++ /dev/null @@ -1,82 +0,0 @@ -package com.github.quiltservertools.ledger.network.packet.receiver - -import com.github.quiltservertools.ledger.Ledger -import com.github.quiltservertools.ledger.commands.CommandConsts -import com.github.quiltservertools.ledger.commands.arguments.SearchParamArgument -import com.github.quiltservertools.ledger.database.DatabaseManager -import com.github.quiltservertools.ledger.network.packet.LedgerPacketTypes -import com.github.quiltservertools.ledger.network.packet.Receiver -import com.github.quiltservertools.ledger.network.packet.response.ResponseCodes -import com.github.quiltservertools.ledger.network.packet.response.ResponseContent -import com.github.quiltservertools.ledger.network.packet.response.ResponsePacket -import com.github.quiltservertools.ledger.utility.MessageUtils -import com.github.quiltservertools.ledger.utility.TextColorPallet -import kotlinx.coroutines.launch -import me.lucko.fabric.api.permissions.v0.Permissions -import net.fabricmc.fabric.api.networking.v1.PacketSender -import net.minecraft.network.PacketByteBuf -import net.minecraft.server.MinecraftServer -import net.minecraft.server.network.ServerPlayNetworkHandler -import net.minecraft.server.network.ServerPlayerEntity -import net.minecraft.text.Text - -class SearchReceiver : Receiver { - override fun receive( - server: MinecraftServer, - player: ServerPlayerEntity, - handler: ServerPlayNetworkHandler, - buf: PacketByteBuf, - sender: PacketSender - ) { - if (!Permissions.check(player, "ledger.networking", CommandConsts.PERMISSION_LEVEL) || - !Permissions.check(player, "ledger.commands.search", CommandConsts.PERMISSION_LEVEL) - ) { - ResponsePacket.sendResponse( - ResponseContent(LedgerPacketTypes.SEARCH.id, ResponseCodes.NO_PERMISSION.code), - sender - ) - return - } - val source = player.commandSource - val input = buf.readString() - val params = SearchParamArgument.get(input, source) - - val pages = buf.readInt() - - if (params.isEmpty()) { - ResponsePacket.sendResponse( - ResponseContent(LedgerPacketTypes.SEARCH.id, ResponseCodes.ERROR.code), - sender - ) - return - } - - ResponsePacket.sendResponse( - ResponseContent(LedgerPacketTypes.SEARCH.id, ResponseCodes.EXECUTING.code), - sender - ) - - Ledger.launch { - Ledger.searchCache[source.name] = params - - MessageUtils.warnBusy(source) - val results = DatabaseManager.searchActions(params, 1) - - for (i in 1..pages) { - val page = DatabaseManager.searchActions(results.searchParams, i) - MessageUtils.sendSearchResults( - source, - page, - Text.translatable( - "text.ledger.header.search" - ).setStyle(TextColorPallet.primary) - ) - } - - ResponsePacket.sendResponse( - ResponseContent(LedgerPacketTypes.SEARCH.id, ResponseCodes.COMPLETED.code), - sender - ) - } - } -} diff --git a/src/main/kotlin/com/github/quiltservertools/ledger/network/packet/response/ResponsePacket.kt b/src/main/kotlin/com/github/quiltservertools/ledger/network/packet/response/ResponsePacket.kt deleted file mode 100644 index a3b8fabf..00000000 --- a/src/main/kotlin/com/github/quiltservertools/ledger/network/packet/response/ResponsePacket.kt +++ /dev/null @@ -1,27 +0,0 @@ -package com.github.quiltservertools.ledger.network.packet.response - -import com.github.quiltservertools.ledger.network.packet.LedgerPacket -import com.github.quiltservertools.ledger.network.packet.LedgerPacketTypes -import net.fabricmc.fabric.api.networking.v1.PacketByteBufs -import net.fabricmc.fabric.api.networking.v1.PacketSender -import net.minecraft.network.PacketByteBuf -import net.minecraft.util.Identifier - -class ResponsePacket : LedgerPacket { - override var buf: PacketByteBuf = PacketByteBufs.create() - override val channel: Identifier = LedgerPacketTypes.RESPONSE.id - override fun populate(content: ResponseContent) { - // Packet type, rollback response would be `ledger.rollback` - buf.writeIdentifier(content.type) - // Response code - buf.writeInt(content.response) - } - - companion object { - fun sendResponse(content: ResponseContent, sender: PacketSender) { - val response = ResponsePacket() - response.populate(content) - sender.sendPacket(LedgerPacketTypes.RESPONSE.id, response.buf) - } - } -} diff --git a/src/main/kotlin/com/github/quiltservertools/ledger/network/packet/response/ResponseS2CPacket.kt b/src/main/kotlin/com/github/quiltservertools/ledger/network/packet/response/ResponseS2CPacket.kt new file mode 100644 index 00000000..a890cc06 --- /dev/null +++ b/src/main/kotlin/com/github/quiltservertools/ledger/network/packet/response/ResponseS2CPacket.kt @@ -0,0 +1,29 @@ +package com.github.quiltservertools.ledger.network.packet.response + +import com.github.quiltservertools.ledger.network.packet.LedgerPacketTypes +import net.fabricmc.fabric.api.networking.v1.PacketSender +import net.minecraft.network.PacketByteBuf +import net.minecraft.network.codec.PacketCodec +import net.minecraft.network.packet.CustomPayload + +data class ResponseS2CPacket(val content: ResponseContent) : CustomPayload { + fun write(buf: PacketByteBuf?) { + // Packet type, rollback response would be `ledger.rollback` + buf?.writeIdentifier(content.type) + // Response code + buf?.writeInt(content.response) + } + + override fun getId() = ID + + companion object { + val ID: CustomPayload.Id = CustomPayload.Id(LedgerPacketTypes.RESPONSE.id) + val CODEC: PacketCodec = CustomPayload.codecOf( + ResponseS2CPacket::write + ) { _: PacketByteBuf? -> TODO() } + + fun sendResponse(content: ResponseContent, sender: PacketSender) { + sender.sendPacket(ResponseS2CPacket(content)) + } + } +} diff --git a/src/main/kotlin/com/github/quiltservertools/ledger/utility/InspectionManager.kt b/src/main/kotlin/com/github/quiltservertools/ledger/utility/InspectionManager.kt index 63c89c8f..b771d3d6 100644 --- a/src/main/kotlin/com/github/quiltservertools/ledger/utility/InspectionManager.kt +++ b/src/main/kotlin/com/github/quiltservertools/ledger/utility/InspectionManager.kt @@ -4,7 +4,6 @@ import com.github.quiltservertools.ledger.Ledger import com.github.quiltservertools.ledger.actionutils.ActionSearchParams import com.github.quiltservertools.ledger.actionutils.SearchResults import com.github.quiltservertools.ledger.database.DatabaseManager -import java.util.* import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import net.minecraft.block.BedBlock @@ -22,6 +21,7 @@ import net.minecraft.util.Formatting import net.minecraft.util.math.BlockBox import net.minecraft.util.math.BlockPos import net.minecraft.util.math.Direction +import java.util.* private val inspectingUsers = HashSet() @@ -111,7 +111,9 @@ fun getOtherChestSide(state: BlockState, pos: BlockPos): BlockPos? { } else { pos.offset(facing.rotateClockwise(Direction.Axis.Y)) } - } else null + } else { + null + } } private fun getOtherDoorHalf(state: BlockState, pos: BlockPos): BlockPos { @@ -143,4 +145,3 @@ suspend fun PlayerEntity.getInspectResults(pos: BlockPos): SearchResults { MessageUtils.warnBusy(source) return DatabaseManager.searchActions(params, 1) } - diff --git a/src/main/kotlin/com/github/quiltservertools/ledger/utility/MessageUtils.kt b/src/main/kotlin/com/github/quiltservertools/ledger/utility/MessageUtils.kt index 81823329..7dfc0413 100644 --- a/src/main/kotlin/com/github/quiltservertools/ledger/utility/MessageUtils.kt +++ b/src/main/kotlin/com/github/quiltservertools/ledger/utility/MessageUtils.kt @@ -5,7 +5,7 @@ import com.github.quiltservertools.ledger.actionutils.SearchResults import com.github.quiltservertools.ledger.config.SearchSpec import com.github.quiltservertools.ledger.database.DatabaseManager import com.github.quiltservertools.ledger.network.Networking.hasNetworking -import com.github.quiltservertools.ledger.network.packet.action.ActionPacket +import com.github.quiltservertools.ledger.network.packet.action.ActionS2CPacket import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking import net.minecraft.server.command.ServerCommandSource import net.minecraft.text.ClickEvent @@ -23,15 +23,12 @@ import kotlin.time.toKotlinDuration object MessageUtils { @OptIn(ExperimentalTime::class) suspend fun sendSearchResults(source: ServerCommandSource, results: SearchResults, header: Text) { - // If the player has a Ledger compatible client, we send results as action packets rather than as chat messages if (source.hasPlayer() && source.playerOrThrow.hasNetworking()) { for (n in results.page..results.pages) { val networkResults = DatabaseManager.searchActions(results.searchParams, n) networkResults.actions.forEach { - val packet = ActionPacket() - packet.populate(it) - ServerPlayNetworking.send(source.player, packet.channel, packet.buf) + ServerPlayNetworking.send(source.player, ActionS2CPacket(it)) } } return @@ -40,7 +37,7 @@ object MessageUtils { source.sendFeedback({ header }, false) results.actions.forEach { actionType -> - source.sendFeedback({ actionType.getMessage() }, false) + source.sendFeedback({ actionType.getMessage(source) }, false) } source.sendFeedback( diff --git a/src/main/kotlin/com/github/quiltservertools/ledger/utility/NbtUtils.kt b/src/main/kotlin/com/github/quiltservertools/ledger/utility/NbtUtils.kt index 56743d53..47ec4548 100644 --- a/src/main/kotlin/com/github/quiltservertools/ledger/utility/NbtUtils.kt +++ b/src/main/kotlin/com/github/quiltservertools/ledger/utility/NbtUtils.kt @@ -1,14 +1,23 @@ package com.github.quiltservertools.ledger.utility -import net.fabricmc.fabric.api.util.NbtType +import com.mojang.serialization.Dynamic import net.minecraft.block.BlockState +import net.minecraft.datafixer.Schemas +import net.minecraft.datafixer.TypeReferences import net.minecraft.item.ItemStack import net.minecraft.nbt.NbtCompound +import net.minecraft.nbt.NbtElement import net.minecraft.nbt.NbtHelper +import net.minecraft.nbt.NbtOps import net.minecraft.nbt.StringNbtReader import net.minecraft.registry.Registries +import net.minecraft.registry.RegistryWrapper import net.minecraft.util.Identifier +const val ITEM_NBT_DATA_VERSION = 3817 +const val ITEM_COMPONENTS_DATA_VERSION = 3825 + +const val COMPONENTS = "components" // ItemStack const val PROPERTIES = "Properties" // BlockState const val COUNT = "Count" // ItemStack const val TAG = "tag" // ItemStack @@ -18,7 +27,15 @@ object NbtUtils { fun blockStateToProperties(state: BlockState): NbtCompound? { val stateTag = NbtHelper.fromBlockState(state) if (state.block.defaultState == state) return null // Don't store default block state - return if (stateTag.contains(PROPERTIES, NbtType.COMPOUND)) stateTag.getCompound(PROPERTIES) else null + return if (stateTag.contains( + PROPERTIES, + NbtElement.COMPOUND_TYPE.toInt() + ) + ) { + stateTag.getCompound(PROPERTIES) + } else { + null + } } fun blockStateFromProperties(tag: NbtCompound, name: Identifier): BlockState { @@ -28,41 +45,30 @@ object NbtUtils { return NbtHelper.toBlockState(Registries.BLOCK.readOnlyWrapper, stateTag) } - fun itemToProperties(item: ItemStack): NbtCompound? { - val itemTag = NbtCompound() - - // Don't log the item count if there is only 1 item. The log itself indicates there must be at least 1 - if (item.count > 1) { - itemTag.putByte(COUNT, item.count.toByte()) - } - - if (item.nbt != null) { - itemTag.put(TAG, item.nbt) - } - return if (itemTag.isEmpty) null else itemTag - } - - fun itemFromProperties(tag: String?, name: Identifier): ItemStack { - val itemTag = NbtCompound() - - itemTag.putString("id", name.toString()) - if (tag == null) { - itemTag.putByte(COUNT, 1) - return ItemStack.fromNbt(itemTag) - } - - val tagNbt = StringNbtReader.parse(tag) - // Item was missing count tag. If it's been logged, it must have a single item - if (tagNbt.contains(COUNT)) { - itemTag.putByte(COUNT, tagNbt.getByte(COUNT)) + fun itemFromProperties(tag: String?, name: Identifier, registries: RegistryWrapper.WrapperLookup): ItemStack { + val extraDataTag = StringNbtReader.parse(tag ?: "{}") + var itemTag: NbtElement + if (extraDataTag.contains(COMPONENTS)) { + itemTag = extraDataTag } else { - itemTag.putByte(COUNT, 1) - } + itemTag = NbtCompound() + itemTag.putString("id", name.toString()) + if (extraDataTag.contains(COUNT)) { + itemTag.putByte(COUNT, extraDataTag.getByte(COUNT)) + } else { + itemTag.putByte(COUNT, 1) + } + + if (extraDataTag.contains(TAG)) { + itemTag.put(TAG, extraDataTag.getCompound(TAG)) - if (tagNbt.contains(TAG)) { - itemTag.put(TAG, tagNbt.getCompound(TAG)) + itemTag = Schemas.getFixer().update( + TypeReferences.ITEM_STACK, + Dynamic(NbtOps.INSTANCE, itemTag), ITEM_NBT_DATA_VERSION, ITEM_COMPONENTS_DATA_VERSION + ).cast(NbtOps.INSTANCE) + } } - return ItemStack.fromNbt(itemTag) + return ItemStack.fromNbt(registries, itemTag).get() } } diff --git a/src/main/kotlin/com/github/quiltservertools/ledger/utility/Negatable.kt b/src/main/kotlin/com/github/quiltservertools/ledger/utility/Negatable.kt index 8cb7d3af..73a9af6f 100644 --- a/src/main/kotlin/com/github/quiltservertools/ledger/utility/Negatable.kt +++ b/src/main/kotlin/com/github/quiltservertools/ledger/utility/Negatable.kt @@ -4,6 +4,7 @@ data class Negatable (val property: T, val allowed: Boolean) { companion object { @JvmStatic fun allow(value: U) = Negatable(value, true) + @JvmStatic fun deny(value: U) = Negatable(value, false) } diff --git a/src/main/kotlin/com/github/quiltservertools/ledger/utility/PlayerResult.kt b/src/main/kotlin/com/github/quiltservertools/ledger/utility/PlayerResult.kt index 882faa54..3b2dc235 100644 --- a/src/main/kotlin/com/github/quiltservertools/ledger/utility/PlayerResult.kt +++ b/src/main/kotlin/com/github/quiltservertools/ledger/utility/PlayerResult.kt @@ -17,6 +17,11 @@ data class PlayerResult(val uuid: UUID, val name: String, val firstJoin: Instant } companion object { - fun fromRow(row: Tables.Player): PlayerResult = PlayerResult(row.playerId, row.playerName, row.firstJoin, row.lastJoin) + fun fromRow(row: Tables.Player): PlayerResult = PlayerResult( + row.playerId, + row.playerName, + row.firstJoin, + row.lastJoin + ) } } diff --git a/src/main/kotlin/com/github/quiltservertools/ledger/utility/TextColorPallet.kt b/src/main/kotlin/com/github/quiltservertools/ledger/utility/TextColorPallet.kt index 7f823aae..3c4c0c8d 100644 --- a/src/main/kotlin/com/github/quiltservertools/ledger/utility/TextColorPallet.kt +++ b/src/main/kotlin/com/github/quiltservertools/ledger/utility/TextColorPallet.kt @@ -11,10 +11,14 @@ object TextColorPallet { val primary: Style get() = Style.EMPTY.withColor(TextColor.parse(config[ColorSpec.primary]).getOrNull()) - val primaryVariant: Style get() = Style.EMPTY.withColor(TextColor.parse(config[ColorSpec.primaryVariant]).getOrNull()) + val primaryVariant: Style get() = Style.EMPTY.withColor( + TextColor.parse(config[ColorSpec.primaryVariant]).getOrNull() + ) val secondary: Style get() = Style.EMPTY.withColor(TextColor.parse(config[ColorSpec.secondary]).getOrNull()) - val secondaryVariant: Style get() = Style.EMPTY.withColor(TextColor.parse(config[ColorSpec.secondaryVariant]).getOrNull()) + val secondaryVariant: Style get() = Style.EMPTY.withColor( + TextColor.parse(config[ColorSpec.secondaryVariant]).getOrNull() + ) val light: Style get() = Style.EMPTY.withColor(TextColor.parse(config[ColorSpec.light]).getOrNull()) } -fun DataResult.getOrNull(): TextColor? = this.get().left().orElse(null) +fun DataResult.getOrNull(): TextColor? = this.result().orElse(null) diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index a1bf9687..567ca7d4 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -26,7 +26,7 @@ "ledger.mixins.json" ], "depends": { - "fabricloader": ">=0.15.0", + "fabricloader": ">=0.15.10", "fabric": ">=${fabricApi}", "fabric-language-kotlin": ">=${fabricKotlin}", "minecraft": ">=${minecraft}" @@ -34,4 +34,4 @@ "breaks": { "cardboard": "*" } -} \ No newline at end of file +} diff --git a/src/testmod/kotlin/com/github/quiltservertools/ledger/testmod/LedgerTest.kt b/src/testmod/kotlin/com/github/quiltservertools/ledger/testmod/LedgerTest.kt index 8b4bd5e3..85bf2f5b 100644 --- a/src/testmod/kotlin/com/github/quiltservertools/ledger/testmod/LedgerTest.kt +++ b/src/testmod/kotlin/com/github/quiltservertools/ledger/testmod/LedgerTest.kt @@ -1,18 +1,20 @@ package com.github.quiltservertools.ledger.testmod +import com.github.quiltservertools.ledger.testmod.commands.packet.ActionS2CPacket +import com.github.quiltservertools.ledger.testmod.commands.packet.HandshakeC2SPacket +import com.github.quiltservertools.ledger.testmod.commands.packet.HandshakeS2CPacket +import com.github.quiltservertools.ledger.testmod.commands.packet.InspectC2SPacket +import com.github.quiltservertools.ledger.testmod.commands.packet.SearchC2SPacket import com.github.quiltservertools.ledger.testmod.commands.registerCommands import net.fabricmc.api.ClientModInitializer import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback -import net.fabricmc.fabric.api.client.networking.v1.ClientPlayConnectionEvents import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking import net.fabricmc.fabric.api.event.player.PlayerBlockBreakEvents -import net.fabricmc.fabric.api.networking.v1.PacketByteBufs -import net.minecraft.nbt.NbtCompound +import net.fabricmc.fabric.api.networking.v1.PayloadTypeRegistry import net.minecraft.util.Identifier import net.minecraft.util.math.BlockPos import org.apache.logging.log4j.LogManager import org.apache.logging.log4j.Logger -import java.time.Instant object LedgerTest : ClientModInitializer { val HANDSHAKE = Identifier("ledger", "handshake") @@ -22,42 +24,15 @@ object LedgerTest : ClientModInitializer { val LOGGER: Logger = LogManager.getLogger("LedgerTestmod") override fun onInitializeClient() { - ClientPlayConnectionEvents.JOIN.register { handler, sender, client -> - // Create and send handshake packet - val tag = NbtCompound() - tag.putString("modid", "ledger-testmod") - tag.putString("version", "1.0.0") - tag.putInt("protocol_version", 1) - val buf = PacketByteBufs.create() - buf.writeNbt(tag) - sender.sendPacket(HANDSHAKE, buf) - } - - ClientPlayNetworking.registerGlobalReceiver(HANDSHAKE) { client, handler, buf, sender -> - val protocolVersion = buf.readInt() - val ledgerVersion = buf.readString() - val actionsLength = buf.readInt() - LOGGER.info("Protocol version: {}", protocolVersion) - LOGGER.info("Ledger version: {}", ledgerVersion) - LOGGER.info("Number of types registered: {}", actionsLength) - for (i in 0..actionsLength) { - LOGGER.info("Action type: {}", buf.readString()) - } - } + PayloadTypeRegistry.playC2S().register(HandshakeC2SPacket.ID, HandshakeC2SPacket.CODEC) + PayloadTypeRegistry.playC2S().register(SearchC2SPacket.ID, SearchC2SPacket.CODEC) + PayloadTypeRegistry.playC2S().register(InspectC2SPacket.ID, InspectC2SPacket.CODEC) - ClientPlayNetworking.registerGlobalReceiver(ACTION) { client, handler, buf, sender -> - val pos = buf.readBlockPos() - val id = buf.readString() - val world = buf.readIdentifier() - val oldObjectId = buf.readIdentifier() - val objectId = buf.readIdentifier() - val source = buf.readString() - val timestamp = Instant.ofEpochSecond(buf.readLong()) - val extraData = buf.readString() + PayloadTypeRegistry.playS2C().register(HandshakeS2CPacket.ID, HandshakeS2CPacket.CODEC) + PayloadTypeRegistry.playS2C().register(ActionS2CPacket.ID, ActionS2CPacket.CODEC) - LOGGER.info("pos={}, id={}, world={}, oldObjectId={}, objectId={}, source={}, timestamp={}, extraData={}", - pos, id, world, oldObjectId, objectId, source, timestamp, extraData) - } + ClientPlayNetworking.registerGlobalReceiver(HandshakeS2CPacket.ID, HandshakeS2CPacket) + ClientPlayNetworking.registerGlobalReceiver(ActionS2CPacket.ID, ActionS2CPacket) PlayerBlockBreakEvents.AFTER.register { world, player, pos, state, blockEntity -> inspectBlock(pos) @@ -69,14 +44,10 @@ object LedgerTest : ClientModInitializer { } fun inspectBlock(pos: BlockPos) { - val buf = PacketByteBufs.create() - buf.writeBlockPos(pos) - ClientPlayNetworking.send(INSPECT, buf) + ClientPlayNetworking.send(InspectC2SPacket(pos)) } fun sendSearchQuery(query: String) { - val buf = PacketByteBufs.create() - buf.writeString(query) - ClientPlayNetworking.send(SEARCH, buf) + ClientPlayNetworking.send(SearchC2SPacket(query)) } } diff --git a/src/testmod/kotlin/com/github/quiltservertools/ledger/testmod/commands/packet/ActionS2CPacket.kt b/src/testmod/kotlin/com/github/quiltservertools/ledger/testmod/commands/packet/ActionS2CPacket.kt new file mode 100644 index 00000000..d7c8f502 --- /dev/null +++ b/src/testmod/kotlin/com/github/quiltservertools/ledger/testmod/commands/packet/ActionS2CPacket.kt @@ -0,0 +1,58 @@ +package com.github.quiltservertools.ledger.testmod.commands.packet + + +import com.github.quiltservertools.ledger.testmod.LedgerTest +import java.time.Instant +import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking +import net.minecraft.network.PacketByteBuf +import net.minecraft.network.codec.PacketCodec +import net.minecraft.network.packet.CustomPayload +import net.minecraft.util.Identifier +import net.minecraft.util.math.BlockPos + +data class ActionS2CPacket( + val pos: BlockPos, + val id: String, + val world: Identifier, + val oldObjectId: Identifier, + val objectId: Identifier, + val source: String, + val timestamp: Instant, + val extraData: String +) : + CustomPayload { + + override fun getId() = ID + + companion object : ClientPlayNetworking.PlayPayloadHandler { + val ID: CustomPayload.Id = CustomPayload.Id(LedgerTest.ACTION) + val CODEC: PacketCodec = + CustomPayload.codecOf({ _, _ -> TODO() }, { + ActionS2CPacket( + it.readBlockPos(), + it.readString(), + it.readIdentifier(), + it.readIdentifier(), + it.readIdentifier(), + it.readString(), + Instant.ofEpochSecond(it.readLong()), + it.readString() + ) + }) + + override fun receive(payload: ActionS2CPacket, context: ClientPlayNetworking.Context?) { + LedgerTest.LOGGER.info( + "pos={}, id={}, world={}, oldObjectId={}, objectId={}, source={}, timestamp={}, extraData={}", + payload.pos, + payload.id, + payload.world, + payload.oldObjectId, + payload.objectId, + payload.source, + payload.timestamp, + payload.extraData + ) + } + } + +} diff --git a/src/testmod/kotlin/com/github/quiltservertools/ledger/testmod/commands/packet/HandshakeC2SPacket.kt b/src/testmod/kotlin/com/github/quiltservertools/ledger/testmod/commands/packet/HandshakeC2SPacket.kt new file mode 100644 index 00000000..ded3aa2f --- /dev/null +++ b/src/testmod/kotlin/com/github/quiltservertools/ledger/testmod/commands/packet/HandshakeC2SPacket.kt @@ -0,0 +1,24 @@ +package com.github.quiltservertools.ledger.testmod.commands.packet + + +import com.github.quiltservertools.ledger.testmod.LedgerTest +import net.minecraft.nbt.NbtCompound +import net.minecraft.network.PacketByteBuf +import net.minecraft.network.codec.PacketCodec +import net.minecraft.network.packet.CustomPayload + +data class HandshakeC2SPacket(val nbt: NbtCompound?) : CustomPayload { + + override fun getId() = ID + + private fun write(buf: PacketByteBuf?) { + buf?.writeNbt(nbt) + } + + companion object { + val ID: CustomPayload.Id = CustomPayload.Id(LedgerTest.HANDSHAKE) + val CODEC: PacketCodec = + CustomPayload.codecOf(HandshakeC2SPacket::write) { TODO() } + } + +} diff --git a/src/testmod/kotlin/com/github/quiltservertools/ledger/testmod/commands/packet/HandshakeS2CPacket.kt b/src/testmod/kotlin/com/github/quiltservertools/ledger/testmod/commands/packet/HandshakeS2CPacket.kt new file mode 100644 index 00000000..ca86fbd6 --- /dev/null +++ b/src/testmod/kotlin/com/github/quiltservertools/ledger/testmod/commands/packet/HandshakeS2CPacket.kt @@ -0,0 +1,39 @@ +package com.github.quiltservertools.ledger.testmod.commands.packet + + +import com.github.quiltservertools.ledger.testmod.LedgerTest +import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking +import net.minecraft.network.PacketByteBuf +import net.minecraft.network.codec.PacketCodec +import net.minecraft.network.packet.CustomPayload + +data class HandshakeS2CPacket(val protocolVersion: Int, val ledgerVersion: String, val actionTypes: Collection) : + CustomPayload { + + override fun getId() = ID + + companion object : ClientPlayNetworking.PlayPayloadHandler { + val ID: CustomPayload.Id = CustomPayload.Id(LedgerTest.HANDSHAKE) + val CODEC: PacketCodec = + CustomPayload.codecOf({ _, _ -> TODO() }, { + val protocolVersion = it.readInt() + val ledgerVersion = it.readString() + val actionsLength = it.readInt() + val actionTypes: MutableList = mutableListOf() + for (i in 0..actionsLength) { + actionTypes.add(it.readString()) + } + HandshakeS2CPacket(protocolVersion, ledgerVersion, actionTypes) + }) + + override fun receive(payload: HandshakeS2CPacket, context: ClientPlayNetworking.Context?) { + LedgerTest.LOGGER.info("Protocol version: {}", payload.protocolVersion) + LedgerTest.LOGGER.info("Ledger version: {}", payload.ledgerVersion) + LedgerTest.LOGGER.info("Number of types registered: {}", payload.actionTypes.size) + payload.actionTypes.forEach { + LedgerTest.LOGGER.info("Action type: {}", it) + } + } + } + +} diff --git a/src/testmod/kotlin/com/github/quiltservertools/ledger/testmod/commands/packet/InspectC2SPacket.kt b/src/testmod/kotlin/com/github/quiltservertools/ledger/testmod/commands/packet/InspectC2SPacket.kt new file mode 100644 index 00000000..b4af1461 --- /dev/null +++ b/src/testmod/kotlin/com/github/quiltservertools/ledger/testmod/commands/packet/InspectC2SPacket.kt @@ -0,0 +1,24 @@ +package com.github.quiltservertools.ledger.testmod.commands.packet + + +import com.github.quiltservertools.ledger.testmod.LedgerTest +import net.minecraft.network.PacketByteBuf +import net.minecraft.network.codec.PacketCodec +import net.minecraft.network.packet.CustomPayload +import net.minecraft.util.math.BlockPos + +data class InspectC2SPacket(val pos: BlockPos) : CustomPayload { + + override fun getId() = ID + + private fun write(buf: PacketByteBuf?) { + buf?.writeBlockPos(pos) + } + + companion object { + val ID: CustomPayload.Id = CustomPayload.Id(LedgerTest.INSPECT) + val CODEC: PacketCodec = + CustomPayload.codecOf(InspectC2SPacket::write) { TODO() } + } + +} diff --git a/src/testmod/kotlin/com/github/quiltservertools/ledger/testmod/commands/packet/SearchC2SPacket.kt b/src/testmod/kotlin/com/github/quiltservertools/ledger/testmod/commands/packet/SearchC2SPacket.kt new file mode 100644 index 00000000..db658aff --- /dev/null +++ b/src/testmod/kotlin/com/github/quiltservertools/ledger/testmod/commands/packet/SearchC2SPacket.kt @@ -0,0 +1,23 @@ +package com.github.quiltservertools.ledger.testmod.commands.packet + + +import com.github.quiltservertools.ledger.testmod.LedgerTest +import net.minecraft.network.PacketByteBuf +import net.minecraft.network.codec.PacketCodec +import net.minecraft.network.packet.CustomPayload + +data class SearchC2SPacket(val query: String) : CustomPayload { + + override fun getId() = ID + + private fun write(buf: PacketByteBuf?) { + buf?.writeString(query) + } + + companion object { + val ID: CustomPayload.Id = CustomPayload.Id(LedgerTest.SEARCH) + val CODEC: PacketCodec = + CustomPayload.codecOf(SearchC2SPacket::write) { TODO() } + } + +} From 0c0ebeceb8902e06619d25fa55ae4c1d2c5a31c3 Mon Sep 17 00:00:00 2001 From: dirtTW <31981880+yichifauzi@users.noreply.github.com> Date: Sun, 2 Jun 2024 05:32:57 +0700 Subject: [PATCH 7/7] Create zh_tw.json (#266) --- .../resources/data/ledger/lang/zh_tw.json | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 src/main/resources/data/ledger/lang/zh_tw.json diff --git a/src/main/resources/data/ledger/lang/zh_tw.json b/src/main/resources/data/ledger/lang/zh_tw.json new file mode 100644 index 00000000..de14709b --- /dev/null +++ b/src/main/resources/data/ledger/lang/zh_tw.json @@ -0,0 +1,54 @@ +{ + "text.ledger.header.search.pos": "--- 位於 %s 的紀錄---", + "text.ledger.header.search": "------ 記錄搜尋 ------", + "text.ledger.header.status": "------ Ledger ------", + + "text.ledger.footer.search": "------- %s [第 %s 頁 共 %s 頁] %s -------", + "text.ledger.footer.page_forward": ">>", + "text.ledger.footer.page_forward.hover": "下一頁", + "text.ledger.footer.page_backward": "<<", + "text.ledger.footer.page_backward.hover": "上一頁", + + "text.ledger.status.queue": "資料庫隊列狀態: %s ", + "text.ledger.status.queue.busy": "繁忙", + "text.ledger.status.queue.empty": "閒置", + "text.ledger.status.version": "版本: %s", + "text.ledger.status.discord": "單擊以加入 Ledger discord 伺服器", + "text.ledger.status.discord.join": "單擊以加入", + "text.ledger.status.wiki": "Wiki: %s", + "text.ledger.status.wiki.view": "單擊跳轉WIKI", + + "text.ledger.preview.start": "功能預覽", + + "text.ledger.action_message": "%1$s %2$s %3$s %4$s %5$s", + "text.ledger.action_message.time_diff": "%s ago", + "text.ledger.action_message.location.hover": "單擊傳送至此", + + "text.ledger.rollback.start": "正在回滾,共 %s 次更改", + "text.ledger.rollback.finish": "完成了指定規則內的回滾", + "text.ledger.rollback.fail": "回滾失敗 %s x%s", + + "text.ledger.restore.start": "正在還原 %s 次回溯更改", + "text.ledger.restore.finish": "完成了指定規則內的還原", + "text.ledger.restore.fail": "還原失敗 %s x%s", + + "text.ledger.inspect.toggle": "查詢模式: %s", + "text.ledger.inspect.on": "開啟", + "text.ledger.inspect.off": "關閉", + + "text.ledger.database.busy": "資料庫任務繁忙. 這可能需要一點時間", + + "error.ledger.no_cached_params": "沒有快取搜尋. 嘗試先執行搜尋", + "error.ledger.command.no_results": "沒有查詢到任何結果", + "error.ledger.no_more_pages": "沒有更多頁了", + "error.ledger.unknown_param": "非法參數--> %s", + "error.ledger.no_preview": "沒有可預覽的結果,預覽失敗", + + "text.ledger.action.block-place": "放置", + "text.ledger.action.block-break": "破壞", + "text.ledger.action.item-insert": "放入", + "text.ledger.action.item-remove": "拿取", + "text.ledger.action.entity-kill": "殺死", + + "text.ledger.network.protocols_mismatched": "協議版本不匹配: 用戶端協議版本 %d 服務端版本為 %d" +}