Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RPC #4

Merged
merged 1 commit into from
Sep 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ repositories {
maven("https://repo.sk1er.club/repository/maven-public/")
maven("https://repo.sk1er.club/repository/maven-releases/")
maven("https://repo.spongepowered.org/maven/")
maven("https://maven.teamresourceful.com/repository/maven-public/")
}

dependencies {
Expand All @@ -39,7 +40,18 @@ dependencies {
implementation(shade("org.spongepowered:mixin:0.7.11-SNAPSHOT") {
isTransitive = false
})
implementation(shade("com.jagrosh:DiscordIPC:0.5.3") {
exclude(module = "log4j")
because("Different version conflicts with Minecraft's Log4J")
exclude(module = "gson")
because("Different version conflicts with Minecraft's Gson")
})

implementation(kotlin("stdlib"))
}

tasks {
fatJar {
relocate("com.jagrosh.discordipc", "gay.j10a1n15.sillygames.deps.discordipc")
}
}
3 changes: 3 additions & 0 deletions src/main/kotlin/gay/j10a1n15/sillygames/SillyGames.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package gay.j10a1n15.sillygames

import gay.j10a1n15.sillygames.commands.CommandManager
import gay.j10a1n15.sillygames.events.EventHandler
import gay.j10a1n15.sillygames.rpc.RpcManager
import gay.j10a1n15.sillygames.screens.PictureInPicture
import net.minecraftforge.common.MinecraftForge
import net.minecraftforge.fml.common.Mod
Expand Down Expand Up @@ -32,5 +33,7 @@ class SillyGames {
).forEach {
MinecraftForge.EVENT_BUS.register(it)
}

RpcManager.start()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,13 @@ package gay.j10a1n15.sillygames.games

import gay.j10a1n15.sillygames.events.Events

object GameEventManager {
object GameManager {

private var game: Game? = null
var game: Game? = null

init {
Events.TICK.register { game?.onTick() }
Events.KEYBOARD.register { game?.onKeyHeld(it) }
Events.KEYBOARD_DOWN.register { game?.onKeyPressed(it) }
}

fun setGame(game: Game?) {
this.game = game
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package gay.j10a1n15.sillygames.games.wordle

import gay.j10a1n15.sillygames.games.Game
import gay.j10a1n15.sillygames.rpc.RpcProvider
import gg.essential.elementa.UIComponent
import gg.essential.elementa.components.UIBlock
import gg.essential.elementa.components.UIContainer
Expand Down Expand Up @@ -34,7 +35,7 @@ private const val KEYBOARD_SPACING = 5
private const val ROWS = 6
private const val COLS = 5

class Wordle : Game() {
class Wordle : Game(), RpcProvider {

private val state: WordleState = WordleState()
private var text: String = ""
Expand Down Expand Up @@ -272,4 +273,6 @@ class Wordle : Game() {
}

override val name = "Wordle"

override fun getRpcInfo() = this.state.getRpcInfo()
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
package gay.j10a1n15.sillygames.games.wordle

import gay.j10a1n15.sillygames.rpc.RpcInfo
import gay.j10a1n15.sillygames.rpc.RpcProvider
import gay.j10a1n15.sillygames.utils.SillyUtils.getKeyCodeName
import gay.j10a1n15.sillygames.utils.SillyUtils.replaceAt
import gg.essential.elementa.utils.invisible
import gg.essential.universal.UKeyboard
import java.awt.Color

class WordleState(private val wordIndexInput: Int? = null) {
class WordleState(private val wordIndexInput: Int? = null): RpcProvider {

private val letterKeys = setOf(
UKeyboard.KEY_A, UKeyboard.KEY_B, UKeyboard.KEY_C, UKeyboard.KEY_D, UKeyboard.KEY_E, UKeyboard.KEY_F,
Expand All @@ -24,6 +26,12 @@ class WordleState(private val wordIndexInput: Int? = null) {
var tries = 0
var reset = false

private val rpc = RpcInfo(
firstLine = "Wordle",
secondLine = "Guesses: ${tries}/6",
start = System.currentTimeMillis()
)

fun reset(wordIndex: Int? = null) {
word = wordIndex?.let { WordleWordList.getWord(it) } ?: WordleWordList.getWord()
this.wordIndex = wordIndex ?: WordleWordList.getIndex(word)
Expand All @@ -32,6 +40,7 @@ class WordleState(private val wordIndexInput: Int? = null) {
letters.clear()
tries = 0
reset = false
updateRpc()
}

fun enterChar(char: Char) {
Expand Down Expand Up @@ -92,6 +101,7 @@ class WordleState(private val wordIndexInput: Int? = null) {
}

tries++
updateRpc()
if (guess.lowercase() == word) {
reset = true
return "You won!\nWord Index: $wordIndex"
Expand All @@ -104,6 +114,10 @@ class WordleState(private val wordIndexInput: Int? = null) {

private fun isAllowed() = WordleWordList.isAllowed(guesses[tries])

private fun updateRpc() {
rpc.secondLine = "Guesses: ${tries}/6"
}

fun getKeyboardColor(letter: Char): Color {
if (!letters.containsKey(letter.lowercaseChar())) return WordlePalette.LIGHT_GRAY
return when (letters[letter.lowercaseChar()]) {
Expand All @@ -112,4 +126,6 @@ class WordleState(private val wordIndexInput: Int? = null) {
else -> WordlePalette.GRAY
}
}

override fun getRpcInfo() = rpc
}
12 changes: 12 additions & 0 deletions src/main/kotlin/gay/j10a1n15/sillygames/rpc/RpcInfo.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package gay.j10a1n15.sillygames.rpc

data class RpcInfo(
var firstLine: String,
var secondLine: String,

var start: Long,
var end: Long? = null,

var thumbnail: String? = null,
var icon: String? = null,
)
77 changes: 77 additions & 0 deletions src/main/kotlin/gay/j10a1n15/sillygames/rpc/RpcManager.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package gay.j10a1n15.sillygames.rpc

import com.google.gson.JsonObject
import com.jagrosh.discordipc.IPCClient
import com.jagrosh.discordipc.IPCListener
import com.jagrosh.discordipc.entities.RichPresence
import com.jagrosh.discordipc.entities.pipe.PipeStatus
import gay.j10a1n15.sillygames.games.GameManager
import gay.j10a1n15.sillygames.utils.Scheduling
import java.util.concurrent.CompletableFuture
import java.util.concurrent.ScheduledFuture
import kotlin.time.Duration
import kotlin.time.Duration.Companion.seconds

private const val CLIENT_ID = 1287128195124039715L

object RpcManager : IPCListener {

private var client: IPCClient? = null
private var lastInfo: RpcInfo? = null
private var scheduler: ScheduledFuture<*>? = null
private var started: Boolean = false

fun start() {
if (started) return
CompletableFuture.runAsync {
client = IPCClient(CLIENT_ID)
client?.setListener(this)
client?.connect()
}
}

fun stop() {
if (client?.status != PipeStatus.CONNECTED) return
CompletableFuture.runAsync {
close()
}
}

override fun onReady(client: IPCClient?) {
scheduler = Scheduling.schedule(Duration.ZERO, 1.seconds) {
val info = (GameManager.game as? RpcProvider)?.getRpcInfo()
if (info != lastInfo) {
lastInfo = info?.copy()
updatePresence()
}
}
}

override fun onClose(client: IPCClient?, json: JsonObject?) = close()
override fun onDisconnect(client: IPCClient?, t: Throwable?) = close()

private fun close() {
scheduler?.cancel(true)
scheduler = null
started = false
client = null
}

private fun updatePresence() {
val client = client ?: return
if (lastInfo == null) {
client.sendRichPresence(null)
} else {
val info = lastInfo!!
client.sendRichPresence(RichPresence.Builder().apply {
setDetails(info.firstLine)
setState(info.secondLine)
setStartTimestamp(info.start)
info.end?.let { setEndTimestamp(it) }
info.thumbnail?.let { setLargeImage(it) }
info.icon?.let { setSmallImage(it) }
}.build())
}
}

}
6 changes: 6 additions & 0 deletions src/main/kotlin/gay/j10a1n15/sillygames/rpc/RpcProvider.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package gay.j10a1n15.sillygames.rpc

interface RpcProvider {

fun getRpcInfo(): RpcInfo?
}
6 changes: 3 additions & 3 deletions src/main/kotlin/gay/j10a1n15/sillygames/screens/FullScreen.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package gay.j10a1n15.sillygames.screens

import gay.j10a1n15.sillygames.games.Game
import gay.j10a1n15.sillygames.games.GameEventManager
import gay.j10a1n15.sillygames.games.GameManager
import gg.essential.elementa.ElementaVersion
import gg.essential.elementa.WindowScreen
import gg.essential.elementa.components.UIBlock
Expand All @@ -20,7 +20,7 @@ class FullScreen(private val element: Game) : WindowScreen(
) {

init {
GameEventManager.setGame(element)
GameManager.game = element
}

private val container = UIBlock().constrain {
Expand Down Expand Up @@ -50,7 +50,7 @@ class FullScreen(private val element: Game) : WindowScreen(

override fun onScreenClose() {
super.onScreenClose()
GameEventManager.setGame(null)
GameManager.game = null
}

override fun updateGuiScale() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package gay.j10a1n15.sillygames.screens

import gay.j10a1n15.sillygames.events.Events
import gay.j10a1n15.sillygames.games.Game
import gay.j10a1n15.sillygames.games.GameEventManager
import gay.j10a1n15.sillygames.games.GameManager
import gay.j10a1n15.sillygames.games.Snake
import gg.essential.elementa.ElementaVersion
import gg.essential.elementa.WindowScreen
Expand Down Expand Up @@ -54,6 +54,6 @@ object PictureInPicture : WindowScreen(
}

private fun updateEventListeners() {
GameEventManager.setGame(if (visible) game else null)
GameManager.game = if (visible) game else null
}
}
29 changes: 29 additions & 0 deletions src/main/kotlin/gay/j10a1n15/sillygames/utils/Scheduling.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package gay.j10a1n15.sillygames.utils

import java.util.concurrent.Executors
import java.util.concurrent.ScheduledExecutorService
import java.util.concurrent.ScheduledFuture
import java.util.concurrent.TimeUnit
import java.util.concurrent.atomic.AtomicInteger
import kotlin.time.Duration
import kotlin.time.DurationUnit

object Scheduling {

private val counter = AtomicInteger(0)
private val scheduler: ScheduledExecutorService = Executors.newScheduledThreadPool(10) { target: Runnable? ->
Thread(target, "Scheduling-Thread-${counter.getAndIncrement()}")
}

fun schedule(time: Duration, runnable: () -> Unit): ScheduledFuture<*> = scheduler.schedule(
runnable,
time.toLong(DurationUnit.MILLISECONDS),
TimeUnit.MILLISECONDS,
)

fun schedule(initalDelay: Duration, delay: Duration, runnable: () -> Unit): ScheduledFuture<*> = scheduler.scheduleAtFixedRate(
runnable,
initalDelay.toLong(DurationUnit.MILLISECONDS),
delay.toLong(DurationUnit.MILLISECONDS), TimeUnit.MILLISECONDS,
)
}
Loading