Added additional abstraction for better squad overview.
This commit is contained in:
parent
78b102dfbf
commit
72625833cd
1
.idea/misc.xml
generated
1
.idea/misc.xml
generated
@ -1,4 +1,3 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" project-jdk-name="17" project-jdk-type="JavaSDK">
|
||||
|
||||
@ -1,21 +1,48 @@
|
||||
object Css {
|
||||
val cssString = """
|
||||
.teamView{
|
||||
.teamView{
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
}
|
||||
.teamA{
|
||||
}
|
||||
.team{
|
||||
width: 50%;
|
||||
}
|
||||
.teamB{
|
||||
width: 50%;
|
||||
}
|
||||
.squadTable{
|
||||
margin: 6px;
|
||||
padding: 6px;
|
||||
}
|
||||
.colorBluFor{
|
||||
background-color: #bbffff;
|
||||
}
|
||||
.colorRedFor{
|
||||
background-color: #ffbbbb;
|
||||
}
|
||||
.squad{
|
||||
background-color: #00000020;
|
||||
margin: 6px;
|
||||
}
|
||||
.squadTable{
|
||||
width: 100%;
|
||||
}
|
||||
tr:nth-child(even) {
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
}
|
||||
.squadHeader{
|
||||
background-color: #00000050
|
||||
}
|
||||
.leader{
|
||||
background-color: #CD7F32
|
||||
}
|
||||
.playerClass{
|
||||
width: 15%;
|
||||
}
|
||||
.playerName{
|
||||
width: 35%;
|
||||
}
|
||||
.playerId{
|
||||
width: 35%;
|
||||
}
|
||||
.playerButtons{
|
||||
width: 15%;
|
||||
}
|
||||
tr:nth-child(even) {
|
||||
background-color: rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
""".trimIndent()
|
||||
}
|
||||
@ -74,8 +74,47 @@ fun main() {
|
||||
}
|
||||
get("/overview") {
|
||||
val players = abstraction.getCurrentPlayers()
|
||||
val squadInfo = abstraction.getSquadList()
|
||||
|
||||
call.respondHtmlTemplate(OverviewTemplate(players)) {}
|
||||
call.respondHtmlTemplate(OverviewTemplate(players, squadInfo)) {}
|
||||
}
|
||||
get("/overviewDemo") {
|
||||
//val players = abstraction.getCurrentPlayers()
|
||||
//val squadInfo = abstraction.getSquadList()
|
||||
val players = ListPlayersOutput(
|
||||
arrayListOf(
|
||||
Player(1, 86868686868686868L, "newSlMan", 1, 1, true, "SL"),
|
||||
Player(2, 31337313373133711L, "IStayed(TM)", 2, 1, true, "SL"),
|
||||
Player(1, 1L, "Man1", 1, 1, false, "RM"),
|
||||
Player(1, 2L, "Man2", 1, 1, false, "LAT"),
|
||||
Player(1, 3L, "Man3", 1, 1, false, "HAT"),
|
||||
Player(1, 4L, "Man4", 1, 1, false, "MED"),
|
||||
Player(1, 5L, "Man5", 1, 1, false, "GR"),
|
||||
Player(1, 6L, "OtherSL1", 2, 2, true, "SL"),
|
||||
Player(1, 7L, "OtherMan2", 2, 2, false, "MED"),
|
||||
Player(1, 8L, "OtherMan3", 2, 0, false, "RM"),
|
||||
Player(1, 9L, "OtherMan4", 2, 0, false, "RM"),
|
||||
Player(1, 10L, "OtherMan5", 2, 0, false, "RM"),
|
||||
), arrayListOf()
|
||||
)
|
||||
|
||||
val squadInfo = Pair(
|
||||
RconAbstraction.SquadListFaction(
|
||||
"1st Battalion, 1st Marines", hashMapOf(
|
||||
1 to RconAbstraction.SquadListSquad("HERPS", 5, true, "leaver9000", 69696969696969696L)
|
||||
)
|
||||
),
|
||||
RconAbstraction.SquadListFaction(
|
||||
"Insurgent Rebel Federation", hashMapOf(
|
||||
1 to RconAbstraction.SquadListSquad("DERPS", 1, true, "IStayed(TM)", 31337313373133711L),
|
||||
2 to RconAbstraction.SquadListSquad("NOOBS WELCOME", 2, false, "OtherSL1", 6L)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
call.respondHtmlTemplate(OverviewTemplate(players, squadInfo)) {
|
||||
|
||||
}
|
||||
}
|
||||
get("/css") {
|
||||
call.respondText(contentType = ContentType.Text.CSS, text = Css.cssString)
|
||||
|
||||
@ -1,7 +1,10 @@
|
||||
import io.ktor.server.html.*
|
||||
import kotlinx.html.*
|
||||
|
||||
class OverviewTemplate(private val players: ListPlayersOutput) : Template<HTML> {
|
||||
class OverviewTemplate(
|
||||
private val players: ListPlayersOutput,
|
||||
private val squadInfo: Pair<RconAbstraction.SquadListFaction, RconAbstraction.SquadListFaction>
|
||||
) : Template<HTML> {
|
||||
private fun TR.makePlayer(player: Player) {
|
||||
td { +player.role }
|
||||
td { +player.name }
|
||||
@ -11,7 +14,7 @@ class OverviewTemplate(private val players: ListPlayersOutput) : Template<HTML>
|
||||
+"✉"
|
||||
}
|
||||
button {//Kick
|
||||
+"\uD83E\uDDB6"
|
||||
+"⏏"
|
||||
}
|
||||
button {//Ban
|
||||
+"⛔"
|
||||
@ -19,17 +22,38 @@ class OverviewTemplate(private val players: ListPlayersOutput) : Template<HTML>
|
||||
}
|
||||
}
|
||||
|
||||
private fun FlowContent.makeSquad(squad: Map.Entry<Int, List<Player>>) {
|
||||
private fun FlowContent.makeSquad(
|
||||
squad: Map.Entry<Int, List<Player>>,
|
||||
squadListSquad: RconAbstraction.SquadListSquad
|
||||
) {
|
||||
val leader = squad.value.find { it.leader }
|
||||
+if (squad.key != 0) {
|
||||
"Squad ${squad.key}"
|
||||
div("squad") {
|
||||
div("squadHeader") {
|
||||
if (squad.key != 0) {
|
||||
+squadListSquad.name
|
||||
} else {
|
||||
"Unassigned"
|
||||
+"Unassigned"
|
||||
}
|
||||
|
||||
if (squadListSquad.locked) {
|
||||
+" \uD83D\uDD12"
|
||||
}
|
||||
|
||||
if (squadListSquad.creatorSteamId != (leader?.steamId ?: 0) && squadListSquad.creatorSteamId != 0L) {
|
||||
+" (originally created by ${squadListSquad.creatorName} ${squadListSquad.creatorSteamId})"
|
||||
}
|
||||
}
|
||||
|
||||
table("squadTable") {
|
||||
colGroup {
|
||||
col("playerClass")
|
||||
col("playerName")
|
||||
col("playerId")
|
||||
col("playerButtons")
|
||||
}
|
||||
leader?.let {
|
||||
thead {
|
||||
tr {
|
||||
tr("leader") {
|
||||
makePlayer(leader)
|
||||
}
|
||||
}
|
||||
@ -43,14 +67,23 @@ class OverviewTemplate(private val players: ListPlayersOutput) : Template<HTML>
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun FlowContent.makeSide(team: Map<Int, List<Player>>) {
|
||||
private fun FlowContent.makeSide(team: Map<Int, List<Player>>, squadListFaction: RconAbstraction.SquadListFaction) {
|
||||
div("teamHeader") {
|
||||
+squadListFaction.name
|
||||
}
|
||||
if (team.keys.isEmpty()) {
|
||||
+"empty"
|
||||
return
|
||||
}
|
||||
team.forEach {
|
||||
makeSquad(it)
|
||||
if (it.key != 0) {
|
||||
makeSquad(it, squadListFaction.squads[it.key]!!)
|
||||
}
|
||||
}
|
||||
team.filter { it.key == 0 }.forEach {
|
||||
makeSquad(it, RconAbstraction.SquadListSquad("Unassigned", it.value.size, false, "default", 0L))
|
||||
}
|
||||
}
|
||||
|
||||
@ -64,11 +97,11 @@ class OverviewTemplate(private val players: ListPlayersOutput) : Template<HTML>
|
||||
|
||||
body {
|
||||
div("teamView") {
|
||||
div("teamA") {
|
||||
makeSide(teamA)
|
||||
div("team colorRedFor") {
|
||||
makeSide(teamA, squadInfo.first)
|
||||
}
|
||||
div("teamB") {
|
||||
makeSide(teamB)
|
||||
div("team colorBluFor") {
|
||||
makeSide(teamB, squadInfo.second)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,11 +1,4 @@
|
||||
/*
|
||||
Format for "ListPlayers"
|
||||
----- Active Players -----
|
||||
ID: 0 | SteamID: 76561198037144702 | Name: [PACK] yenon | Team ID: 1 | Squad ID: N/A | Is Leader: False | Role: USA_Rifleman_01
|
||||
----- Recently Disconnected Players [Max of 15] -----
|
||||
ID: 1 | SteamID: 76561199074475884 | Since Disconnect: 03m.56s | Name: RoeveNn
|
||||
ID: 2 | SteamID: 76561199262966526 | Since Disconnect: 03m.51s | Name: Aliko
|
||||
*/
|
||||
|
||||
|
||||
data class ListPlayersOutput(val players: ArrayList<Player>, val disconnected: ArrayList<DisconnectedPlayer>)
|
||||
data class Player(
|
||||
@ -30,12 +23,19 @@ val inactivePlayerInListRegex = Regex(
|
||||
)
|
||||
|
||||
class RconAbstraction(private val connection: RconConnection) {
|
||||
|
||||
/*
|
||||
Format for "ListPlayers"
|
||||
----- Active Players -----
|
||||
ID: 0 | SteamID: 76561198037144702 | Name: [PACK] yenon | Team ID: 1 | Squad ID: N/A | Is Leader: False | Role: USA_Rifleman_01
|
||||
----- Recently Disconnected Players [Max of 15] -----
|
||||
ID: 1 | SteamID: 76561199074475884 | Since Disconnect: 03m.56s | Name: RoeveNn
|
||||
ID: 2 | SteamID: 76561199262966526 | Since Disconnect: 03m.51s | Name: Aliko
|
||||
*/
|
||||
suspend fun getCurrentPlayers(): ListPlayersOutput {
|
||||
val active = arrayListOf<Player>()
|
||||
val disconnected = arrayListOf<DisconnectedPlayer>()
|
||||
connection.sendCommand("ListPlayers").getOrNull()?.let {
|
||||
|
||||
println(it)
|
||||
activePlayerInListRegex.findAll(it).forEach { match ->
|
||||
val playerId = match.groupValues[1].toInt()
|
||||
val steamId = match.groupValues[2].toLong()
|
||||
@ -57,6 +57,60 @@ class RconAbstraction(private val connection: RconConnection) {
|
||||
return ListPlayersOutput(active, disconnected)
|
||||
}
|
||||
|
||||
/*
|
||||
----- Active Squads -----
|
||||
Team ID: 1 (3rd Division)
|
||||
ID: 1 | Name: HERPDERP2 THE RECONING | Size: 1 | Locked: True | Creator Name: yenon | Creator Steam ID: 76561198037144702
|
||||
Team ID: 2 (Insurgent Rebel Federation)
|
||||
*/
|
||||
|
||||
data class SquadListSquad(
|
||||
val name: String,
|
||||
val size: Int,
|
||||
val locked: Boolean,
|
||||
val creatorName: String,
|
||||
val creatorSteamId: Long
|
||||
)
|
||||
|
||||
data class SquadListFaction(val name: String, val squads: HashMap<Int, SquadListSquad>)
|
||||
|
||||
suspend fun getSquadList(): Pair<SquadListFaction, SquadListFaction> {
|
||||
val lines = connection.sendCommand("ListSquads").getOrNull()!!.split("\n")
|
||||
|
||||
val teamRegex = Regex("""^Team ID: ([12]) \(([^)]+)\)$""")
|
||||
val squadRegex =
|
||||
Regex("""^ID: (\d+) \| Name: (.*) \| Size: (\d+) \| Locked: (True|False) \| Creator Name: (.*) \| Creator Steam ID: (\d{17})${'$'}""")
|
||||
|
||||
lateinit var faction1: SquadListFaction
|
||||
lateinit var faction2: SquadListFaction
|
||||
|
||||
lateinit var currentFaction: SquadListFaction
|
||||
|
||||
lines.forEach { line ->
|
||||
teamRegex.find(line)?.let {
|
||||
if (it.groupValues[1].toInt() == 1) {
|
||||
faction1 = SquadListFaction(it.groupValues[2], hashMapOf())
|
||||
currentFaction = faction1
|
||||
} else {
|
||||
faction2 = SquadListFaction(it.groupValues[2], hashMapOf())
|
||||
currentFaction = faction2
|
||||
}
|
||||
}
|
||||
squadRegex.find(line)?.let {
|
||||
val squadId = it.groupValues[1].toInt()
|
||||
val name = it.groupValues[2]
|
||||
val size = it.groupValues[3].toInt()
|
||||
val locked = it.groupValues[4].lowercase().toBooleanStrict()
|
||||
val creatorName = it.groupValues[5]
|
||||
val creatorSteamId = it.groupValues[6].toLong()
|
||||
|
||||
currentFaction.squads[squadId] = SquadListSquad(name, size, locked, creatorName, creatorSteamId)
|
||||
}
|
||||
}
|
||||
|
||||
return Pair(faction1, faction2)
|
||||
}
|
||||
|
||||
suspend fun kickPlayer(steamId: Long, reason: String) {
|
||||
connection.sendCommand("AdminKickById $steamId \"$reason\"")
|
||||
}
|
||||
@ -66,6 +120,6 @@ class RconAbstraction(private val connection: RconConnection) {
|
||||
}
|
||||
|
||||
suspend fun messagePlayer(steamId: Long, message: String) {
|
||||
connection.sendCommand("AdminKickById $steamId \"$message\"")
|
||||
connection.sendCommand("AdminMessageById $steamId \"$message\"")
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user