fix idiotic errors in config
This commit is contained in:
parent
a12a9ae74f
commit
d4802d372f
|
@ -34,15 +34,15 @@ dependencies {
|
||||||
shade (project(':Jankson')) { transitive = false }
|
shade (project(':Jankson')) { transitive = false }
|
||||||
|
|
||||||
shade group: 'org.jetbrains.kotlin', name: 'kotlin-stdlib-jdk8', version: kotlinVersion
|
shade group: 'org.jetbrains.kotlin', name: 'kotlin-stdlib-jdk8', version: kotlinVersion
|
||||||
shade(group: "com.github.NikkyAi.Fuel", name: "fuel", version: "feature~chunked-SNAPSHOT")
|
|
||||||
shade(group: "com.github.NikkyAi.Fuel", name: "fuel-coroutines", version: "feature~chunked-SNAPSHOT")
|
shade(group: "org.jetbrains.kotlinx", name: "kotlinx-coroutines-core", version: coroutinesVersion)
|
||||||
|
shade(group: "org.jetbrains.kotlinx", name: "kotlinx-serialization-runtime", version: serializationVersion)
|
||||||
|
|
||||||
|
shade(group: "com.github.kittinunf.Fuel", name: "fuel", version: fuelVersion)
|
||||||
|
shade(group: "com.github.kittinunf.Fuel", name: "fuel-coroutines", version: fuelVersion)
|
||||||
shade(group: 'com.github.kittinunf.result', name: 'result', version: resultVersion)
|
shade(group: 'com.github.kittinunf.result', name: 'result', version: resultVersion)
|
||||||
|
// shade group: 'com.github.kittinunf.fuel', name: 'fuel', version: fuelVersion
|
||||||
shade(group: "org.jetbrains.kotlinx", name: "kotlinx-coroutines-core", version: "1.0.0")
|
// shade group: 'com.github.kittinunf.result', name: 'result', version: resultVersion
|
||||||
shade(group: "org.jetbrains.kotlinx", name: "kotlinx-serialization-runtime", version: "0.9.0")
|
|
||||||
|
|
||||||
shade group: 'com.github.kittinunf.fuel', name: 'fuel', version: fuelVersion
|
|
||||||
shade group: 'com.github.kittinunf.result', name: 'result', version: resultVersion
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -23,18 +23,18 @@ dependencies {
|
||||||
compile group: 'com.google.code.gson', name: 'gson', version: '+'
|
compile group: 'com.google.code.gson', name: 'gson', version: '+'
|
||||||
compile group: 'com.google.guava', name: 'guava', version: '+'
|
compile group: 'com.google.guava', name: 'guava', version: '+'
|
||||||
|
|
||||||
compile(group: "com.github.NikkyAi.Fuel", name: "fuel", version: "742c73082e")
|
compile(group: "com.github.kittinunf.Fuel", name: "fuel", version: fuelVersion)
|
||||||
shadow(group: "com.github.NikkyAi.Fuel", name: "fuel", version: "742c73082e") { transitive = false }
|
shadow(group: "com.github.kittinunf.Fuel", name: "fuel", version: fuelVersion) { transitive = false }
|
||||||
compile(group: "com.github.NikkyAi.Fuel", name: "fuel-coroutines", version: "742c73082e")
|
compile(group: "com.github.kittinunf.Fuel", name: "fuel-coroutines", version: fuelVersion)
|
||||||
shadow(group: "com.github.NikkyAi.Fuel", name: "fuel-coroutines", version: "742c73082e") { transitive = false }
|
shadow(group: "com.github.kittinunf.Fuel", name: "fuel-coroutines", version: fuelVersion) { transitive = false }
|
||||||
compile(group: 'com.github.kittinunf.result', name: 'result', version: resultVersion)
|
compile(group: 'com.github.kittinunf.result', name: 'result', version: resultVersion)
|
||||||
shadow(group: 'com.github.kittinunf.result', name: 'result', version: resultVersion) { transitive = false }
|
shadow(group: 'com.github.kittinunf.result', name: 'result', version: resultVersion) { transitive = false }
|
||||||
|
|
||||||
compile(group: "org.jetbrains.kotlinx", name: "kotlinx-coroutines-core", version: "1.0.1")
|
compile(group: "org.jetbrains.kotlinx", name: "kotlinx-coroutines-core", version: coroutinesVersion)
|
||||||
shadow(group: "org.jetbrains.kotlinx", name: "kotlinx-coroutines-core", version: "1.0.1") { transitive = false }
|
shadow(group: "org.jetbrains.kotlinx", name: "kotlinx-coroutines-core", version: coroutinesVersion) { transitive = false }
|
||||||
|
|
||||||
compile(group: "org.jetbrains.kotlinx", name: "kotlinx-serialization-runtime", version: "0.9.0")
|
compile(group: "org.jetbrains.kotlinx", name: "kotlinx-serialization-runtime", version: serializationVersion)
|
||||||
shadow(group: "org.jetbrains.kotlinx", name: "kotlinx-serialization-runtime", version: "0.9.0") { transitive = false }
|
shadow(group: "org.jetbrains.kotlinx", name: "kotlinx-serialization-runtime", version: serializationVersion) { transitive = false }
|
||||||
|
|
||||||
compile group: 'org.jetbrains.kotlin', name: 'kotlin-stdlib-jdk8', version: kotlinVersion
|
compile group: 'org.jetbrains.kotlin', name: 'kotlin-stdlib-jdk8', version: kotlinVersion
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,9 +7,4 @@ data class Config(
|
||||||
var announceDisconnect: Boolean = true,
|
var announceDisconnect: Boolean = true,
|
||||||
var reconnectWait: Long = 500,
|
var reconnectWait: Long = 500,
|
||||||
var systemUser: String = "Server"
|
var systemUser: String = "Server"
|
||||||
) {
|
)
|
||||||
fun sync(connection: StreamConnection) {
|
|
||||||
connection.token = token
|
|
||||||
connection.host = url
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -12,7 +12,9 @@ import com.github.kittinunf.result.Result
|
||||||
import kotlinx.coroutines.CoroutineName
|
import kotlinx.coroutines.CoroutineName
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
|
import kotlinx.coroutines.ObsoleteCoroutinesApi
|
||||||
import kotlinx.coroutines.channels.BroadcastChannel
|
import kotlinx.coroutines.channels.BroadcastChannel
|
||||||
import kotlinx.coroutines.channels.Channel
|
import kotlinx.coroutines.channels.Channel
|
||||||
import kotlinx.coroutines.channels.SendChannel
|
import kotlinx.coroutines.channels.SendChannel
|
||||||
|
@ -27,6 +29,7 @@ import kotlinx.serialization.json.JSON
|
||||||
import kotlinx.serialization.list
|
import kotlinx.serialization.list
|
||||||
import matterlink.Logger
|
import matterlink.Logger
|
||||||
import java.io.Reader
|
import java.io.Reader
|
||||||
|
import java.net.ConnectException
|
||||||
import kotlin.coroutines.CoroutineContext
|
import kotlin.coroutines.CoroutineContext
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -46,6 +49,7 @@ open class MessageHandler : CoroutineScope {
|
||||||
private var sendChannel: SendChannel<ApiMessage> = senderActor()
|
private var sendChannel: SendChannel<ApiMessage> = senderActor()
|
||||||
|
|
||||||
private val messageStream = Channel<ApiMessage>(Channel.UNLIMITED)
|
private val messageStream = Channel<ApiMessage>(Channel.UNLIMITED)
|
||||||
|
@UseExperimental(ExperimentalCoroutinesApi::class)
|
||||||
var broadcast: BroadcastChannel<ApiMessage> = broadcast {
|
var broadcast: BroadcastChannel<ApiMessage> = broadcast {
|
||||||
while (true) {
|
while (true) {
|
||||||
val msg = messageStream.receive()
|
val msg = messageStream.receive()
|
||||||
|
@ -135,7 +139,7 @@ open class MessageHandler : CoroutineScope {
|
||||||
logger.error("missing gateway on message: $msg")
|
logger.error("missing gateway on message: $msg")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
logger.debug("Transmitting: $msg")
|
logger.info("Transmitting: $msg")
|
||||||
sendChannel.send(msg)
|
sendChannel.send(msg)
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
@ -144,34 +148,40 @@ open class MessageHandler : CoroutineScope {
|
||||||
fun checkConnection() {
|
fun checkConnection() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@UseExperimental(ObsoleteCoroutinesApi::class)
|
||||||
private fun CoroutineScope.senderActor() = actor<ApiMessage>(context = Dispatchers.IO) {
|
private fun CoroutineScope.senderActor() = actor<ApiMessage>(context = Dispatchers.IO) {
|
||||||
consumeEach {
|
consumeEach {
|
||||||
logger.debug("sending $it")
|
try {
|
||||||
val url = "${config.url}/api/message"
|
logger.debug("sending $it")
|
||||||
val (request, response, result) = url.httpPost()
|
val url = "${config.url}/api/message"
|
||||||
.apply {
|
val (request, response, result) = url.httpPost()
|
||||||
if (config.token.isNotEmpty()) {
|
.apply {
|
||||||
headers["Authorization"] = "Bearer ${config.token}"
|
if (config.token.isNotEmpty()) {
|
||||||
|
headers["Authorization"] = "Bearer ${config.token}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.jsonBody(it.encode())
|
||||||
|
.responseString()
|
||||||
|
when (result) {
|
||||||
|
is Result.Success -> {
|
||||||
|
logger.info("sent $it")
|
||||||
|
sendErrors = 0
|
||||||
|
}
|
||||||
|
is Result.Failure -> {
|
||||||
|
sendErrors++
|
||||||
|
logger.error("failed to deliver: $it")
|
||||||
|
logger.error("url: $url")
|
||||||
|
logger.error("cUrl: ${request.cUrlString()}")
|
||||||
|
logger.error("response: $response")
|
||||||
|
logger.error(result.error.exception.localizedMessage)
|
||||||
|
result.error.exception.printStackTrace()
|
||||||
|
// close()
|
||||||
|
throw result.error.exception
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.jsonBody(it.encode())
|
} catch (connectError: ConnectException) {
|
||||||
.responseString()
|
connectError.printStackTrace()
|
||||||
when (result) {
|
sendErrors++
|
||||||
is Result.Success -> {
|
|
||||||
logger.info("sent $it")
|
|
||||||
sendErrors = 0
|
|
||||||
}
|
|
||||||
is Result.Failure -> {
|
|
||||||
sendErrors++
|
|
||||||
logger.error("failed to deliver: $it")
|
|
||||||
logger.error("url: $url")
|
|
||||||
logger.error("cUrl: ${request.cUrlString()}")
|
|
||||||
logger.error("response: $response")
|
|
||||||
logger.error(result.error.exception.localizedMessage)
|
|
||||||
result.error.exception.printStackTrace()
|
|
||||||
// close()
|
|
||||||
throw result.error.exception
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,155 +0,0 @@
|
||||||
package matterlink.api
|
|
||||||
|
|
||||||
import matterlink.Logger
|
|
||||||
import java.io.IOException
|
|
||||||
import java.net.ConnectException
|
|
||||||
import java.net.HttpURLConnection
|
|
||||||
import java.net.MalformedURLException
|
|
||||||
import java.net.URL
|
|
||||||
import java.util.Arrays
|
|
||||||
import java.util.LinkedList
|
|
||||||
import java.util.concurrent.ConcurrentLinkedQueue
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by nikky on 07/05/18.
|
|
||||||
*
|
|
||||||
* @author Nikky
|
|
||||||
* @version 1.0
|
|
||||||
*/
|
|
||||||
class StreamConnection(private val rcvQueue: ConcurrentLinkedQueue<ApiMessage>) : Runnable {
|
|
||||||
private var thread: Thread = createThread()
|
|
||||||
private var urlConnection: HttpURLConnection? = null
|
|
||||||
private val onSuccessCallbacks = LinkedList<(Boolean) -> Unit>()
|
|
||||||
|
|
||||||
var logger = object : Logger {
|
|
||||||
override fun info(message: String) = println("INFO: $message")
|
|
||||||
override fun debug(message: String) = println("DEBUG: $message")
|
|
||||||
override fun error(message: String) = println("ERROR: $message")
|
|
||||||
override fun warn(message: String) = println("WARN: $message")
|
|
||||||
override fun trace(message: String) = println("TRACE: $message")
|
|
||||||
}
|
|
||||||
var host = ""
|
|
||||||
var token = ""
|
|
||||||
|
|
||||||
var isConnected = false
|
|
||||||
private set
|
|
||||||
var isConnecting = false
|
|
||||||
private set
|
|
||||||
var isCancelled = false
|
|
||||||
private set
|
|
||||||
|
|
||||||
private fun createThread(): Thread {
|
|
||||||
val thread = Thread(this)
|
|
||||||
thread.name = "RcvThread"
|
|
||||||
return thread
|
|
||||||
}
|
|
||||||
|
|
||||||
fun addOnSuccess(callback: (Boolean) -> Unit) {
|
|
||||||
onSuccessCallbacks.add(callback)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun removeOnSuccess(callback: (Boolean) -> Unit) {
|
|
||||||
onSuccessCallbacks.remove(callback)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun onSuccess(success: Boolean) {
|
|
||||||
isConnecting = false
|
|
||||||
isConnected = success
|
|
||||||
for (callback in onSuccessCallbacks) {
|
|
||||||
callback(success)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun run() {
|
|
||||||
try {
|
|
||||||
val serviceURL = "$host/api/stream"
|
|
||||||
val myURL: URL
|
|
||||||
|
|
||||||
myURL = URL(serviceURL)
|
|
||||||
urlConnection = myURL.openConnection() as HttpURLConnection
|
|
||||||
urlConnection!!.requestMethod = "GET"
|
|
||||||
if (!token.isEmpty()) {
|
|
||||||
val bearerAuth = "Bearer $token"
|
|
||||||
urlConnection!!.setRequestProperty("Authorization", bearerAuth)
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
urlConnection!!.inputStream.use { input ->
|
|
||||||
logger.info("connection opened")
|
|
||||||
onSuccess(true)
|
|
||||||
// BufferedInputStream bufferedInput = new BufferedInputStream(input, 8 * 1024);
|
|
||||||
val buffer = StringBuilder()
|
|
||||||
while (!isCancelled) {
|
|
||||||
val buf = ByteArray(1024)
|
|
||||||
Thread.sleep(10)
|
|
||||||
while (input.available() <= 0) {
|
|
||||||
if (isCancelled) break
|
|
||||||
Thread.sleep(10)
|
|
||||||
}
|
|
||||||
val chars = input.read(buf)
|
|
||||||
|
|
||||||
logger.trace(String.format("read %d chars", chars))
|
|
||||||
if (chars > 0) {
|
|
||||||
val added = String(Arrays.copyOfRange(buf, 0, chars))
|
|
||||||
logger.debug("json: $added")
|
|
||||||
buffer.append(added)
|
|
||||||
while (buffer.toString().contains("\n")) {
|
|
||||||
val index = buffer.indexOf("\n")
|
|
||||||
val line = buffer.substring(0, index)
|
|
||||||
buffer.delete(0, index + 1)
|
|
||||||
rcvQueue.add(ApiMessage.decode(line))
|
|
||||||
}
|
|
||||||
} else if (chars < 0) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
onClose()
|
|
||||||
}
|
|
||||||
} catch (e: MalformedURLException) {
|
|
||||||
e.printStackTrace()
|
|
||||||
} catch (e: ConnectException) {
|
|
||||||
e.printStackTrace()
|
|
||||||
onSuccess(false)
|
|
||||||
} catch (e: IOException) {
|
|
||||||
e.printStackTrace()
|
|
||||||
onSuccess(false)
|
|
||||||
} catch (e: InterruptedException) {
|
|
||||||
e.printStackTrace()
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun onClose() {
|
|
||||||
logger.info("Bridge connection closed!")
|
|
||||||
isConnected = false
|
|
||||||
isConnecting = false
|
|
||||||
}
|
|
||||||
|
|
||||||
fun open() {
|
|
||||||
if (!thread.isAlive) {
|
|
||||||
thread = createThread()
|
|
||||||
isConnecting = true
|
|
||||||
isCancelled = false
|
|
||||||
thread.start()
|
|
||||||
logger.info("Starting Connection")
|
|
||||||
}
|
|
||||||
if (thread.isAlive) {
|
|
||||||
logger.info("Bridge is connecting")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun close() {
|
|
||||||
try {
|
|
||||||
isCancelled = true
|
|
||||||
if (urlConnection != null) {
|
|
||||||
urlConnection!!.disconnect()
|
|
||||||
}
|
|
||||||
thread.join()
|
|
||||||
logger.info("Thread stopped")
|
|
||||||
} catch (e: InterruptedException) {
|
|
||||||
e.printStackTrace()
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -194,8 +194,7 @@ data class BaseConfig(val rootDir: File) {
|
||||||
data class AvatarOptions(
|
data class AvatarOptions(
|
||||||
val enable: Boolean = true,
|
val enable: Boolean = true,
|
||||||
val urlTemplate: String = "https://visage.surgeplay.com/head/512/{uuid}",
|
val urlTemplate: String = "https://visage.surgeplay.com/head/512/{uuid}",
|
||||||
// https://www.freepik.com/free-icon/right-arrow-angle-and-horizontal-down-line-code-signs_732795.htm
|
val systemUserAvatar: String = ""
|
||||||
val systemUserAvatar: String = "https://image.freepik.com/free-icon/right-arrow-angle-and-horizontal-down-line-code-signs_318-53994.jpg"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
data class JoinPartOptions(
|
data class JoinPartOptions(
|
||||||
|
@ -625,20 +624,32 @@ data class BaseConfig(val rootDir: File) {
|
||||||
}
|
}
|
||||||
.registerSerializer { locationSettings: SettingsOutgoing, marshaller: Marshaller ->
|
.registerSerializer { locationSettings: SettingsOutgoing, marshaller: Marshaller ->
|
||||||
val jsonObject = JsonObject()
|
val jsonObject = JsonObject()
|
||||||
|
locationSettings.plain?.let {
|
||||||
|
jsonObject["plain"] = marshaller.serialize(it)
|
||||||
|
}
|
||||||
|
locationSettings.action?.let {
|
||||||
|
jsonObject["action"] = marshaller.serialize(it)
|
||||||
|
}
|
||||||
|
locationSettings.join?.let {
|
||||||
|
jsonObject["join"] = marshaller.serialize(it)
|
||||||
|
}
|
||||||
|
locationSettings.leave?.let {
|
||||||
|
jsonObject["leave"] = marshaller.serialize(it)
|
||||||
|
}
|
||||||
locationSettings.advancement?.let {
|
locationSettings.advancement?.let {
|
||||||
jsonObject["advancements"] = marshaller.serialize(it)
|
jsonObject["advancement"] = marshaller.serialize(it)
|
||||||
}
|
}
|
||||||
locationSettings.death?.let {
|
locationSettings.death?.let {
|
||||||
jsonObject["death"] = marshaller.serialize(it)
|
jsonObject["death"] = marshaller.serialize(it)
|
||||||
}
|
}
|
||||||
locationSettings.join?.let {
|
|
||||||
jsonObject["joins"] = marshaller.serialize(it)
|
|
||||||
}
|
|
||||||
locationSettings.leave?.let {
|
|
||||||
jsonObject["leaves"] = marshaller.serialize(it)
|
|
||||||
}
|
|
||||||
locationSettings.broadcast?.let {
|
locationSettings.broadcast?.let {
|
||||||
jsonObject["say"] = marshaller.serialize(it)
|
jsonObject["broadcast"] = marshaller.serialize(it)
|
||||||
|
}
|
||||||
|
locationSettings.status?.let {
|
||||||
|
jsonObject["status"] = marshaller.serialize(it)
|
||||||
|
}
|
||||||
|
locationSettings.skip.let {
|
||||||
|
jsonObject["skip"] = marshaller.serialize(it)
|
||||||
}
|
}
|
||||||
jsonObject
|
jsonObject
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,8 @@ object ChatProcessor {
|
||||||
msg = message,
|
msg = message,
|
||||||
x = x, y = y, z = z, dimension = dimension,
|
x = x, y = y, z = z, dimension = dimension,
|
||||||
event = event,
|
event = event,
|
||||||
cause = "Message from $user"
|
cause = "Message from $user",
|
||||||
|
uuid = uuid
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -55,6 +55,9 @@ object LocationHandler {
|
||||||
|
|
||||||
if (!matchesEvent) {
|
if (!matchesEvent) {
|
||||||
logger.info("location: $label dropped message '$msg' from user: '$user', event not enabled")
|
logger.info("location: $label dropped message '$msg' from user: '$user', event not enabled")
|
||||||
|
logger.info("event: $event")
|
||||||
|
logger.info("location.outgoing: ${location.outgoing}")
|
||||||
|
logger.info("defaults: $defaults")
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package matterlink.handlers
|
package matterlink.handlers
|
||||||
|
|
||||||
|
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||||
import matterlink.api.ApiMessage
|
import matterlink.api.ApiMessage
|
||||||
import matterlink.bridge.MessageHandlerInst
|
import matterlink.bridge.MessageHandlerInst
|
||||||
import matterlink.bridge.command.BridgeCommandRegistry
|
import matterlink.bridge.command.BridgeCommandRegistry
|
||||||
|
@ -10,6 +11,7 @@ import matterlink.logger
|
||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
|
|
||||||
object ServerChatHandler {
|
object ServerChatHandler {
|
||||||
|
@UseExperimental(ExperimentalCoroutinesApi::class)
|
||||||
val rcvChannel = MessageHandlerInst.broadcast.openSubscription()
|
val rcvChannel = MessageHandlerInst.broadcast.openSubscription()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -2,9 +2,11 @@ modName = MatterLink
|
||||||
modVersion = 1.6.4
|
modVersion = 1.6.4
|
||||||
forgelinVersion = 1.8.0
|
forgelinVersion = 1.8.0
|
||||||
kotlinVersion = 1.3.0
|
kotlinVersion = 1.3.0
|
||||||
|
coroutinesVersion = 1.0.1
|
||||||
|
serializationVersion = 0.9.1
|
||||||
shadowVersion = 2.0.2
|
shadowVersion = 2.0.2
|
||||||
fuelVersion = 1.16.0
|
fuelVersion = b5d2b1fd05
|
||||||
resultVersion = 1.6.0
|
resultVersion = 2.0.0
|
||||||
cursegradleVersion = 1.1.0
|
cursegradleVersion = 1.1.0
|
||||||
curseId = 287323
|
curseId = 287323
|
||||||
curseReleaseType = beta
|
curseReleaseType = beta
|
Loading…
Reference in New Issue