Skip to content

Commit 9b8a9a9

Browse files
committed
Refactored the discord module
1 parent 060a13b commit 9b8a9a9

File tree

10 files changed

+188
-104
lines changed

10 files changed

+188
-104
lines changed

common/src/main/java/com/lambda/mixin/world/ClientWorldMixin.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,12 @@
2323
import com.lambda.module.modules.render.WorldColors;
2424
import com.lambda.util.math.ColorKt;
2525
import net.minecraft.block.BlockState;
26+
import net.minecraft.client.network.ClientPlayNetworkHandler;
27+
import net.minecraft.client.render.WorldRenderer;
2628
import net.minecraft.client.world.ClientWorld;
2729
import net.minecraft.entity.Entity;
30+
import net.minecraft.registry.RegistryKey;
31+
import net.minecraft.registry.entry.RegistryEntry;
2832
import net.minecraft.util.math.BlockPos;
2933
import net.minecraft.util.math.Vec3d;
3034
import org.spongepowered.asm.mixin.Mixin;
@@ -33,8 +37,15 @@
3337
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
3438
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
3539

40+
import java.util.function.Supplier;
41+
3642
@Mixin(ClientWorld.class)
3743
public class ClientWorldMixin {
44+
@Inject(method = "<init>(Lnet/minecraft/client/network/ClientPlayNetworkHandler;Lnet/minecraft/client/world/ClientWorld$Properties;Lnet/minecraft/registry/RegistryKey;Lnet/minecraft/registry/entry/RegistryEntry;IILjava/util/function/Supplier;Lnet/minecraft/client/render/WorldRenderer;ZJ)V", at = @At("TAIL"))
45+
void constructorMixin(ClientPlayNetworkHandler networkHandler, ClientWorld.Properties properties, RegistryKey registryRef, RegistryEntry dimensionTypeEntry, int loadDistance, int simulationDistance, Supplier profiler, WorldRenderer worldRenderer, boolean debugWorld, long seed, CallbackInfo ci) {
46+
EventFlow.post(new WorldEvent.Join());
47+
}
48+
3849
@Inject(method = "addEntity", at = @At("HEAD"), cancellable = true)
3950
private void onAddEntity(Entity entity, CallbackInfo ci) {
4051
if (EventFlow.post(new EntityEvent.EntitySpawn(entity)).isCanceled()) ci.cancel();

common/src/main/kotlin/com/lambda/Lambda.kt

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@
1717

1818
package com.lambda
1919

20+
import com.github.kittinunf.fuel.Fuel
21+
import com.github.kittinunf.fuel.core.await
22+
import com.github.kittinunf.fuel.core.awaitResponse
23+
import com.github.kittinunf.fuel.core.awaitUnit
2024
import com.google.gson.Gson
2125
import com.google.gson.GsonBuilder
2226
import com.lambda.config.serializer.*
@@ -27,6 +31,7 @@ import com.lambda.core.Loader
2731
import com.lambda.gui.impl.clickgui.windows.tag.CustomModuleWindow
2832
import com.lambda.gui.impl.clickgui.windows.tag.TagWindow
2933
import com.lambda.module.tag.ModuleTag
34+
import com.lambda.threading.runConcurrent
3035
import com.lambda.util.KeyCode
3136
import com.mojang.authlib.GameProfile
3237
import com.mojang.blaze3d.systems.RenderSystem.recordRenderCall
@@ -38,7 +43,12 @@ import net.minecraft.util.math.BlockPos
3843
import org.apache.logging.log4j.LogManager
3944
import org.apache.logging.log4j.Logger
4045
import java.awt.Color
46+
import java.net.URI
47+
import java.net.http.HttpClient
48+
import java.net.http.HttpRequest
49+
import java.net.http.HttpResponse
4150
import java.util.*
51+
import java.util.concurrent.CountDownLatch
4252

4353

4454
object Lambda {
@@ -70,6 +80,39 @@ object Lambda {
7080
.create()
7181

7282
fun initialize(block: (Long) -> Unit) {
83+
runConcurrent {
84+
// Create an HttpClient
85+
val client = HttpClient.newHttpClient()
86+
87+
// Define the URI for the SSE stream
88+
val uri = URI.create("http://localhost:8080/api/v1/party/listen")
89+
90+
// Create an HttpRequest for the SSE stream
91+
val request = HttpRequest.newBuilder()
92+
.uri(uri)
93+
.header("Accept", "text/event-stream")
94+
.build()
95+
96+
// Create a CountDownLatch to wait for the events
97+
val latch = CountDownLatch(1)
98+
99+
// Send the request and handle the response asynchronously
100+
client.sendAsync(request, HttpResponse.BodyHandlers.ofLines())
101+
.thenAccept { response ->
102+
println("Connected to SSE stream")
103+
response.body().forEach { line ->
104+
if (line.startsWith("data:")) {
105+
val data = line.substring(5).trim()
106+
println("Received event data: $data")
107+
}
108+
}
109+
latch.countDown()
110+
}
111+
112+
// Wait until the response is received and handled
113+
latch.await()
114+
}
115+
73116
recordRenderCall {
74117
block(Loader.initialize())
75118
}

common/src/main/kotlin/com/lambda/command/commands/DiscordCommand.kt

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,21 +23,43 @@ import com.lambda.brigadier.argument.word
2323
import com.lambda.brigadier.execute
2424
import com.lambda.brigadier.required
2525
import com.lambda.command.LambdaCommand
26-
import com.lambda.module.modules.client.Discord
26+
import com.lambda.module.modules.client.Discord.partyCreate
27+
import com.lambda.module.modules.client.Discord.partyJoin
28+
import com.lambda.module.modules.client.Discord.partyLeave
2729
import com.lambda.module.modules.client.Discord.rpc
30+
import com.lambda.network.api.v1.endpoints.leaveParty
2831
import com.lambda.threading.runConcurrent
32+
import com.lambda.threading.runSafe
2933
import com.lambda.util.extension.CommandBuilder
3034

3135
object DiscordCommand : LambdaCommand(
3236
name = "discord",
3337
description = "Discord Rich Presence commands",
34-
usage = "rpc <join [id]>"
38+
usage = "rpc <create | leave | delete | join [id] | accept [user] | refuse [user]>"
3539
) {
3640
override fun CommandBuilder.create() {
41+
required(literal("create")) {
42+
execute {
43+
runSafe { partyCreate() }
44+
}
45+
}
46+
47+
required(literal("leave")) {
48+
execute {
49+
runSafe { partyLeave() }
50+
}
51+
}
52+
53+
required(literal("delete")) {
54+
execute {
55+
runSafe { partyCreate() }
56+
}
57+
}
58+
3759
required(literal("join")) {
3860
required(word("id")) { id ->
3961
execute {
40-
Discord.join(id().value())
62+
runSafe { partyJoin(id().value()) }
4163
}
4264
}
4365
}
@@ -57,11 +79,5 @@ object DiscordCommand : LambdaCommand(
5779
}
5880
}
5981
}
60-
61-
required(literal("create")) {
62-
execute {
63-
Discord.createParty()
64-
}
65-
}
6682
}
6783
}

common/src/main/kotlin/com/lambda/event/events/WorldEvent.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@ import net.minecraft.world.chunk.WorldChunk
3636
* occurrences in the game world.
3737
*/
3838
sealed class WorldEvent {
39+
// ToDo: Add doc
40+
// Represents the player joining the client world
41+
class Join() : Event
42+
3943
/**
4044
* Represents an event specific to chunk operations within the world.
4145
*

common/src/main/kotlin/com/lambda/module/modules/client/Discord.kt

Lines changed: 48 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -20,20 +20,22 @@ package com.lambda.module.modules.client
2020
import com.lambda.Lambda
2121
import com.lambda.context.SafeContext
2222
import com.lambda.event.EventFlow
23-
import com.lambda.event.events.ConnectionEvent
24-
import com.lambda.event.listener.UnsafeListener.Companion.listenUnsafeConcurrently
23+
import com.lambda.event.events.RenderEvent
24+
import com.lambda.event.events.WorldEvent
25+
import com.lambda.event.listener.SafeListener.Companion.listen
26+
import com.lambda.event.listener.SafeListener.Companion.listenConcurrently
2527
import com.lambda.network.api.v1.models.Party
2628
import com.lambda.module.Module
29+
import com.lambda.module.modules.client.Network.isDiscordLinked
2730
import com.lambda.module.modules.client.Network.updateToken
2831
import com.lambda.module.tag.ModuleTag
2932
import com.lambda.network.api.v1.endpoints.createParty
30-
import com.lambda.network.api.v1.endpoints.editParty
33+
import com.lambda.network.api.v1.endpoints.deleteParty
3134
import com.lambda.network.api.v1.endpoints.joinParty
3235
import com.lambda.network.api.v1.endpoints.leaveParty
3336
import com.lambda.network.api.v1.endpoints.linkDiscord
37+
import com.lambda.network.api.v1.endpoints.partyUpdates
3438
import com.lambda.threading.runConcurrent
35-
import com.lambda.threading.runSafe
36-
import com.lambda.util.Communication
3739
import com.lambda.util.Communication.toast
3840
import com.lambda.util.Communication.warn
3941
import com.lambda.util.Nameable
@@ -64,7 +66,6 @@ object Discord : Module(
6466

6567
/* Party settings */
6668
private val createByDefault by setting("Create By Default", true, description = "Create parties on") { page == Page.Party }
67-
private val maxPlayers by setting("Max Players", 10, 2..20) { page == Page.Party }.onValueChange { _, _ -> if (player.isPartyOwner) edit() } // ToDo: Avoid spam requests
6869

6970
val rpc = KDiscordIPC(Lambda.APP_ID, scope = EventFlow.lambdaScope)
7071

@@ -76,72 +77,72 @@ object Discord : Module(
7677
val PlayerEntity.isPartyOwner
7778
get() = uuid == currentParty?.leader?.uuid
7879

79-
val PlayerEntity.isInParty
80-
get() = currentParty?.players?.any { it.uuid == uuid }
80+
val PlayerEntity.isInParty: Boolean
81+
get() = currentParty?.players?.any { it.uuid == uuid } ?: false
8182

8283
init {
8384
rpc.subscribe()
8485

85-
listenUnsafeConcurrently<ConnectionEvent.Connect.Post> {
86-
// FixMe: We have to wait even though this is the last event until toSafe() != null
87-
// because of timing
88-
delay(3000)
89-
runSafe { handleLoop() }
90-
}
91-
92-
onEnable { runConcurrent { startDiscord(); handleLoop() } }
93-
onDisable { stopDiscord() }
94-
}
95-
96-
fun createParty() {
97-
if (discordAuth == null) return toast("Can not interact with the api (are you offline?)")
86+
// ToDo: Nametag for friends when ref/ui is merged
87+
// listen<RenderEvent.World>()
9888

99-
val (party, error) = createParty(maxPlayers, true)
100-
if (error != null) toast("Failed to create a party: ${error.message}", Communication.LogLevel.WARN)
89+
listenConcurrently<WorldEvent.Join> {
90+
// If the player is in a party and this most likely means that the `onEnable`
91+
// block ran and is already handling the activity
92+
if (player.isInParty) return@listenConcurrently
93+
handleLoop()
94+
}
10195

102-
currentParty = party
96+
onEnable { runConcurrent { start(); handleLoop() } }
97+
onDisable { stop() }
10398
}
10499

105100
/**
106-
* Joins a new party with the invitation ID
101+
* Creates a new party, leaves or delete the current party if there is one
107102
*/
108-
fun join(id: String) {
109-
if (discordAuth == null) return toast("Can not interact with the api (are you offline?)")
103+
fun SafeContext.partyCreate() {
104+
if (!isDiscordLinked) return warn("You did not link your discord account")
105+
if (!player.isInParty) {
106+
if (player.isPartyOwner) deleteParty() else leaveParty()
107+
return
108+
}
110109

111-
val (party, error) = joinParty(id)
112-
if (error != null) toast("Failed to join the party: ${error.message}", Communication.LogLevel.WARN)
110+
val (party, error) = createParty()
111+
if (error != null) warn("Failed to create a party: ${error.errorData}")
113112

114113
currentParty = party
114+
partyUpdates { currentParty = it }
115115
}
116116

117117
/**
118-
* Triggers a party edit request if you are the owner
118+
* Joins a new party with the invitation ID
119119
*/
120-
fun edit() {
121-
if (discordAuth == null) return toast("Can not interact with the api (are you offline?)")
120+
fun SafeContext.partyJoin(id: String) {
121+
if (!isDiscordLinked) return warn("You did not link your discord account")
122122

123-
val (party, error) = editParty(maxPlayers)
124-
if (error != null) toast("Failed to edit the party: ${error.message}", Communication.LogLevel.WARN)
123+
val (party, error) = joinParty(id)
124+
if (error != null) warn("Failed to join the party: ${error.errorData}")
125125

126126
currentParty = party
127+
partyUpdates { currentParty = it }
127128
}
128129

129130
/**
130131
* Leaves the current party
131132
*/
132-
fun leave() {
133-
if (discordAuth == null || currentParty == null) return toast("Can not interact with the api (are you offline?)")
133+
fun SafeContext.partyLeave() {
134+
if (!isDiscordLinked) return warn("You did not link your discord account")
135+
if (!player.isInParty) return warn("You are not in a party")
134136

135137
val (_, error) = leaveParty()
136-
if (error != null) return toast("Failed to edit the party: ${error.message}", Communication.LogLevel.WARN)
138+
if (error != null) return warn("Failed to leave the party: ${error.errorData}")
137139

138140
currentParty = null
139141
}
140142

141-
private suspend fun startDiscord() {
143+
private suspend fun start() {
142144
if (rpc.connected) return
143145

144-
rpc.subscribe()
145146
runConcurrent { rpc.connect() } // TODO: Create a function that will wait until x seconds has passed or if the connection is successful
146147
delay(1000)
147148

@@ -152,18 +153,15 @@ object Discord : Module(
152153
return toast("Failed to link the discord account to the minecraft auth")
153154
}
154155

155-
authResp?.let { updateToken(it) }
156+
updateToken(authResp)
156157
discordAuth = auth
157158
}
158159

159-
private fun stopDiscord() {
160-
if (!rpc.connected) return
161-
162-
rpc.disconnect()
160+
private fun stop() {
161+
if (rpc.connected) rpc.disconnect()
163162
}
164163

165164
private fun KDiscordIPC.subscribe() {
166-
// ToDO: Get party on join event
167165
on<ReadyEvent> {
168166
subscribe(DiscordEvent.VoiceChannelSelect)
169167
subscribe(DiscordEvent.VoiceStateCreate)
@@ -181,14 +179,17 @@ object Discord : Module(
181179
}
182180

183181
private suspend fun SafeContext.handleLoop() {
184-
if (createByDefault) createParty(maxPlayers)
182+
if (isDiscordLinked) {
183+
if (createByDefault) createParty()
184+
partyUpdates { currentParty = it }
185+
}
185186

186187
while (rpc.connected) {
187188
update()
188189
delay(delay)
189190
}
190191

191-
leave()
192+
if (isDiscordLinked) leaveParty()
192193
}
193194

194195
private suspend fun SafeContext.update() {
@@ -229,8 +230,6 @@ object Discord : Module(
229230
HEALTH({ "${mc.player?.health ?: 0} HP" }),
230231
HUNGER({ "${mc.player?.hungerManager?.foodLevel ?: 0} Hunger" }),
231232
DIMENSION({ dimensionName }),
232-
COORDINATES({ "Coords: ${player.blockPos.toShortString()}" }),
233-
SERVER({ mc.currentServerEntry?.address ?: "Not Connected" }),
234233
FPS({ "${mc.currentFps} FPS" });
235234
}
236235
}

0 commit comments

Comments
 (0)