Skip to content

Commit 2d788f5

Browse files
authored
Merge pull request #74 from Astra-Interactive/fix/logging
Fix/logging
2 parents d7f053e + ccbd20a commit 2d788f5

File tree

16 files changed

+331
-93
lines changed

16 files changed

+331
-93
lines changed

gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ makeevrserg.java.ktarget=21
1313
# Project
1414
makeevrserg.project.name=SoulKeeper
1515
makeevrserg.project.group=ru.astrainteractive.soulkeeper
16-
makeevrserg.project.version.string=1.2.9
16+
makeevrserg.project.version.string=1.2.10
1717
makeevrserg.project.description=Keep your items after death
1818
makeevrserg.project.developers=makeevrserg|Makeev Roman|[email protected]
1919
makeevrserg.project.url=https://github.com/Astra-Interactive/SoulKeeper

instances/bukkit/src/main/resources/plugin.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,5 @@ libraries:
1616
- "com.h2database:h2:2.4.240"
1717
commands:
1818
souls:
19-
skreload:
19+
skreload:
20+
soulkrate:

modules/command-bukkit/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ plugins {
55

66
dependencies {
77
compileOnly(libs.kotlin.coroutines.core)
8+
implementation(libs.kotlin.serialization.json)
89

910
implementation(libs.minecraft.astralibs.core)
1011
implementation(libs.minecraft.astralibs.core.bukkit)

modules/command-bukkit/src/main/kotlin/ru/astrainteractive/soulkeeper/command/di/CommandModule.kt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package ru.astrainteractive.soulkeeper.command.di
33
import ru.astrainteractive.astralibs.command.api.registrar.PaperCommandRegistrarContext
44
import ru.astrainteractive.astralibs.lifecycle.Lifecycle
55
import ru.astrainteractive.soulkeeper.command.reload.SoulsReloadCommandRegistrar
6+
import ru.astrainteractive.soulkeeper.command.soulkrate.SoulKrateCommandRegistrar
67
import ru.astrainteractive.soulkeeper.command.souls.SoulsCommandExecutor
78
import ru.astrainteractive.soulkeeper.command.souls.SoulsListCommandRegistrar
89
import ru.astrainteractive.soulkeeper.core.di.BukkitCoreModule
@@ -30,6 +31,12 @@ class CommandModule(
3031
kyoriKrate = coreModule.kyoriComponentSerializer
3132
)
3233
).register()
34+
SoulKrateCommandRegistrar(
35+
registrarContext = paperCommandRegistrar,
36+
stringFormat = coreModule.yamlFormat,
37+
dataFolder = coreModule.dataFolder,
38+
ioScope = coreModule.ioScope
39+
).register()
3340
SoulsReloadCommandRegistrar(
3441
plugin = bukkitCoreModule.plugin,
3542
translationKrate = coreModule.translation,
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
package ru.astrainteractive.soulkeeper.command.soulkrate
2+
3+
import com.mojang.brigadier.arguments.IntegerArgumentType
4+
import com.mojang.brigadier.arguments.LongArgumentType
5+
import com.mojang.brigadier.arguments.StringArgumentType
6+
import com.mojang.brigadier.tree.LiteralCommandNode
7+
import io.papermc.paper.command.brigadier.CommandSourceStack
8+
import kotlinx.coroutines.CoroutineScope
9+
import kotlinx.coroutines.launch
10+
import kotlinx.serialization.StringFormat
11+
import ru.astrainteractive.astralibs.command.api.registrar.PaperCommandRegistrarContext
12+
import ru.astrainteractive.astralibs.command.api.util.argument
13+
import ru.astrainteractive.astralibs.command.api.util.command
14+
import ru.astrainteractive.astralibs.command.api.util.requireArgument
15+
import ru.astrainteractive.astralibs.command.api.util.requirePermission
16+
import ru.astrainteractive.astralibs.command.api.util.requirePlayer
17+
import ru.astrainteractive.astralibs.command.api.util.runs
18+
import ru.astrainteractive.klibs.mikro.core.logging.JUtiltLogger
19+
import ru.astrainteractive.klibs.mikro.core.logging.Logger
20+
import ru.astrainteractive.soulkeeper.core.plugin.PluginPermission
21+
import ru.astrainteractive.soulkeeper.core.serialization.ItemStackSerializer
22+
import ru.astrainteractive.soulkeeper.core.serialization.ItemStackSerializer.decodeFromString
23+
import ru.astrainteractive.soulkeeper.module.souls.database.model.StringFormatObject
24+
import ru.astrainteractive.soulkeeper.module.souls.krate.PlayerSoulKrate
25+
import java.io.File
26+
import java.time.Instant
27+
import java.util.UUID
28+
29+
internal class SoulKrateCommandRegistrar(
30+
private val registrarContext: PaperCommandRegistrarContext,
31+
private val stringFormat: StringFormat,
32+
private val dataFolder: File,
33+
private val ioScope: CoroutineScope
34+
) : Logger by JUtiltLogger("SoulKrateCommandRegistrar") {
35+
private fun createNode(): LiteralCommandNode<CommandSourceStack> {
36+
return command("soulkrate") {
37+
argument("uuid", StringArgumentType.string()) { uuidArg ->
38+
argument("instant", LongArgumentType.longArg()) { instantArg ->
39+
argument("index", IntegerArgumentType.integer()) { indexArg ->
40+
runs { ctx ->
41+
ctx.requirePermission(PluginPermission.LoadSouls)
42+
val player = ctx.requirePlayer()
43+
val instant = ctx.requireArgument(instantArg).let(Instant::ofEpochSecond)
44+
val index = ctx.requireArgument(indexArg)
45+
val uuid = ctx.requireArgument(uuidArg).let(UUID::fromString)
46+
ioScope.launch {
47+
val soul = PlayerSoulKrate(
48+
stringFormat = stringFormat,
49+
dataFolder = dataFolder,
50+
createdAt = instant,
51+
ownerUUID = uuid,
52+
readIndex = index
53+
).getValue()
54+
val items = soul?.items
55+
.orEmpty()
56+
.map(StringFormatObject::raw)
57+
.map(ItemStackSerializer::decodeFromString)
58+
.mapNotNull { itemStackResult ->
59+
itemStackResult
60+
.onFailure { error(it) { "Failed to deserialize item stack" } }
61+
.getOrNull()
62+
}
63+
player.inventory.addItem(*items.toTypedArray())
64+
}
65+
}
66+
}
67+
}
68+
}
69+
}.build()
70+
}
71+
72+
fun register() {
73+
registrarContext.registerWhenReady(createNode())
74+
}
75+
}

modules/core/src/main/kotlin/ru/astrainteractive/soulkeeper/core/plugin/PluginPermission.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,5 @@ sealed class PluginPermission(override val value: String) : Permission {
77
data object ViewAllSouls : PluginPermission("soulkeeper.all")
88
data object FreeAllSouls : PluginPermission("soulkeeper.free.all")
99
data object TeleportToSouls : PluginPermission("soulkeeper.teleport")
10+
data object LoadSouls : PluginPermission("soulkeeper.load")
1011
}

modules/dao/build.gradle.kts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
plugins {
22
kotlin("jvm")
3+
kotlin("plugin.serialization")
34
}
45

56
dependencies {
@@ -8,8 +9,10 @@ dependencies {
89
implementation(libs.exposed.dao)
910
implementation(libs.exposed.jdbc)
1011
implementation(libs.exposed.java.time)
12+
implementation(libs.kotlin.serialization.json)
1113
// AstraLibs
1214
implementation(libs.minecraft.astralibs.core)
1315
implementation(libs.klibs.mikro.extensions)
1416
implementation(libs.klibs.mikro.core)
17+
implementation(libs.klibs.kstorage)
1518
}

modules/dao/src/main/kotlin/ru/astrainteractive/soulkeeper/module/souls/database/model/DefaultSoul.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,18 @@
11
package ru.astrainteractive.soulkeeper.module.souls.database.model
22

3+
import kotlinx.serialization.Serializable
34
import ru.astrainteractive.astralibs.server.location.Location
5+
import ru.astrainteractive.klibs.mikro.extensions.serialization.JInstantSerializer
6+
import ru.astrainteractive.klibs.mikro.extensions.serialization.UUIDSerializer
47
import java.time.Instant
58
import java.util.UUID
69

10+
@Serializable
711
data class DefaultSoul(
12+
@Serializable(with = UUIDSerializer::class)
813
override val ownerUUID: UUID,
914
override val ownerLastName: String,
15+
@Serializable(with = JInstantSerializer::class)
1016
override val createdAt: Instant,
1117
override val isFree: Boolean,
1218
override val location: Location,
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
11
package ru.astrainteractive.soulkeeper.module.souls.database.model
22

3+
import kotlinx.serialization.Serializable
4+
5+
@Serializable
36
data class StringFormatObject(val raw: String)
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
package ru.astrainteractive.soulkeeper.module.souls.krate
2+
3+
import kotlinx.serialization.StringFormat
4+
import ru.astrainteractive.astralibs.util.parse
5+
import ru.astrainteractive.astralibs.util.writeIntoFile
6+
import ru.astrainteractive.klibs.kstorage.suspend.SuspendMutableKrate
7+
import ru.astrainteractive.klibs.kstorage.suspend.impl.DefaultSuspendMutableKrate
8+
import ru.astrainteractive.klibs.mikro.core.logging.JUtiltLogger
9+
import ru.astrainteractive.klibs.mikro.core.logging.Logger
10+
import ru.astrainteractive.soulkeeper.module.souls.database.model.DefaultSoul
11+
import java.io.File
12+
import java.time.Instant
13+
import java.util.UUID
14+
15+
class PlayerSoulKrate(
16+
stringFormat: StringFormat,
17+
private val dataFolder: File,
18+
private val createdAt: Instant,
19+
private val ownerUUID: UUID,
20+
private val readIndex: Int = 0
21+
) : SuspendMutableKrate<DefaultSoul?>, Logger by JUtiltLogger("SoulKeeper-PlayerSoulKrate") {
22+
private fun createFile(): File {
23+
val parentDir = dataFolder.resolve("$ownerUUID")
24+
parentDir.mkdirs()
25+
26+
var index = 0
27+
var file: File
28+
do {
29+
file = parentDir.resolve("${createdAt.epochSecond}_$index.yml")
30+
index++
31+
} while (file.exists())
32+
file.createNewFile()
33+
return file
34+
}
35+
36+
private val krate = DefaultSuspendMutableKrate(
37+
factory = { null },
38+
loader = {
39+
val file = dataFolder
40+
.resolve("$ownerUUID")
41+
.resolve("${createdAt.epochSecond}_$readIndex.yml")
42+
stringFormat.parse<DefaultSoul>(file)
43+
.onFailure { error(it) { "Failed to load soul for $ownerUUID" } }
44+
.getOrNull()
45+
},
46+
saver = saver@{ defaultSoul ->
47+
val file = createFile()
48+
if (defaultSoul == null) {
49+
file.renameTo(file.resolveSibling("${file.nameWithoutExtension}.deleted"))
50+
return@saver
51+
}
52+
stringFormat.writeIntoFile(defaultSoul, file)
53+
}
54+
)
55+
56+
override suspend fun save(value: DefaultSoul?) {
57+
krate.save(value)
58+
}
59+
60+
override suspend fun reset() {
61+
krate.reset()
62+
}
63+
64+
override suspend fun getValue(): DefaultSoul? {
65+
return krate.getValue()
66+
}
67+
}

0 commit comments

Comments
 (0)