Skip to content

Commit a556027

Browse files
committed
add config
1 parent 5fae2f7 commit a556027

File tree

6 files changed

+112
-31
lines changed

6 files changed

+112
-31
lines changed

build.gradle.kts

-12
Original file line numberDiff line numberDiff line change
@@ -42,18 +42,6 @@ dependencies {
4242
implementation("thedarkcolour:kfflib:${kotlin_forge_version}")
4343

4444
//add("minecraftLibrary", "org.jetbrains.kotlin:kotlin-reflect:${kotlin.coreLibrariesVersion}")
45-
46-
/*
47-
"minecraftLibrary"("com.expediagroup:graphql-kotlin-ktor-client:$graphql_client_version") {
48-
exclude(group = "org.jetbrains.kotlinx")
49-
exclude(group = "org.jetbrains.kotlin", module = "kotlin-stdlib")
50-
exclude(group = "org.jetbrains")
51-
}
52-
53-
"jarJar"("com.expediagroup:graphql-kotlin-ktor-client:$graphql_client_version") {
54-
jarJar.pin(this, "[${graphql_client_version},)")
55-
}
56-
*/
5745
}
5846

5947
graphql {

gradle.properties

+1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ kotlin.code.style=official
22
org.gradle.jvmargs=-Xmx2G
33
org.gradle.daemon=false
44

5+
java_version=17
56
mc_version=1.20.1
67
forge_version=47.1.3
78

src/main/kotlin/com/possible_triangle/atheneum_connector/AtheneumConnector.kt

+16-7
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,21 @@
11
package com.possible_triangle.atheneum_connector
22

3+
import com.possible_triangle.atheneum_connector.messages.ServerStatus
4+
import com.possible_triangle.atheneum_connector.messages.ServerStatusMessage
35
import kotlinx.serialization.json.Json
46
import kotlinx.serialization.json.JsonBuilder
5-
import net.minecraftforge.api.distmarker.Dist
7+
import net.minecraftforge.event.server.ServerStartedEvent
68
import net.minecraftforge.event.server.ServerStoppingEvent
7-
import net.minecraftforge.fml.DistExecutor
9+
import net.minecraftforge.eventbus.api.SubscribeEvent
810
import net.minecraftforge.fml.common.Mod
11+
import net.minecraftforge.fml.common.Mod.EventBusSubscriber
12+
import net.minecraftforge.fml.event.lifecycle.FMLDedicatedServerSetupEvent
913
import org.slf4j.Logger
1014
import org.slf4j.LoggerFactory
1115
import thedarkcolour.kotlinforforge.forge.FORGE_BUS
1216

1317
@Mod("atheneum_connector")
18+
@EventBusSubscriber(bus = EventBusSubscriber.Bus.MOD)
1419
object AtheneumConnector {
1520

1621
fun JsonBuilder.configure() {
@@ -22,16 +27,20 @@ object AtheneumConnector {
2227
val LOG: Logger = LoggerFactory.getLogger("Atheneum Connector")
2328

2429
init {
25-
DistExecutor.unsafeRunWhenOn(Dist.DEDICATED_SERVER) {
26-
Runnable(::serverInit)
27-
}
30+
Config.register()
2831
}
2932

30-
private fun serverInit() {
31-
RabbitMQ.connect("amqp://guest:guest@localhost:5672/")
33+
@SubscribeEvent
34+
fun serverInit(event: FMLDedicatedServerSetupEvent) {
35+
RabbitMQ.connect()
3236
LocationCache.initialize()
3337

38+
FORGE_BUS.addListener { _: ServerStartedEvent ->
39+
RabbitMQ.publish(ServerStatusMessage(ServerStatus.STARTED))
40+
}
41+
3442
FORGE_BUS.addListener { _: ServerStoppingEvent ->
43+
RabbitMQ.publish(ServerStatusMessage(ServerStatus.STOPPED))
3544
RabbitMQ.close()
3645
}
3746
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package com.possible_triangle.atheneum_connector
2+
3+
import net.minecraftforge.common.ForgeConfigSpec
4+
import net.minecraftforge.fml.config.ModConfig
5+
import thedarkcolour.kotlinforforge.forge.LOADING_CONTEXT
6+
import java.net.URI
7+
import java.net.URL
8+
9+
object Config {
10+
11+
private val SERVER_SPEC: ForgeConfigSpec
12+
val SERVER: Server
13+
14+
init {
15+
with(ForgeConfigSpec.Builder().configure { Server(it) }) {
16+
SERVER = left
17+
SERVER_SPEC = right
18+
}
19+
}
20+
21+
fun register() {
22+
LOADING_CONTEXT.registerConfig(ModConfig.Type.COMMON, SERVER_SPEC)
23+
}
24+
25+
class Server internal constructor(builder: ForgeConfigSpec.Builder) {
26+
27+
init {
28+
builder.push("rabbitmq")
29+
}
30+
31+
private val rabbitmqUser = builder.define("user", "guest")
32+
private val rabbitmqPass = builder.define("password", "guest")
33+
private val rabbitmqHost = builder.define("host", "localhost")
34+
private val rabbitmqPort = builder.define("port", "5672")
35+
36+
val rabbitMQUrl
37+
get() = "amqp://${rabbitmqUser.get()}:${rabbitmqPass.get()}@${rabbitmqHost.get()}:${rabbitmqPort.get()}/"
38+
39+
init {
40+
builder.pop()
41+
builder.push("grapql")
42+
}
43+
44+
private val _graphqlUrl = builder.define("url", "http://localhost:8080/api/graphql")
45+
val graphqlUrl: URL get() = URI(_graphqlUrl.get()).toURL()
46+
47+
}
48+
49+
}

src/main/kotlin/com/possible_triangle/atheneum_connector/GraphQL.kt

+1-2
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,11 @@ import com.expediagroup.graphql.client.ktor.GraphQLKtorClient
44
import com.expediagroup.graphql.client.serialization.GraphQLClientKotlinxSerializer
55
import com.expediagroup.graphql.client.types.GraphQLClientRequest
66
import com.possible_triangle.atheneum_connector.AtheneumConnector.configure
7-
import java.net.URL
87

98
object GraphQL {
109

1110
private val client = GraphQLKtorClient(
12-
URL("http://localhost:8080/api/graphql"),
11+
Config.SERVER.graphqlUrl,
1312
serializer = GraphQLClientKotlinxSerializer { configure() }
1413
)
1514

src/main/kotlin/com/possible_triangle/atheneum_connector/RabbitMQ.kt

+45-10
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
package com.possible_triangle.atheneum_connector
22

3-
import com.rabbitmq.client.Channel
4-
import com.rabbitmq.client.ConnectionFactory
3+
import com.possible_triangle.atheneum_connector.messages.ServerStatus
4+
import com.possible_triangle.atheneum_connector.messages.ServerStatusMessage
5+
import com.rabbitmq.client.*
6+
import io.ktor.util.logging.*
57
import kotlinx.serialization.InternalSerializationApi
68
import kotlinx.serialization.serializer
79
import net.minecraftforge.fml.ModList
@@ -11,18 +13,26 @@ import kotlin.reflect.KParameter
1113
import kotlin.reflect.full.hasAnnotation
1214
import kotlin.reflect.full.memberFunctions
1315

14-
object RabbitMQ {
16+
object RabbitMQ : RecoveryListener, ShutdownListener {
1517

1618
private const val EXCHANGE_KEY = "exchange"
1719

1820
private lateinit var channel: Channel
1921

20-
fun connect(url: String) {
22+
fun connect() {
2123
AtheneumConnector.LOG.info("Connecting to RabbitMQ")
2224

23-
val connection = ConnectionFactory().newConnection(url)
25+
val connection = ConnectionFactory().newConnection(Config.SERVER.rabbitMQUrl)
26+
27+
connection.addShutdownListener(this)
28+
29+
if (connection is Recoverable) {
30+
connection.addRecoveryListener(this)
31+
}
2432

2533
channel = connection.createChannel()
34+
declareExchanges()
35+
2636
val queue = channel.queueDeclare().queue
2737

2838
val consumers = hashMapOf<String, MutableList<(ByteArray) -> Unit>>()
@@ -39,11 +49,38 @@ object RabbitMQ {
3949
}, { _ -> })
4050
}
4151

42-
fun close() {
52+
private fun declareExchanges() {
53+
channel.exchangeDeclare(EXCHANGE_KEY, "direct")
54+
}
55+
56+
override fun handleRecovery(recoverable: Recoverable) {
57+
AtheneumConnector.LOG.warn("RabbitMQ has recovered")
58+
declareExchanges()
59+
publish(ServerStatusMessage(ServerStatus.RECOVERED))
60+
}
61+
62+
override fun handleRecoveryStarted(recoverable: Recoverable) {
63+
AtheneumConnector.LOG.warn("Trying to reconnect to RabbitMQ...")
64+
}
65+
66+
override fun shutdownCompleted(exception: ShutdownSignalException) {
67+
AtheneumConnector.LOG.warn("RabbitMQ has shutdown, reconnecting... ({})", exception.message)
68+
}
69+
70+
private fun tryCatching(action: () -> Unit) {
71+
try {
72+
action()
73+
} catch (ex: ShutdownSignalException) {
74+
AtheneumConnector.LOG.error("Encountered exception when publishing to RabbitMQ")
75+
AtheneumConnector.LOG.error(ex)
76+
}
77+
}
78+
79+
fun close() = tryCatching {
4380
channel.connection.close()
4481
}
4582

46-
fun publish(routingKey: String, bytes: ByteArray) {
83+
fun publish(routingKey: String, bytes: ByteArray) = tryCatching {
4784
channel.basicPublish(EXCHANGE_KEY, routingKey, null, bytes)
4885
}
4986

@@ -63,9 +100,7 @@ object RabbitMQ {
63100
val topic = Class.forName(messageType.toString()).simpleName
64101
val deserializer = serializer(messageType)
65102

66-
if (method.parameters.size != 2) {
67-
throw IllegalArgumentException("@SubscribeMessage handlers may only accept one parameter, the message itself")
68-
}
103+
require(method.parameters.size == 2) { "@SubscribeMessage handlers may only accept one parameter, the message itself" }
69104

70105
consume(topic) {
71106
val message = AtheneumConnector.JSON.decodeFromString(deserializer, it.decodeToString())

0 commit comments

Comments
 (0)