visual-driver

Форк
0
224 строки · 9.9 Кб
1
@file:Suppress("UNCHECKED_CAST")
2

3
import data.FeatureUserStorage
4
import data.GraffitiPackStorage
5
import data.GraffitiUnitStorage
6
import kotlinx.coroutines.*
7
import kotlinx.coroutines.future.await
8
import me.func.protocol.graffiti.packet.GraffitiBuyPackage
9
import me.func.protocol.graffiti.packet.GraffitiLoadUserPackage
10
import me.func.protocol.graffiti.packet.GraffitiUsePackage
11
import me.func.protocol.personalization.FeatureUserData
12
import me.func.protocol.personalization.packet.StickersAvailablePackage
13
import ru.cristalix.core.microservice.MicroServicePlatform
14
import ru.cristalix.core.microservice.MicroserviceBootstrap
15
import ru.cristalix.core.network.Capability
16
import ru.cristalix.core.network.CorePackage
17
import ru.cristalix.core.network.ISocketClient
18
import ru.cristalix.core.network.packages.MoneyTransactionRequestPackage
19
import ru.cristalix.core.network.packages.MoneyTransactionResponsePackage
20
import ru.cristalix.core.realm.RealmId
21
import java.util.*
22
import kotlin.concurrent.thread
23

24
private val scope = CoroutineScope(Dispatchers.IO)
25
private lateinit var mongoAdapter: MongoAdapter
26

27
fun syncProfile(player: UUID, data: FeatureUserData? = null) = FeatureUserStorage(player, actualGraffitiPacks.values.map {
28
        GraffitiPackStorage(
29
            it.uuid,
30
            it.graffiti.map { GraffitiUnitStorage(it.uses, it.uuid) }.toMutableList()
31
        )
32
    }.toMutableList(), data?.activePack ?: 0, mutableListOf(), null)
33

34
fun main() {
35
    mongoAdapter = MongoAdapter(
36
        System.getenv("MONGO_URI"), System.getenv("MONGO_DB"), System.getenv("MONGO_COLLECTION")
37
    )
38

39
    MicroserviceBootstrap.bootstrap(MicroServicePlatform(2))
40

41
    ISocketClient.get().registerCapabilities(
42
        Capability.builder().className(GraffitiBuyPackage::class.java.name).notification(true).build(),
43
        Capability.builder().className(GraffitiUsePackage::class.java.name).notification(true).build(),
44
        Capability.builder().className(GraffitiLoadUserPackage::class.java.name).notification(true).build(),
45
        Capability.builder().className(StickersAvailablePackage::class.java.name).notification(true).build()
46
    )
47

48
    registerHandler<StickersAvailablePackage> { _, packet ->
49
        // Ответ серверу списком доступных стикеров
50
        packet.list = mutableListOf()
51
        // TODO: Тут пропущена логика
52
        ISocketClient.get().write(packet)
53
    }
54

55
    val standardProfile = FeatureUserData(
56
        UUID.randomUUID(), "", actualGraffitiPacks.values.toMutableList(), 0, mutableListOf(), null
57
    )
58

59
    registerHandler<GraffitiLoadUserPackage> { realm, packet ->
60
        // Загрузка профиля игрока
61
        scope.launch {
62
            loadProfile(packet.playerUuid) { data ->
63
                var update: Boolean
64

65
                // Если данные уже есть - обновляем набор паков, если нет - создаем новые
66
                packet.data = data?.let {
67
                    println("Loaded data for ${packet.playerUuid}.")
68
                    FeatureUserData(
69
                        it.uuid,
70
                        "",
71
                        it.packs.mapNotNull { it.toFullData() }.toMutableList().apply {
72
                            // Если не хватает новых паков - добавить и сохранить
73
                            val actual =
74
                                actualGraffitiPacks.values.filter { pack -> it.packs.none { it.uuid == pack.uuid } }
75
                            if (actual.isNotEmpty()) {
76
                                update = true
77
                                addAll(actual)
78
                            }
79
                        },
80
                        it.activePack,
81
                        it.stickers,
82
                        it.activeSticker
83
                    )
84
                } ?: standardProfile.apply {
85
                    uuid = packet.playerUuid
86
                    update = true
87
                }
88

89
                packet.data?.packs?.forEach {
90
                    it.graffiti.onEach { it.uses = 50 }
91
                }
92
                update = true
93

94
                // Если данные только что были сгенерированы - сохранить
95
                if (update) scope.launch { mongoAdapter.save(syncProfile(packet.playerUuid, packet.data)) }
96

97
                // Ответ серверу
98
                ISocketClient.get().write(packet)
99
                println("Wrote graffiti load to ${data?.uuid} from ${realm.realmName}.")
100
            }
101
        }
102
    }
103

104
    registerHandler<GraffitiBuyPackage> { realm, pckg ->
105
        // Загрузка профиля игрока
106
        scope.launch {
107
            loadProfile(pckg.playerUUID) { userData ->
108
                // Покупка граффити
109
                if (userData == null) {
110
                    ISocketClient.get().write(pckg)
111
                    println("Cannot buy pack! UserData is null, player uuid: ${pckg.playerUUID}.")
112
                } else {
113
                    // Если данные игрока успешно загружены
114
                    pckg.errorMessage = invoice(
115
                        pckg.playerUUID, pckg.price, "Покупка граффити ${pckg.packUUID}"
116
                    ).errorMessage
117

118
                    if (pckg.errorMessage.isNullOrEmpty()) {
119
                        // Если покупка прошла успешно
120
                        println("${pckg.playerUUID} payed ${pckg.price} for ${pckg.packUUID}!")
121

122
                        // Начисление граффити
123
                        actualGraffitiPacks[pckg.packUUID]?.apply {
124
                            // Если у игрока нет этого пака - добавить
125
                            if (userData.packs.none { it.uuid == this.uuid }) {
126
                                userData.packs.add(
127
                                    GraffitiPackStorage(
128
                                        uuid,
129
                                        graffiti.map { GraffitiUnitStorage(it.uses, it.uuid) }.toMutableList()
130
                                    )
131
                                )
132
                            }
133

134
                            // Выдача граффити
135
                            userData.packs.firstOrNull { uuid == it.uuid }?.data?.forEachIndexed { i, it -> it.uses += graffiti[i].address.maxUses }
136
                            println("${pckg.playerUUID} got ${pckg.packUUID} pack")
137
                        }
138

139
                        // Сохранение данных
140
                        async { mongoAdapter.save(userData) }.invokeOnCompletion {
141
                            if (it == null) println(
142
                                "Successful payment from ${realm.realmName}! ${pckg.playerUUID} bought pack ${
143
                                    pckg.packUUID
144
                                }"
145
                            ) else {
146
                                println("Payment save error")
147
                                it.printStackTrace()
148
                            }
149
                        }
150
                    }
151

152
                    // Отправка пакета назад
153
                    ISocketClient.get().write(pckg)
154
                }
155
            }
156
        }
157
    }
158

159
    registerHandler<GraffitiUsePackage> { realm, pckg ->
160
        // Загрузка профиля игрока
161
        scope.launch {
162
            loadProfile(pckg.playerUUID) { userData ->
163
                // Если данные игрока успешно загружены
164
                // Получение пака
165
                userData?.packs?.firstOrNull { it.uuid == pckg.packUUID }?.let { pack ->
166
                    // pack.data.firstOrNull { it.uuid == pckg.graffitiUUID && it.uses > 0 }?.let {
167
                    pack.data.firstOrNull { it.uuid == pckg.graffitiUUID }?.let {
168
                        // Разрешить ставить граффити если оно есть
169
                        pckg.success = true
170

171
                        // Вычесть игроку одну штуку
172
                        it.uses--
173

174
                        // Сохранить изменение
175
                        mongoAdapter.save(userData)
176
                        println("Player use graffiti from ${realm.realmName}! ${pckg.playerUUID} used ${pckg.packUUID}")
177
                    }
178
                }
179

180
                // Ответ серверу об игроке
181
                ISocketClient.get().write(pckg)
182
            }
183
        }
184
    }
185

186
    thread {
187
        while (true) {
188
            val line = readLine()
189
            if (line?.startsWith("give ") == true) {
190
                val uuid = UUID.fromString(line.drop(5))
191
                scope.launch {
192
                    loadProfile(uuid) { data ->
193
                        if (data != null) {
194
                            data.packs.forEach { pack ->
195
                                pack.data.forEach { unit ->
196
                                    unit.uses += 1000
197
                                }
198
                            }
199
                            mongoAdapter.save(data)
200
                            println("Done! $uuid get graffiti...")
201
                        } else {
202
                            println("Player not initialized!")
203
                        }
204
                    }
205
                }
206
            }
207
        }
208
    }
209
}
210

211
private suspend fun loadProfile(uuid: UUID, accept: suspend (FeatureUserStorage?) -> (Any)) =
212
    accept(mongoAdapter.find(uuid) ?: syncProfile(uuid))
213

214
private inline fun <reified T : CorePackage> registerHandler(noinline packageHandler: (RealmId, T) -> Unit) =
215
    ISocketClient.get().addListener(T::class.java, packageHandler)
216

217
private suspend fun invoice(user: UUID, price: Int, desc: String): MoneyTransactionResponsePackage =
218
    coroutineScope {
219
        async {
220
            ISocketClient.get().writeAndAwaitResponse<MoneyTransactionResponsePackage>(
221
                MoneyTransactionRequestPackage(user, price, true, desc)
222
            ).await()
223
        }
224
    }.await()
225

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.