Add Forge :)
This commit is contained in:
parent
cdd572bb7e
commit
b98a23fc90
35
common/build.gradle.kts
Normal file
35
common/build.gradle.kts
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
plugins {
|
||||||
|
kotlin("jvm") version "1.7.20"
|
||||||
|
kotlin("plugin.serialization") version "1.7.20"
|
||||||
|
}
|
||||||
|
|
||||||
|
group = "openproximitychat.muellerssoftware.org"
|
||||||
|
version = "unspecified"
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
// KTOR
|
||||||
|
implementation("io.ktor:ktor-server-core-jvm:2.1.3")
|
||||||
|
implementation("io.ktor:ktor-server-netty-jvm:2.1.3")
|
||||||
|
implementation("io.ktor:ktor-network:2.1.3")
|
||||||
|
implementation("io.ktor:ktor-network-tls:2.1.3")
|
||||||
|
|
||||||
|
// UPnP
|
||||||
|
implementation("org.bitlet:weupnp:0.1.4")
|
||||||
|
|
||||||
|
// Serialization
|
||||||
|
implementation("org.jetbrains.kotlinx:kotlinx-serialization-core:1.4.1")
|
||||||
|
implementation("org.jetbrains.kotlinx:kotlinx-serialization-protobuf:1.4.1")
|
||||||
|
|
||||||
|
// Logging
|
||||||
|
implementation("org.slf4j:slf4j-api:2.0.3")
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks {
|
||||||
|
compileKotlin {
|
||||||
|
kotlinOptions.jvmTarget = "17"
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,53 @@
|
|||||||
|
package org.muellerssoftware.openproximitychat.common
|
||||||
|
|
||||||
|
import org.slf4j.Logger
|
||||||
|
|
||||||
|
object Logging {
|
||||||
|
enum class LogType {
|
||||||
|
Debug,
|
||||||
|
Info,
|
||||||
|
Error
|
||||||
|
}
|
||||||
|
|
||||||
|
var logger: Logger? = null
|
||||||
|
set(value) {
|
||||||
|
for (log in backLog) {
|
||||||
|
when (log.first) {
|
||||||
|
LogType.Debug -> value?.debug(log.second)
|
||||||
|
LogType.Info -> value?.info(log.second)
|
||||||
|
LogType.Error -> value?.error(log.second)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
field = value
|
||||||
|
}
|
||||||
|
|
||||||
|
var backLog = mutableListOf<Pair<LogType, String>>()
|
||||||
|
|
||||||
|
fun info(message: String) {
|
||||||
|
if (logger != null) {
|
||||||
|
logger!!.info(message)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
backLog.add(Pair(LogType.Info, message))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun error(message: String) {
|
||||||
|
if (logger != null) {
|
||||||
|
logger!!.error(message)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
backLog.add(Pair(LogType.Error, message))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun debug(message: String) {
|
||||||
|
if (logger != null) {
|
||||||
|
logger!!.debug(message)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
backLog.add(Pair(LogType.Debug, message))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,8 +1,7 @@
|
|||||||
package org.muellerssoftware.openproximitychatfabric.voice
|
package org.muellerssoftware.openproximitychat.common
|
||||||
|
|
||||||
import org.bitlet.weupnp.GatewayDevice
|
import org.bitlet.weupnp.GatewayDevice
|
||||||
import org.bitlet.weupnp.GatewayDiscover
|
import org.bitlet.weupnp.GatewayDiscover
|
||||||
import org.muellerssoftware.openproximitychatfabric.OPCFabric
|
|
||||||
|
|
||||||
object UPnPManager {
|
object UPnPManager {
|
||||||
var gateway: GatewayDevice? = null
|
var gateway: GatewayDevice? = null
|
||||||
@ -11,7 +10,7 @@ object UPnPManager {
|
|||||||
init {
|
init {
|
||||||
val gatewayDiscoverer = GatewayDiscover()
|
val gatewayDiscoverer = GatewayDiscover()
|
||||||
for (i in 0..9) {
|
for (i in 0..9) {
|
||||||
OPCFabric.LOGGER.info("Searching for UPnP gateway... (Attempt ${i + 1})")
|
Logging.info("Searching for UPnP gateway... (Attempt ${i + 1})")
|
||||||
gatewayDiscoverer.discover()
|
gatewayDiscoverer.discover()
|
||||||
if (gatewayDiscoverer.getValidGateway() != null) {
|
if (gatewayDiscoverer.getValidGateway() != null) {
|
||||||
gateway = gatewayDiscoverer.validGateway
|
gateway = gatewayDiscoverer.validGateway
|
||||||
@ -20,10 +19,10 @@ object UPnPManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (gateway == null) {
|
if (gateway == null) {
|
||||||
OPCFabric.LOGGER.error("No UPnP gateway found!")
|
Logging.error("No UPnP gateway found!")
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
OPCFabric.LOGGER.info("UPnP gateway found: ${gateway!!.friendlyName}")
|
Logging.info("UPnP gateway found: ${gateway!!.friendlyName}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
package org.muellerssoftware.openproximitychatfabric.voice
|
package org.muellerssoftware.openproximitychat.common
|
||||||
|
|
||||||
import kotlinx.serialization.KSerializer
|
import kotlinx.serialization.KSerializer
|
||||||
import kotlinx.serialization.descriptors.PrimitiveKind
|
import kotlinx.serialization.descriptors.PrimitiveKind
|
@ -1,4 +1,4 @@
|
|||||||
package org.muellerssoftware.openproximitychatfabric.voice
|
package org.muellerssoftware.openproximitychat.common
|
||||||
|
|
||||||
import io.ktor.network.selector.*
|
import io.ktor.network.selector.*
|
||||||
import io.ktor.network.sockets.*
|
import io.ktor.network.sockets.*
|
||||||
@ -8,14 +8,13 @@ import kotlinx.coroutines.*
|
|||||||
import kotlinx.serialization.ExperimentalSerializationApi
|
import kotlinx.serialization.ExperimentalSerializationApi
|
||||||
import kotlinx.serialization.encodeToByteArray
|
import kotlinx.serialization.encodeToByteArray
|
||||||
import kotlinx.serialization.protobuf.ProtoBuf
|
import kotlinx.serialization.protobuf.ProtoBuf
|
||||||
import org.muellerssoftware.openproximitychatfabric.OPCFabric
|
import org.muellerssoftware.openproximitychat.common.packets.ClosePacket
|
||||||
import org.muellerssoftware.openproximitychatfabric.voice.packets.ClosePacket
|
import org.muellerssoftware.openproximitychat.common.packets.InitialPacket
|
||||||
import org.muellerssoftware.openproximitychatfabric.voice.packets.InitialPacket
|
import org.muellerssoftware.openproximitychat.common.packets.PacketType
|
||||||
import org.muellerssoftware.openproximitychatfabric.voice.packets.PacketType
|
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
class VoiceClient(netAddress: InetSocketAddress, playerUUID: UUID) {
|
class VoiceClient(netAddress: java.net.InetSocketAddress, playerUUID: UUID) {
|
||||||
var server = netAddress
|
var server = InetSocketAddress(netAddress.hostString, netAddress.port)
|
||||||
val uuid = playerUUID
|
val uuid = playerUUID
|
||||||
val selectorManager = SelectorManager(Dispatchers.IO)
|
val selectorManager = SelectorManager(Dispatchers.IO)
|
||||||
val socket = aSocket(selectorManager).udp().connect(server)
|
val socket = aSocket(selectorManager).udp().connect(server)
|
||||||
@ -23,7 +22,7 @@ class VoiceClient(netAddress: InetSocketAddress, playerUUID: UUID) {
|
|||||||
var clientJob: Job = Job()
|
var clientJob: Job = Job()
|
||||||
|
|
||||||
init {
|
init {
|
||||||
OPCFabric.LOGGER.info("VoiceClient initialized for IP: ${server.hostname}:${server.port}")
|
Logging.info("VoiceClient initialized for IP: ${server.hostname}:${server.port}")
|
||||||
}
|
}
|
||||||
|
|
||||||
@OptIn(DelicateCoroutinesApi::class)
|
@OptIn(DelicateCoroutinesApi::class)
|
||||||
@ -45,7 +44,7 @@ class VoiceClient(netAddress: InetSocketAddress, playerUUID: UUID) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
} catch (e: CancellationException) {
|
} catch (e: CancellationException) {
|
||||||
OPCFabric.LOGGER.info("VoiceClient for ${server.hostname}:${server.port} exiting...")
|
Logging.info("VoiceClient for ${server.hostname}:${server.port} exiting...")
|
||||||
} finally {
|
} finally {
|
||||||
writeChannel.write {
|
writeChannel.write {
|
||||||
ProtoBuf.encodeToByteArray(
|
ProtoBuf.encodeToByteArray(
|
@ -1,6 +1,6 @@
|
|||||||
@file:OptIn(ExperimentalSerializationApi::class)
|
@file:OptIn(ExperimentalSerializationApi::class)
|
||||||
|
|
||||||
package org.muellerssoftware.openproximitychatfabric.voice
|
package org.muellerssoftware.openproximitychat.common
|
||||||
|
|
||||||
import io.ktor.network.selector.*
|
import io.ktor.network.selector.*
|
||||||
import io.ktor.network.sockets.*
|
import io.ktor.network.sockets.*
|
||||||
@ -11,8 +11,7 @@ import kotlinx.serialization.ExperimentalSerializationApi
|
|||||||
import kotlinx.serialization.decodeFromByteArray
|
import kotlinx.serialization.decodeFromByteArray
|
||||||
import kotlinx.serialization.encodeToByteArray
|
import kotlinx.serialization.encodeToByteArray
|
||||||
import kotlinx.serialization.protobuf.ProtoBuf
|
import kotlinx.serialization.protobuf.ProtoBuf
|
||||||
import org.muellerssoftware.openproximitychatfabric.OPCFabric
|
import org.muellerssoftware.openproximitychat.common.packets.*
|
||||||
import org.muellerssoftware.openproximitychatfabric.voice.packets.*
|
|
||||||
import java.net.InetAddress
|
import java.net.InetAddress
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
@ -53,7 +52,7 @@ object VoiceServer {
|
|||||||
when (packet.type) {
|
when (packet.type) {
|
||||||
PacketType.Initial -> {
|
PacketType.Initial -> {
|
||||||
val initialPacket = ProtoBuf.decodeFromByteArray<InitialPacket>(packetBytes.array())
|
val initialPacket = ProtoBuf.decodeFromByteArray<InitialPacket>(packetBytes.array())
|
||||||
OPCFabric.LOGGER.debug("Received InitialPacket from ${initialPacket.uuidFrom}")
|
Logging.debug("Received InitialPacket from ${initialPacket.uuidFrom}")
|
||||||
}
|
}
|
||||||
|
|
||||||
PacketType.Voice -> {
|
PacketType.Voice -> {
|
||||||
@ -62,11 +61,11 @@ object VoiceServer {
|
|||||||
|
|
||||||
PacketType.Close -> {
|
PacketType.Close -> {
|
||||||
val closePacket = ProtoBuf.decodeFromByteArray<ClosePacket>(packetBytes.array())
|
val closePacket = ProtoBuf.decodeFromByteArray<ClosePacket>(packetBytes.array())
|
||||||
OPCFabric.LOGGER.debug("Received ClosePacket from ${closePacket.uuidFrom}")
|
Logging.debug("Received ClosePacket from ${closePacket.uuidFrom}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
OPCFabric.LOGGER.error("Error while handling packet: ${e.message}")
|
Logging.error("Error while handling packet: ${e.message}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -75,7 +74,7 @@ object VoiceServer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun exit() {
|
fun exit() {
|
||||||
OPCFabric.LOGGER.info("VoiceServer exiting...")
|
Logging.info("VoiceServer exiting...")
|
||||||
UPnPManager.unMapAll()
|
UPnPManager.unMapAll()
|
||||||
if (recieverJob.isActive) {
|
if (recieverJob.isActive) {
|
||||||
runBlocking {
|
runBlocking {
|
@ -1,7 +1,7 @@
|
|||||||
package org.muellerssoftware.openproximitychatfabric.voice.packets
|
package org.muellerssoftware.openproximitychat.common.packets
|
||||||
|
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import org.muellerssoftware.openproximitychatfabric.voice.UUIDSerializer
|
import org.muellerssoftware.openproximitychat.common.UUIDSerializer
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
@ -1,7 +1,7 @@
|
|||||||
package org.muellerssoftware.openproximitychatfabric.voice.packets
|
package org.muellerssoftware.openproximitychat.common.packets
|
||||||
|
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import org.muellerssoftware.openproximitychatfabric.voice.UUIDSerializer
|
import org.muellerssoftware.openproximitychat.common.UUIDSerializer
|
||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
@ -1,8 +1,8 @@
|
|||||||
package org.muellerssoftware.openproximitychatfabric.voice.packets
|
package org.muellerssoftware.openproximitychat.common.packets
|
||||||
|
|
||||||
import kotlinx.serialization.Polymorphic
|
import kotlinx.serialization.Polymorphic
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import org.muellerssoftware.openproximitychatfabric.voice.UUIDSerializer
|
import org.muellerssoftware.openproximitychat.common.UUIDSerializer
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
@Polymorphic
|
@Polymorphic
|
@ -1,4 +1,4 @@
|
|||||||
package org.muellerssoftware.openproximitychatfabric.voice.packets
|
package org.muellerssoftware.openproximitychat.common.packets
|
||||||
|
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
|
|
@ -1,7 +1,7 @@
|
|||||||
package org.muellerssoftware.openproximitychatfabric.voice.packets
|
package org.muellerssoftware.openproximitychat.common.packets
|
||||||
|
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import org.muellerssoftware.openproximitychatfabric.voice.UUIDSerializer
|
import org.muellerssoftware.openproximitychat.common.UUIDSerializer
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
@ -1,6 +1,4 @@
|
|||||||
plugins {
|
plugins {
|
||||||
kotlin("jvm") version "1.7.20"
|
|
||||||
kotlin("plugin.serialization") version "1.7.20"
|
|
||||||
id("fabric-loom")
|
id("fabric-loom")
|
||||||
`maven-publish`
|
`maven-publish`
|
||||||
java
|
java
|
||||||
@ -25,18 +23,11 @@ dependencies {
|
|||||||
modImplementation("net.fabricmc:fabric-language-kotlin:${property("fabric_kotlin_version")}")
|
modImplementation("net.fabricmc:fabric-language-kotlin:${property("fabric_kotlin_version")}")
|
||||||
modImplementation("net.fabricmc.fabric-api:fabric-api:${property("fabric_api_version")}")
|
modImplementation("net.fabricmc.fabric-api:fabric-api:${property("fabric_api_version")}")
|
||||||
|
|
||||||
// KTOR
|
// Common Kotlin
|
||||||
implementation("io.ktor:ktor-server-core-jvm:2.1.3")
|
implementation(project(":common"))
|
||||||
implementation("io.ktor:ktor-server-netty-jvm:2.1.3")
|
|
||||||
implementation("io.ktor:ktor-network:2.1.3")
|
|
||||||
implementation("io.ktor:ktor-network-tls:2.1.3")
|
|
||||||
|
|
||||||
// UPnP
|
// UPnP
|
||||||
implementation("org.bitlet:weupnp:0.1.4")
|
implementation("org.bitlet:weupnp:0.1.4")
|
||||||
|
|
||||||
// Serialization
|
|
||||||
implementation("org.jetbrains.kotlinx:kotlinx-serialization-core:1.4.1")
|
|
||||||
implementation("org.jetbrains.kotlinx:kotlinx-serialization-protobuf:1.4.1")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks {
|
tasks {
|
||||||
@ -52,10 +43,6 @@ tasks {
|
|||||||
from("LICENSE")
|
from("LICENSE")
|
||||||
}
|
}
|
||||||
|
|
||||||
compileKotlin {
|
|
||||||
kotlinOptions.jvmTarget = "17"
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
java {
|
java {
|
@ -1,7 +1,7 @@
|
|||||||
package org.muellerssoftware.openproximitychatfabric;
|
package org.muellerssoftware.openproximitychat.fabric;
|
||||||
|
|
||||||
import net.fabricmc.api.ModInitializer;
|
import net.fabricmc.api.ModInitializer;
|
||||||
import org.muellerssoftware.openproximitychatfabric.connect.HandshakeBuilder;
|
import org.muellerssoftware.openproximitychat.fabric.connect.HandshakeBuilder;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
package org.muellerssoftware.openproximitychatfabric.client;
|
package org.muellerssoftware.openproximitychat.fabric.client;
|
||||||
|
|
||||||
import net.fabricmc.api.ClientModInitializer;
|
import net.fabricmc.api.ClientModInitializer;
|
||||||
import net.fabricmc.api.EnvType;
|
import net.fabricmc.api.EnvType;
|
||||||
@ -10,10 +10,11 @@ import net.minecraft.client.option.KeyBinding;
|
|||||||
import net.minecraft.client.util.InputUtil;
|
import net.minecraft.client.util.InputUtil;
|
||||||
import net.minecraft.network.packet.c2s.play.PlayerMoveC2SPacket;
|
import net.minecraft.network.packet.c2s.play.PlayerMoveC2SPacket;
|
||||||
import org.lwjgl.glfw.GLFW;
|
import org.lwjgl.glfw.GLFW;
|
||||||
import org.muellerssoftware.openproximitychatfabric.OPCFabric;
|
import org.muellerssoftware.openproximitychat.common.Logging;
|
||||||
import org.muellerssoftware.openproximitychatfabric.connect.HandshakeBuilder;
|
import org.muellerssoftware.openproximitychat.fabric.OPCFabric;
|
||||||
import org.muellerssoftware.openproximitychatfabric.mixins.ClientConnectionInvoker;
|
import org.muellerssoftware.openproximitychat.fabric.connect.HandshakeBuilder;
|
||||||
import org.muellerssoftware.openproximitychatfabric.voice.VoiceServer;
|
import org.muellerssoftware.openproximitychat.fabric.mixins.ClientConnectionInvoker;
|
||||||
|
import org.muellerssoftware.openproximitychat.common.VoiceServer;
|
||||||
|
|
||||||
@Environment(EnvType.CLIENT)
|
@Environment(EnvType.CLIENT)
|
||||||
public class OPCFabricClient implements ClientModInitializer {
|
public class OPCFabricClient implements ClientModInitializer {
|
||||||
@ -30,6 +31,8 @@ public class OPCFabricClient implements ClientModInitializer {
|
|||||||
};
|
};
|
||||||
@Override
|
@Override
|
||||||
public void onInitializeClient() {
|
public void onInitializeClient() {
|
||||||
|
Logging.INSTANCE.setLogger(OPCFabric.LOGGER);
|
||||||
|
|
||||||
keyBinding = KeyBindingHelper.registerKeyBinding(
|
keyBinding = KeyBindingHelper.registerKeyBinding(
|
||||||
new KeyBinding(
|
new KeyBinding(
|
||||||
"key.openproximitychatfabric.sendhandshake",
|
"key.openproximitychatfabric.sendhandshake",
|
@ -1,4 +1,4 @@
|
|||||||
package org.muellerssoftware.openproximitychatfabric.connect;
|
package org.muellerssoftware.openproximitychat.fabric.connect;
|
||||||
|
|
||||||
public enum ConnectionFilterType {
|
public enum ConnectionFilterType {
|
||||||
Friend,
|
Friend,
|
@ -1,8 +1,8 @@
|
|||||||
package org.muellerssoftware.openproximitychatfabric.connect;
|
package org.muellerssoftware.openproximitychat.fabric.connect;
|
||||||
|
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
import org.muellerssoftware.openproximitychatfabric.voice.VoiceClient;
|
import org.muellerssoftware.openproximitychat.common.VoiceServer;
|
||||||
import org.muellerssoftware.openproximitychatfabric.voice.VoiceServer;
|
import org.muellerssoftware.openproximitychat.common.VoiceClient;
|
||||||
|
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
|
|
||||||
@ -32,6 +32,6 @@ public class Handshake {
|
|||||||
|
|
||||||
|
|
||||||
VoiceServer.INSTANCE.getHandshook().put(player.getUuid(), address.getAddress());
|
VoiceServer.INSTANCE.getHandshook().put(player.getUuid(), address.getAddress());
|
||||||
voiceClient = new VoiceClient(new io.ktor.network.sockets.InetSocketAddress(address.getHostName(), address.getPort()), player.getUuid());
|
voiceClient = new VoiceClient(new InetSocketAddress(address.getHostName(), address.getPort()), player.getUuid());
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,8 +1,8 @@
|
|||||||
package org.muellerssoftware.openproximitychatfabric.connect;
|
package org.muellerssoftware.openproximitychat.fabric.connect;
|
||||||
|
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.muellerssoftware.openproximitychatfabric.OPCFabric;
|
import org.muellerssoftware.openproximitychat.fabric.OPCFabric;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
@ -1,4 +1,4 @@
|
|||||||
package org.muellerssoftware.openproximitychatfabric.connect;
|
package org.muellerssoftware.openproximitychat.fabric.connect;
|
||||||
|
|
||||||
public class HandshakeException extends Exception {
|
public class HandshakeException extends Exception {
|
||||||
HandshakeException(String message) {
|
HandshakeException(String message) {
|
@ -1,10 +1,10 @@
|
|||||||
package org.muellerssoftware.openproximitychatfabric.mixins;
|
package org.muellerssoftware.openproximitychat.fabric.mixins;
|
||||||
|
|
||||||
import net.minecraft.client.MinecraftClient;
|
import net.minecraft.client.MinecraftClient;
|
||||||
import net.minecraft.network.listener.ClientPlayPacketListener;
|
import net.minecraft.network.listener.ClientPlayPacketListener;
|
||||||
import net.minecraft.network.message.SignedMessage;
|
import net.minecraft.network.message.SignedMessage;
|
||||||
import net.minecraft.network.packet.s2c.play.ChatMessageS2CPacket;
|
import net.minecraft.network.packet.s2c.play.ChatMessageS2CPacket;
|
||||||
import org.muellerssoftware.openproximitychatfabric.OPCFabric;
|
import org.muellerssoftware.openproximitychat.fabric.OPCFabric;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
import org.spongepowered.asm.mixin.injection.At;
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
import org.spongepowered.asm.mixin.injection.Inject;
|
import org.spongepowered.asm.mixin.injection.Inject;
|
@ -1,4 +1,4 @@
|
|||||||
package org.muellerssoftware.openproximitychatfabric.mixins;
|
package org.muellerssoftware.openproximitychat.fabric.mixins;
|
||||||
|
|
||||||
import net.minecraft.network.ClientConnection;
|
import net.minecraft.network.ClientConnection;
|
||||||
import net.minecraft.network.Packet;
|
import net.minecraft.network.Packet;
|
@ -1,4 +1,4 @@
|
|||||||
package org.muellerssoftware.openproximitychatfabric.mixins;
|
package org.muellerssoftware.openproximitychat.fabric.mixins;
|
||||||
|
|
||||||
import net.minecraft.entity.LivingEntity;
|
import net.minecraft.entity.LivingEntity;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
@ -6,12 +6,6 @@ import org.spongepowered.asm.mixin.gen.Accessor;
|
|||||||
|
|
||||||
@Mixin(LivingEntity.class)
|
@Mixin(LivingEntity.class)
|
||||||
public interface LivingEntityAccessor {
|
public interface LivingEntityAccessor {
|
||||||
@Accessor("bodyTrackingIncrements")
|
|
||||||
int getBodyTrackingIncrements();
|
|
||||||
|
|
||||||
@Accessor("headTrackingIncrements")
|
|
||||||
int getHeadTrackingIncrements();
|
|
||||||
|
|
||||||
@Accessor("serverHeadYaw")
|
@Accessor("serverHeadYaw")
|
||||||
double getServerHeadYaw();
|
double getServerHeadYaw();
|
||||||
|
|
@ -1,13 +1,13 @@
|
|||||||
package org.muellerssoftware.openproximitychatfabric.mixins;
|
package org.muellerssoftware.openproximitychat.fabric.mixins;
|
||||||
|
|
||||||
import net.minecraft.client.MinecraftClient;
|
import net.minecraft.client.MinecraftClient;
|
||||||
import net.minecraft.client.network.OtherClientPlayerEntity;
|
import net.minecraft.client.network.OtherClientPlayerEntity;
|
||||||
import org.muellerssoftware.openproximitychatfabric.OPCFabric;
|
import org.muellerssoftware.openproximitychat.fabric.OPCFabric;
|
||||||
import org.muellerssoftware.openproximitychatfabric.connect.Handshake;
|
import org.muellerssoftware.openproximitychat.fabric.connect.Handshake;
|
||||||
import org.muellerssoftware.openproximitychatfabric.connect.HandshakeBuilder;
|
import org.muellerssoftware.openproximitychat.fabric.connect.HandshakeBuilder;
|
||||||
import org.muellerssoftware.openproximitychatfabric.connect.HandshakeException;
|
import org.muellerssoftware.openproximitychat.fabric.connect.HandshakeException;
|
||||||
import org.muellerssoftware.openproximitychatfabric.voice.UPnPManager;
|
import org.muellerssoftware.openproximitychat.common.UPnPManager;
|
||||||
import org.muellerssoftware.openproximitychatfabric.voice.VoiceServer;
|
import org.muellerssoftware.openproximitychat.common.VoiceServer;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
import org.spongepowered.asm.mixin.injection.At;
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
import org.spongepowered.asm.mixin.injection.Inject;
|
import org.spongepowered.asm.mixin.injection.Inject;
|
@ -1,12 +1,11 @@
|
|||||||
{
|
{
|
||||||
"required": true,
|
"required": true,
|
||||||
"minVersion": "0.8",
|
"minVersion": "0.8",
|
||||||
"package": "org.muellerssoftware.openproximitychatfabric.mixins",
|
"package": "org.muellerssoftware.openproximitychat.fabric.mixins",
|
||||||
"compatibilityLevel": "JAVA_17",
|
"compatibilityLevel": "JAVA_17",
|
||||||
"mixins": [
|
"mixins": [
|
||||||
],
|
],
|
||||||
"client": [
|
"client": [
|
||||||
"PlayerMoveMixin",
|
|
||||||
"LivingEntityAccessor",
|
"LivingEntityAccessor",
|
||||||
"OtherClientPlayerEntityMixin",
|
"OtherClientPlayerEntityMixin",
|
||||||
"ClientConnectionInvoker",
|
"ClientConnectionInvoker",
|
@ -11,10 +11,10 @@
|
|||||||
"environment": "*",
|
"environment": "*",
|
||||||
"entrypoints": {
|
"entrypoints": {
|
||||||
"client": [
|
"client": [
|
||||||
"org.muellerssoftware.openproximitychatfabric.client.OPCFabricClient"
|
"org.muellerssoftware.openproximitychat.fabric.client.OPCFabricClient"
|
||||||
],
|
],
|
||||||
"main": [
|
"main": [
|
||||||
"org.muellerssoftware.openproximitychatfabric.OPCFabric"
|
"org.muellerssoftware.openproximitychat.fabric.OPCFabric"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"mixins": [
|
"mixins": [
|
118
forge/.gitignore
vendored
Normal file
118
forge/.gitignore
vendored
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
# User-specific stuff
|
||||||
|
.idea/
|
||||||
|
|
||||||
|
*.iml
|
||||||
|
*.ipr
|
||||||
|
*.iws
|
||||||
|
|
||||||
|
# IntelliJ
|
||||||
|
out/
|
||||||
|
# mpeltonen/sbt-idea plugin
|
||||||
|
.idea_modules/
|
||||||
|
|
||||||
|
# JIRA plugin
|
||||||
|
atlassian-ide-plugin.xml
|
||||||
|
|
||||||
|
# Compiled class file
|
||||||
|
*.class
|
||||||
|
|
||||||
|
# Log file
|
||||||
|
*.log
|
||||||
|
|
||||||
|
# BlueJ files
|
||||||
|
*.ctxt
|
||||||
|
|
||||||
|
# Package Files #
|
||||||
|
*.jar
|
||||||
|
*.war
|
||||||
|
*.nar
|
||||||
|
*.ear
|
||||||
|
*.zip
|
||||||
|
*.tar.gz
|
||||||
|
*.rar
|
||||||
|
|
||||||
|
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
|
||||||
|
hs_err_pid*
|
||||||
|
|
||||||
|
*~
|
||||||
|
|
||||||
|
# temporary files which can be created if a process still has a handle open of a deleted file
|
||||||
|
.fuse_hidden*
|
||||||
|
|
||||||
|
# KDE directory preferences
|
||||||
|
.directory
|
||||||
|
|
||||||
|
# Linux trash folder which might appear on any partition or disk
|
||||||
|
.Trash-*
|
||||||
|
|
||||||
|
# .nfs files are created when an open file is removed but is still being accessed
|
||||||
|
.nfs*
|
||||||
|
|
||||||
|
# General
|
||||||
|
.DS_Store
|
||||||
|
.AppleDouble
|
||||||
|
.LSOverride
|
||||||
|
|
||||||
|
# Icon must end with two \r
|
||||||
|
Icon
|
||||||
|
|
||||||
|
# Thumbnails
|
||||||
|
._*
|
||||||
|
|
||||||
|
# Files that might appear in the root of a volume
|
||||||
|
.DocumentRevisions-V100
|
||||||
|
.fseventsd
|
||||||
|
.Spotlight-V100
|
||||||
|
.TemporaryItems
|
||||||
|
.Trashes
|
||||||
|
.VolumeIcon.icns
|
||||||
|
.com.apple.timemachine.donotpresent
|
||||||
|
|
||||||
|
# Directories potentially created on remote AFP share
|
||||||
|
.AppleDB
|
||||||
|
.AppleDesktop
|
||||||
|
Network Trash Folder
|
||||||
|
Temporary Items
|
||||||
|
.apdisk
|
||||||
|
|
||||||
|
# Windows thumbnail cache files
|
||||||
|
Thumbs.db
|
||||||
|
Thumbs.db:encryptable
|
||||||
|
ehthumbs.db
|
||||||
|
ehthumbs_vista.db
|
||||||
|
|
||||||
|
# Dump file
|
||||||
|
*.stackdump
|
||||||
|
|
||||||
|
# Folder config file
|
||||||
|
[Dd]esktop.ini
|
||||||
|
|
||||||
|
# Recycle Bin used on file shares
|
||||||
|
$RECYCLE.BIN/
|
||||||
|
|
||||||
|
# Windows Installer files
|
||||||
|
*.cab
|
||||||
|
*.msi
|
||||||
|
*.msix
|
||||||
|
*.msm
|
||||||
|
*.msp
|
||||||
|
|
||||||
|
# Windows shortcuts
|
||||||
|
*.lnk
|
||||||
|
|
||||||
|
.gradle
|
||||||
|
build/
|
||||||
|
|
||||||
|
# Ignore Gradle GUI config
|
||||||
|
gradle-app.setting
|
||||||
|
|
||||||
|
# Cache of project
|
||||||
|
.gradletasknamecache
|
||||||
|
|
||||||
|
**/build/
|
||||||
|
|
||||||
|
# Common working directory
|
||||||
|
run/
|
||||||
|
|
||||||
|
# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
|
||||||
|
!gradle-wrapper.jar
|
127
forge/build.gradle
Normal file
127
forge/build.gradle
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
plugins {
|
||||||
|
id 'net.minecraftforge.gradle' version '5.1.+'
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
group = 'org.muellerssoftware.openproximitychat'
|
||||||
|
version = '1.0-SNAPSHOT'
|
||||||
|
|
||||||
|
java {
|
||||||
|
archivesBaseName = 'forge'
|
||||||
|
toolchain.languageVersion = JavaLanguageVersion.of(8)
|
||||||
|
}
|
||||||
|
|
||||||
|
minecraft {
|
||||||
|
// The mappings can be changed at any time and must be in the following format.
|
||||||
|
// Channel: Version:
|
||||||
|
// official MCVersion Official field/method names from Mojang mapping files
|
||||||
|
// parchment YYYY.MM.DD-MCVersion Open community-sourced parameter names and javadocs layered on top of official
|
||||||
|
//
|
||||||
|
// You must be aware of the Mojang license when using the 'official' or 'parchment' mappings.
|
||||||
|
// See more information here: https://github.com/MinecraftForge/MCPConfig/blob/master/Mojang.md
|
||||||
|
//
|
||||||
|
// Parchment is an unofficial project maintained by ParchmentMC, separate from MinecraftForge
|
||||||
|
// Additional setup is needed to use their mappings: https://github.com/ParchmentMC/Parchment/wiki/Getting-Started
|
||||||
|
//
|
||||||
|
// Use non-default mappings at your own risk. They may not always work.
|
||||||
|
// Simply re-run your setup task after changing the mappings to update your workspace.
|
||||||
|
mappings channel: 'stable', version: '39-1.12'
|
||||||
|
|
||||||
|
// accessTransformer = file('src/main/resources/META-INF/accesstransformer.cfg')
|
||||||
|
|
||||||
|
// Default run configurations.
|
||||||
|
// These can be tweaked, removed, or duplicated as needed.
|
||||||
|
runs {
|
||||||
|
client {
|
||||||
|
workingDirectory project.file('run')
|
||||||
|
|
||||||
|
// Recommended logging data for a userdev environment
|
||||||
|
// The markers can be added/remove as needed separated by commas.
|
||||||
|
// "SCAN": For mods scan.
|
||||||
|
// "REGISTRIES": For firing of registry events.
|
||||||
|
// "REGISTRYDUMP": For getting the contents of all registries.
|
||||||
|
property 'forge.logging.markers', 'REGISTRIES'
|
||||||
|
|
||||||
|
|
||||||
|
// Recommended logging level for the console
|
||||||
|
// You can set various levels here.
|
||||||
|
// Please read: https://stackoverflow.com/questions/2031163/when-to-use-the-different-log-levels
|
||||||
|
property 'forge.logging.console.level', 'debug'
|
||||||
|
|
||||||
|
|
||||||
|
mods {
|
||||||
|
forge {
|
||||||
|
source sourceSets.main
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
server {
|
||||||
|
workingDirectory project.file('run')
|
||||||
|
|
||||||
|
property 'forge.logging.markers', 'REGISTRIES'
|
||||||
|
|
||||||
|
property 'forge.logging.console.level', 'debug'
|
||||||
|
|
||||||
|
|
||||||
|
mods {
|
||||||
|
forge {
|
||||||
|
source sourceSets.main
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Include resources generated by data generators.
|
||||||
|
sourceSets.main.resources { srcDir 'src/generated/resources' }
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
// Put repositories for dependencies here
|
||||||
|
// ForgeGradle automatically adds the Forge maven and Maven Central for you
|
||||||
|
|
||||||
|
// If you have mod jar dependencies in ./libs, you can declare them as a repository like so:
|
||||||
|
// flatDir {
|
||||||
|
// dir 'libs'
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
// Specify the version of Minecraft to use. If this is any group other than 'net.minecraft' it is assumed
|
||||||
|
// that the dep is a ForgeGradle 'patcher' dependency, and its patches will be applied.
|
||||||
|
// The userdev artifact is a special name and will get all sorts of transformations applied to it.
|
||||||
|
minecraft 'net.minecraftforge:forge:1.12.2-14.23.5.2860'
|
||||||
|
|
||||||
|
// Real mod deobf dependency examples - these get remapped to your current mappings
|
||||||
|
// compileOnly fg.deobf("mezz.jei:jei-${mc_version}:${jei_version}:api") // Adds JEI API as a compile dependency
|
||||||
|
// runtimeOnly fg.deobf("mezz.jei:jei-${mc_version}:${jei_version}") // Adds the full JEI mod as a runtime dependency
|
||||||
|
// implementation fg.deobf("com.tterrag.registrate:Registrate:MC${mc_version}-${registrate_version}") // Adds registrate as a dependency
|
||||||
|
|
||||||
|
// Examples using mod jars from ./libs
|
||||||
|
// implementation fg.deobf("blank:coolmod-${mc_version}:${coolmod_version}")
|
||||||
|
|
||||||
|
// For more info...
|
||||||
|
// http://www.gradle.org/docs/current/userguide/artifact_dependencies_tutorial.html
|
||||||
|
// http://www.gradle.org/docs/current/userguide/dependency_management.html
|
||||||
|
}
|
||||||
|
|
||||||
|
// Example for how to get properties into the manifest for reading at runtime.
|
||||||
|
jar {
|
||||||
|
manifest {
|
||||||
|
attributes([
|
||||||
|
"Specification-Title" : "forge",
|
||||||
|
//"Specification-Vendor": "forge authors",
|
||||||
|
"Specification-Version" : "1", // We are version 1 of ourselves
|
||||||
|
"Implementation-Title" : project.name,
|
||||||
|
"Implementation-Version" : project.jar.archiveVersion,
|
||||||
|
//"Implementation-Vendor": "forge authors",
|
||||||
|
"Implementation-Timestamp": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ")
|
||||||
|
])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
jar.finalizedBy('reobfJar')
|
||||||
|
|
||||||
|
tasks.withType(JavaCompile).configureEach {
|
||||||
|
options.encoding = 'UTF-8' // Use the UTF-8 charset for Java compilation
|
||||||
|
}
|
@ -0,0 +1,113 @@
|
|||||||
|
package org.muellerssoftware.openproximitychat.forge;
|
||||||
|
|
||||||
|
import net.minecraft.block.Block;
|
||||||
|
import net.minecraft.item.Item;
|
||||||
|
import net.minecraftforge.event.RegistryEvent;
|
||||||
|
import net.minecraftforge.fml.common.event.FMLInitializationEvent;
|
||||||
|
import net.minecraftforge.fml.common.event.FMLPostInitializationEvent;
|
||||||
|
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
|
||||||
|
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
|
||||||
|
import net.minecraftforge.fml.common.Mod;
|
||||||
|
import net.minecraftforge.fml.common.registry.GameRegistry;
|
||||||
|
|
||||||
|
@Mod(
|
||||||
|
modid = Forge.MOD_ID,
|
||||||
|
name = Forge.MOD_NAME,
|
||||||
|
version = Forge.VERSION
|
||||||
|
)
|
||||||
|
public class Forge {
|
||||||
|
|
||||||
|
public static final String MOD_ID = "forge";
|
||||||
|
public static final String MOD_NAME = "Forge";
|
||||||
|
public static final String VERSION = "1.0-SNAPSHOT";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is the instance of your mod as created by Forge. It will never be null.
|
||||||
|
*/
|
||||||
|
@Mod.Instance(MOD_ID)
|
||||||
|
public static Forge INSTANCE;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is the first initialization event. Register tile entities here.
|
||||||
|
* The registry events below will have fired prior to entry to this method.
|
||||||
|
*/
|
||||||
|
@Mod.EventHandler
|
||||||
|
public void preinit(FMLPreInitializationEvent event) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is the second initialization event. Register custom recipes
|
||||||
|
*/
|
||||||
|
@Mod.EventHandler
|
||||||
|
public void init(FMLInitializationEvent event) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is the final initialization event. Register actions from other mods here
|
||||||
|
*/
|
||||||
|
@Mod.EventHandler
|
||||||
|
public void postinit(FMLPostInitializationEvent event) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Forge will automatically look up and bind blocks to the fields in this class
|
||||||
|
* based on their registry name.
|
||||||
|
*/
|
||||||
|
@GameRegistry.ObjectHolder(MOD_ID)
|
||||||
|
public static class Blocks {
|
||||||
|
/*
|
||||||
|
public static final MySpecialBlock mySpecialBlock = null; // placeholder for special block below
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Forge will automatically look up and bind items to the fields in this class
|
||||||
|
* based on their registry name.
|
||||||
|
*/
|
||||||
|
@GameRegistry.ObjectHolder(MOD_ID)
|
||||||
|
public static class Items {
|
||||||
|
/*
|
||||||
|
public static final ItemBlock mySpecialBlock = null; // itemblock for the block above
|
||||||
|
public static final MySpecialItem mySpecialItem = null; // placeholder for special item below
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is a special class that listens to registry events, to allow creation of mod blocks and items at the proper time.
|
||||||
|
*/
|
||||||
|
@Mod.EventBusSubscriber
|
||||||
|
public static class ObjectRegistryHandler {
|
||||||
|
/**
|
||||||
|
* Listen for the register event for creating custom items
|
||||||
|
*/
|
||||||
|
@SubscribeEvent
|
||||||
|
public static void addItems(RegistryEvent.Register<Item> event) {
|
||||||
|
/*
|
||||||
|
event.getRegistry().register(new ItemBlock(Blocks.myBlock).setRegistryName(MOD_ID, "myBlock"));
|
||||||
|
event.getRegistry().register(new MySpecialItem().setRegistryName(MOD_ID, "mySpecialItem"));
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Listen for the register event for creating custom blocks
|
||||||
|
*/
|
||||||
|
@SubscribeEvent
|
||||||
|
public static void addBlocks(RegistryEvent.Register<Block> event) {
|
||||||
|
/*
|
||||||
|
event.getRegistry().register(new MySpecialBlock().setRegistryName(MOD_ID, "mySpecialBlock"));
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* EXAMPLE ITEM AND BLOCK - you probably want these in separate files
|
||||||
|
public static class MySpecialItem extends Item {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class MySpecialBlock extends Block {
|
||||||
|
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
16
forge/src/main/resources/mcmod.info
Normal file
16
forge/src/main/resources/mcmod.info
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"modid": "forge",
|
||||||
|
"name": "Forge",
|
||||||
|
"description": "",
|
||||||
|
"version": "${version}",
|
||||||
|
"mcversion": "${mcversion}",
|
||||||
|
"url": "",
|
||||||
|
"updateUrl": "",
|
||||||
|
"authorList": [],
|
||||||
|
"credits": "",
|
||||||
|
"logoFile": "",
|
||||||
|
"screenshots": [],
|
||||||
|
"dependencies": []
|
||||||
|
}
|
||||||
|
]
|
@ -1,9 +1,15 @@
|
|||||||
rootProject.name = "OpenProximityChatFabric"
|
rootProject.name = "OpenProximityChat"
|
||||||
|
|
||||||
|
include("forge", "fabric", "common")
|
||||||
|
|
||||||
pluginManagement {
|
pluginManagement {
|
||||||
repositories {
|
repositories {
|
||||||
maven("https://maven.fabricmc.net/") {
|
maven("https://maven.fabricmc.net/") {
|
||||||
name = "Fabric"
|
name = "Fabric"
|
||||||
}
|
}
|
||||||
|
maven("https://maven.minecraftforge.net/") {
|
||||||
|
name = "Forge"
|
||||||
|
}
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
gradlePluginPortal()
|
gradlePluginPortal()
|
||||||
}
|
}
|
||||||
@ -17,4 +23,5 @@ pluginManagement {
|
|||||||
.split("+kotlin.")[1] // Grabs the sentence after `+kotlin.`
|
.split("+kotlin.")[1] // Grabs the sentence after `+kotlin.`
|
||||||
.split("+")[0] // Ensures sentences like `+build.1` are ignored
|
.split("+")[0] // Ensures sentences like `+build.1` are ignored
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
include("common")
|
||||||
|
Loading…
Reference in New Issue
Block a user