Skip to content

Commit 8cd840e

Browse files
authored
[FIX] Instant in databse, renderers (#43)
## Changes - Fixed wrong timestamp in Exposed database - Improved souls renderers
1 parent 79340bf commit 8cd840e

File tree

28 files changed

+464
-254
lines changed

28 files changed

+464
-254
lines changed

docker-compose.yml

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
services:
2+
# For command call use `docker exec mc_docker_aspekt rcon-cli <your_command>`
3+
mc_docker_soulkeeper:
4+
restart: no
5+
container_name: mc_docker_soulkeeper
6+
image: itzg/minecraft-server # https://github.com/itzg/docker-minecraft-server
7+
tty: true
8+
stdin_open: true
9+
ports:
10+
- "25565:25565"
11+
environment:
12+
EULA: true
13+
ONLINE_MODE: FALSE
14+
# Forge --------------------
15+
# TYPE: FORGE
16+
# VERSION: "1.20.1"
17+
# FORGE_VERSION: "47.2.20"
18+
# Paper --------------------
19+
TYPE: PAPER
20+
VERSION: 1.21.4
21+
# Custom -------------------
22+
# CUSTOM_SERVER: https://api.papermc.io/v2/projects/paper/versions/1.21.1/builds/121/downloads/paper-1.21.1-121.jar
23+
volumes:
24+
# - ./build/forge:/data # Forge
25+
- ./build/bukkit:/data # Bukkit/Paper/Spigot
26+
# - ./build/velocity:/data # Velocity
27+
# - ./build/fabric:/data # Fabric

gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ makeevrserg.java.ktarget=21
1212
# Project
1313
makeevrserg.project.name=SoulKeeper
1414
makeevrserg.project.group=ru.astrainteractive.soulkeeper
15-
makeevrserg.project.version.string=0.2.12
15+
makeevrserg.project.version.string=0.3.0
1616
makeevrserg.project.description=Keep your items after death
1717
makeevrserg.project.developers=makeevrserg|Makeev Roman|makeevrserg@gmail.com
1818
makeevrserg.project.url=https://github.com/Astra-Interactive/SoulKeeper

instances/bukkit/build.gradle.kts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,9 @@ dependencies {
3434
implementation(projects.modules.dao)
3535
implementation(projects.modules.worker)
3636
}
37-
val destination = File("/run/media/makeevrserg/WDGOLD2TB/MinecraftServers/Servers/conf.smp/smp/plugins/")
37+
val destination = rootDir.resolve("build")
38+
.resolve("bukkit")
39+
.resolve("plugins")
3840
.takeIf(File::exists)
3941
?: File(rootDir, "jars")
4042

instances/bukkit/src/main/kotlin/ru/astrainteractive/soulkeeper/command/SoulsCommandRegistry.kt

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,11 @@ import ru.astrainteractive.soulkeeper.core.plugin.PluginTranslation
2525
import ru.astrainteractive.soulkeeper.module.souls.dao.SoulsDao
2626
import ru.astrainteractive.soulkeeper.module.souls.database.model.DatabaseSoul
2727
import ru.astrainteractive.soulkeeper.module.souls.io.model.Soul
28-
import ru.astrainteractive.soulkeeper.module.souls.worker.call.SoulCallRenderer
2928

3029
internal class SoulsCommandRegistry(
3130
private val plugin: JavaPlugin,
3231
private val scope: CoroutineScope,
3332
private val soulsDao: SoulsDao,
34-
private val soulCallRenderer: SoulCallRenderer,
3533
translationKrate: Krate<PluginTranslation>,
3634
kyoriKrate: Krate<KyoriComponentSerializer>
3735
) {
@@ -102,8 +100,6 @@ internal class SoulsCommandRegistry(
102100
soulsDao.updateSoul(soul.copy(isFree = true))
103101
.onSuccess {
104102
audience.sendMessage(translation.souls.soulFreed.component)
105-
soulCallRenderer.removeSoul(soul)
106-
soulCallRenderer.rememberSoul(soul)
107103
}
108104
.onFailure {
109105
audience.sendMessage(translation.souls.couldNotFreeSoul.component)

instances/bukkit/src/main/kotlin/ru/astrainteractive/soulkeeper/di/RootModule.kt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ interface RootModule {
2929
private val event = SoulEvents(
3030
soulsDao = soulsDaoModule.soulsDao,
3131
soulsConfigKrate = coreModule.soulsConfigKrate,
32-
soulCallRenderer = workerModule.soulCallRenderer
3332
)
3433

3534
private val soulsCommandRegistry = SoulsCommandRegistry(
@@ -38,7 +37,6 @@ interface RootModule {
3837
soulsDao = soulsDaoModule.soulsDao,
3938
kyoriKrate = coreModule.kyoriComponentSerializer,
4039
translationKrate = coreModule.translation,
41-
soulCallRenderer = workerModule.soulCallRenderer
4240
)
4341

4442
private val soulsReloadCommandRegistry = SoulsReloadCommandRegistry(

instances/bukkit/src/main/kotlin/ru/astrainteractive/soulkeeper/event/SoulEvents.kt

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,10 @@ import ru.astrainteractive.soulkeeper.core.util.playSoundForPlayer
1616
import ru.astrainteractive.soulkeeper.core.util.spawnParticleForPlayer
1717
import ru.astrainteractive.soulkeeper.module.souls.dao.SoulsDao
1818
import ru.astrainteractive.soulkeeper.module.souls.io.model.BukkitSoul
19-
import ru.astrainteractive.soulkeeper.module.souls.worker.call.SoulCallRenderer
2019
import java.time.Instant
2120

2221
internal class SoulEvents(
2322
private val soulsDao: SoulsDao,
24-
private val soulCallRenderer: SoulCallRenderer,
2523
soulsConfigKrate: Krate<SoulsConfig>
2624
) : EventListener {
2725
private val scope = CoroutineFeature.Default(Dispatchers.IO)
@@ -77,7 +75,6 @@ internal class SoulEvents(
7775
bukkitSoul.location.playSoundForPlayer(event.player, soulsConfig.sounds.soulDropped)
7876
scope.launch {
7977
soulsDao.insertSoul(bukkitSoul)
80-
.onSuccess { soul -> soulCallRenderer.rememberSoul(soul) }
8178
}
8279
}
8380

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package ru.astrainteractive.soulkeeper.core.util
2+
3+
import kotlinx.coroutines.flow.Flow
4+
import kotlinx.coroutines.flow.channelFlow
5+
import kotlinx.coroutines.launch
6+
7+
inline fun <reified T, R> combineInstantly(
8+
vararg flows: Flow<T>,
9+
crossinline transform: (Array<T?>) -> R
10+
): Flow<R> {
11+
return channelFlow {
12+
val array = arrayOfNulls<T>(flows.size)
13+
flows.forEachIndexed { index, flow ->
14+
launch {
15+
flow.collect {
16+
array[index] = it
17+
send(transform.invoke(array))
18+
}
19+
}
20+
}
21+
}
22+
}
23+
24+
inline fun <reified T1, reified T2, R> combineInstantly(
25+
flow: Flow<T1>,
26+
flow2: Flow<T2>,
27+
crossinline transform: (T1?, T2?) -> R,
28+
): Flow<R> {
29+
return combineInstantly(flow, flow2) { array ->
30+
transform(
31+
array[0] as? T1,
32+
array[1] as? T2
33+
)
34+
}
35+
}
36+
37+
inline fun <reified T1, reified T2, reified T3, R> combineInstantly(
38+
flow: Flow<T1>,
39+
flow2: Flow<T2>,
40+
flow3: Flow<T3>,
41+
crossinline transform: (T1?, T2?, T3?) -> R,
42+
): Flow<R> {
43+
return combineInstantly(flow, flow2, flow3) { array ->
44+
transform(
45+
array[0] as? T1,
46+
array[1] as? T2,
47+
array[2] as? T3
48+
)
49+
}
50+
}

modules/dao/src/main/kotlin/ru/astrainteractive/soulkeeper/module/souls/dao/SoulsDao.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
package ru.astrainteractive.soulkeeper.module.souls.dao
22

3+
import kotlinx.coroutines.flow.Flow
34
import org.bukkit.Location
45
import ru.astrainteractive.soulkeeper.module.souls.database.model.DatabaseSoul
56
import ru.astrainteractive.soulkeeper.module.souls.io.model.BukkitSoul
67
import ru.astrainteractive.soulkeeper.module.souls.io.model.Soul
78
import java.util.UUID
89

910
interface SoulsDao {
11+
fun getSoulsChangeFlow(): Flow<Unit>
12+
1013
suspend fun getSouls(): Result<List<DatabaseSoul>>
1114

1215
suspend fun getPlayerSouls(uuid: UUID): Result<List<DatabaseSoul>>

modules/dao/src/main/kotlin/ru/astrainteractive/soulkeeper/module/souls/dao/SoulsDaoImpl.kt

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package ru.astrainteractive.soulkeeper.module.souls.dao
22

33
import kotlinx.coroutines.flow.Flow
4+
import kotlinx.coroutines.flow.MutableSharedFlow
5+
import kotlinx.coroutines.flow.asSharedFlow
46
import kotlinx.coroutines.flow.first
57
import kotlinx.coroutines.sync.Mutex
68
import kotlinx.coroutines.sync.withLock
@@ -14,6 +16,7 @@ import org.jetbrains.exposed.sql.and
1416
import org.jetbrains.exposed.sql.andWhere
1517
import org.jetbrains.exposed.sql.deleteWhere
1618
import org.jetbrains.exposed.sql.insertAndGetId
19+
import org.jetbrains.exposed.sql.or
1720
import org.jetbrains.exposed.sql.selectAll
1821
import org.jetbrains.exposed.sql.transactions.transaction
1922
import org.jetbrains.exposed.sql.update
@@ -26,18 +29,24 @@ import ru.astrainteractive.soulkeeper.module.souls.io.model.BukkitSoul
2629
import ru.astrainteractive.soulkeeper.module.souls.io.model.Soul
2730
import java.util.UUID
2831

32+
@Suppress("TooManyFunctions")
2933
internal class SoulsDaoImpl(
3034
private val databaseFlow: Flow<Database>,
3135
private val soulFileEditor: BukkitSoulFile
3236
) : SoulsDao, Logger by JUtiltLogger("AspeKt-SoulsDaoImpl") {
3337
private val mutex = Mutex()
38+
private val soulsChangedSharedFlow = MutableSharedFlow<Unit>()
39+
40+
override fun getSoulsChangeFlow(): Flow<Unit> {
41+
return soulsChangedSharedFlow.asSharedFlow()
42+
}
3443

3544
private fun toDatabaseSoul(it: ResultRow): DatabaseSoul {
3645
return DatabaseSoul(
3746
id = it[SoulTable.id].value,
3847
ownerUUID = UUID.fromString(it[SoulTable.ownerUUID]),
3948
ownerLastName = it[SoulTable.ownerLastName],
40-
createdAt = it[SoulTable.created_at],
49+
createdAt = it[SoulTable.created_at] ?: it[SoulTable.broken_created_at],
4150
isFree = it[SoulTable.isFree],
4251
hasXp = it[SoulTable.hasXp],
4352
hasItems = it[SoulTable.hasItems],
@@ -59,6 +68,7 @@ internal class SoulsDaoImpl(
5968
mutex.withLock {
6069
transaction(databaseFlow.first()) {
6170
SoulTable.selectAll()
71+
.orderBy(SoulTable.broken_created_at to SortOrder.DESC)
6272
.orderBy(SoulTable.created_at to SortOrder.DESC)
6373
.map(::toDatabaseSoul)
6474
}
@@ -82,6 +92,7 @@ internal class SoulsDaoImpl(
8292
val id = SoulTable.insertAndGetId {
8393
it[SoulTable.ownerUUID] = soul.ownerUUID.toString()
8494
it[SoulTable.ownerLastName] = soul.ownerLastName
95+
it[SoulTable.broken_created_at] = soul.createdAt
8596
it[SoulTable.created_at] = soul.createdAt
8697
it[SoulTable.isFree] = soul.isFree
8798
it[SoulTable.locationWorld] = soul.location.world.name
@@ -99,7 +110,7 @@ internal class SoulsDaoImpl(
99110
.first()
100111
}
101112
}
102-
}.logFailure("insertSoul")
113+
}.logFailure("insertSoul").onSuccess { soulsChangedSharedFlow.emit(Unit) }
103114

104115
override suspend fun getSoulsNear(location: Location, radius: Int): Result<List<DatabaseSoul>> = runCatching {
105116
mutex.withLock {
@@ -137,21 +148,26 @@ internal class SoulsDaoImpl(
137148
soulFileEditor.delete(soul)
138149
transaction(databaseFlow.first()) {
139150
SoulTable.deleteWhere {
140-
SoulTable.created_at.eq(soul.createdAt)
141-
.and(SoulTable.ownerUUID.eq(soul.ownerUUID.toString()))
151+
SoulTable.ownerUUID.eq(soul.ownerUUID.toString()).and {
152+
SoulTable.broken_created_at.eq(soul.createdAt)
153+
.or(SoulTable.created_at.eq(soul.createdAt))
154+
}
142155
}
143156
}
144157
}
145158
Unit
146-
}.logFailure("deleteSoul")
159+
}.logFailure("deleteSoul").onSuccess { soulsChangedSharedFlow.emit(Unit) }
147160

148161
override suspend fun updateSoul(soul: Soul): Result<Unit> = runCatching {
149162
mutex.withLock {
150163
transaction(databaseFlow.first()) {
151164
SoulTable.update(
152165
where = {
153-
SoulTable.created_at.eq(soul.createdAt)
154-
.and(SoulTable.ownerUUID.eq(soul.ownerUUID.toString()))
166+
SoulTable.ownerUUID.eq(soul.ownerUUID.toString())
167+
.and {
168+
SoulTable.broken_created_at.eq(soul.createdAt)
169+
.or(SoulTable.created_at.eq(soul.createdAt))
170+
}
155171
},
156172
body = {
157173
it[SoulTable.isFree] = soul.isFree
@@ -162,12 +178,12 @@ internal class SoulsDaoImpl(
162178
}
163179
}
164180
Unit
165-
}.logFailure("deleteSoul")
181+
}.logFailure("deleteSoul").onSuccess { soulsChangedSharedFlow.emit(Unit) }
166182

167183
override suspend fun updateSoul(soul: BukkitSoul): Result<Unit> = runCatching {
168184
mutex.withLock { soulFileEditor.write(soul).getOrThrow() }
169185
updateSoul(soul = soul as Soul).getOrThrow()
170-
}.logFailure("deleteSoul")
186+
}.logFailure("deleteSoul").onSuccess { soulsChangedSharedFlow.emit(Unit) }
171187

172188
override suspend fun toItemStackSoul(soul: Soul): Result<BukkitSoul> {
173189
return soulFileEditor.read(soul)
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package ru.astrainteractive.soulkeeper.module.souls.database.coulmn
2+
3+
import org.jetbrains.exposed.sql.ColumnType
4+
import org.jetbrains.exposed.sql.vendors.currentDialect
5+
import java.time.Instant
6+
7+
internal class KJavaInstantColumnType : ColumnType<Instant>() {
8+
override fun sqlType(): String = currentDialect.dataTypeProvider.longType()
9+
10+
override fun valueFromDB(value: Any): Instant = when (value) {
11+
is Long -> Instant.ofEpochMilli(value)
12+
is Number -> Instant.ofEpochMilli(value.toLong())
13+
is String -> Instant.ofEpochMilli(value.toLong())
14+
else -> error("Unexpected value of type Long: $value of ${value::class.qualifiedName}")
15+
}
16+
17+
override fun valueToDB(value: Instant?): Any? {
18+
return value?.toEpochMilli()
19+
}
20+
21+
override fun valueToString(value: Instant?): String {
22+
return value?.toEpochMilli()?.toString().orEmpty()
23+
}
24+
25+
override fun nonNullValueToString(value: Instant): String {
26+
return value.toEpochMilli().toString()
27+
}
28+
}

0 commit comments

Comments
 (0)