This repository was archived by the owner on Dec 1, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathPlayer.kt
220 lines (197 loc) · 7.86 KB
/
Player.kt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
package com.jacobtread.relay.database.models
import com.jacobtread.relay.database.tables.GalaxyAtWarTable
import com.jacobtread.relay.database.tables.PlayerCharactersTable
import com.jacobtread.relay.database.tables.PlayerClassesTable
import com.jacobtread.relay.database.tables.PlayersTable
import com.jacobtread.relay.utils.MEStringParser
import com.jacobtread.relay.utils.comparePasswordHash
import com.jacobtread.relay.utils.generateRandomString
import kotlinx.serialization.Serializable
import java.util.concurrent.CompletableFuture as Future
@Serializable
data class Player(
/**
* The unique id for this player which uniquely identifies it amoungst
* all the players in the datbase
*/
val playerId: Int,
/**
* The email address used when created this account. In future this could be used
* to send out emails for password resets and such.
*/
val email: String,
/**
* The unique display name for this player. Currently, this
* is the first 99 chars of the email until a system for
* updating this is added.
*/
var displayName: String,
private val password: String,
private var sessionToken: String? = null,
/**
* The total number of usable credits that this player has
*/
var credits: Int = 0,
/**
* The total number of credits that this player has spent
*/
var creditsSpent: Int = 0,
/**
* The total number of games that this player has played
*/
var gamesPlayed: Int = 0,
/**
* The total number of seconds that this player has spent
* inside of games.
*/
var secondsPlayed: Long = 0,
/**
* List of values representing the amount/level of each
* inventory item this player has.
*/
var inventory: String = "",
var faceCodes: String? = null,
var newItem: String? = null,
/**
* The challenge reward banner to display behind the player profile
* see the known values listed in [com.jacobtread.relay.data.constants.ChallengeRewards]
*/
var csReward: Int = 0,
var completion: String? = null,
var progress: String? = null,
var cscompletion: String? = null,
var cstimestamps1: String? = null,
var cstimestamps2: String? = null,
var cstimestamps3: String? = null,
) {
fun getGalaxyAtWarData(): Future<GalaxyAtWarData> {
return GalaxyAtWarTable.getByPlayer(this)
.thenApply { value ->
value.applyDecay()
if (value.isModified) {
GalaxyAtWarTable.setByPlayer(this, value)
}
value
}
}
fun getSessionToken(): String {
var sessionToken = sessionToken
if (sessionToken == null) {
sessionToken = generateRandomString(128)
PlayersTable.setSessionToken(this, sessionToken)
}
return sessionToken
}
fun getNullableSessionToken(): String? = sessionToken
fun isSessionToken(token: String): Boolean {
return sessionToken != null && sessionToken == token
}
fun isMatchingPassword(password: String): Boolean {
return comparePasswordHash(password, this.password)
}
fun getTotalPromotions(): Future<Int> {
return PlayerClassesTable.getByPlayer(this)
.thenApply { clases -> clases.sumOf { it.promotions } }
}
fun getN7Rating(): Future<Int> {
return PlayerClassesTable.getByPlayer(this)
.thenApply { classes ->
var level = 0
var promotions = 0
classes.forEach {
level += it.level
promotions += it.promotions
}
level + promotions * 30
}
}
class SettingsMapLoader(private val player: Player) {
private val out = LinkedHashMap<String, String>()
fun load(): Future<Map<String, String>> {
val classesFuture = PlayerClassesTable.getByPlayer(player)
.thenApply { classes -> classes.forEach { out[it.getKey()] = it.toEncoded() } }
val charactersFuture = PlayerCharactersTable.getByPlayer(player)
.thenApply { characters -> characters.forEach { out[it.getKey()] = it.toEncoded() } }
val settingsBase = StringBuilder("20;4;")
.append(player.credits).append(";-1;0;")
.append(player.creditsSpent).append(";0;")
.append(player.gamesPlayed).append(';')
.append(player.secondsPlayed).append(";0;")
.append(player.inventory)
.toString()
return Future.allOf(classesFuture, charactersFuture)
.thenApply {
player.faceCodes?.apply { out["FaceCodes"] = this }
player.newItem?.apply { out["NewItem"] = this }
out["csreward"] = player.csReward.toString()
player.completion?.apply { out["Completion"] = this }
player.progress?.apply { out["Progress"] = this }
player.cscompletion?.apply { out["cscompletion"] = this }
player.cstimestamps1?.apply { out["cstimestamps"] = this }
player.cstimestamps2?.apply { out["cstimestamps2"] = this }
player.cstimestamps3?.apply { out["cstimestamps3"] = this }
out["Base"] = settingsBase
out
}
}
}
fun createSettingsMap(): Future<Map<String, String>> {
val loader = SettingsMapLoader(this)
return loader.load()
}
fun setPlayerDataBulk(map: Map<String, String>) {
val classes = ArrayList<PlayerClass>()
val characters = ArrayList<PlayerCharacter>()
map.forEach { (key, value) ->
if (key.startsWith("class")) {
val playerClass = PlayerClass.createFromKeyValue(key, value)
classes.add(playerClass)
} else if (key.startsWith("char")) {
val playerCharacter = PlayerCharacter.createFromKeyValue(key, value)
characters.add(playerCharacter)
} else {
setPlayerDataOther(key, value)
}
}
PlayersTable.setPlayerFully(this)
classes.forEach { PlayerClassesTable.setByPlayer(this, it) }
characters.forEach { PlayerCharactersTable.setByPlayer(this, it) }
}
private fun setPlayerDataOther(key: String, value: String) {
when (key) {
"Base" -> {
val parser = MEStringParser(value, 11)
credits = parser.int()
parser.skip(2) // Skip -1;0
creditsSpent = parser.int()
parser.skip(1)
gamesPlayed = parser.int()
secondsPlayed = parser.long()
parser.skip(1)
inventory = parser.str()
}
"FaceCodes" -> faceCodes = value
"NewItem" -> newItem = value
// (Possible name is Challenge Selected Reward)
"csreward" -> csReward = value.toIntOrNull() ?: 0
"Completion" -> completion = value
"Progress" -> progress = value
"cscompletion" -> cscompletion = value
"cstimestamps" -> cstimestamps1 = value
"cstimestamps2" -> cstimestamps2 = value
"cstimestamps3" -> cstimestamps3 = value
}
}
fun setPlayerData(key: String, value: String) {
if (key.startsWith("class")) {
val playerClass = PlayerClass.createFromKeyValue(key, value)
PlayerClassesTable.setByPlayer(this, playerClass)
} else if (key.startsWith("char")) {
val playerCharacter = PlayerCharacter.createFromKeyValue(key, value)
PlayerCharactersTable.setByPlayer(this, playerCharacter)
} else {
setPlayerDataOther(key, value)
PlayersTable.setPlayerPartial(this, key)
}
}
}