Skip to content

Commit

Permalink
0.1.3 - Added IRC
Browse files Browse the repository at this point in the history
  • Loading branch information
ya-ilya committed May 17, 2023
1 parent 23efbd9 commit d091b42
Show file tree
Hide file tree
Showing 20 changed files with 455 additions and 33 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,6 @@ jobs:
with:
name: progreso
path: |
./progreso-client/build/libs/*all.jar
./progreso-client/build/libs/*api.jar
./progreso-client/build/libs/*api-source.jar
./progreso-client/build/libs/progreso-client.jar
./progreso-client/build/libs/progreso-client-api.jar
./progreso-client/build/libs/progreso-client-api-source.jar
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,5 @@ This utility mod not ready to use. So for now it's just an experiment
### Development

- `progreso-api` ([source](https://github.com/ya-ilya/progreso/tree/main/progreso-api)) - Api for `progreso-client`. Shouldn't interact with **minecraft**/**modding api** classes.
- `progreso-client` ([source](https://github.com/ya-ilya/progreso/tree/main/progreso-client)) - Client. Uses `progreso-api` as base.
- `progreso-client` ([source](https://github.com/ya-ilya/progreso/tree/main/progreso-client)) - Client. Uses `progreso-api` as base.
- `progreso-irc-server` ([source](https://github.com/ya-ilya/progreso/tree/main/progreso-irc-server)) - Implementation of IRCServer.
1 change: 1 addition & 0 deletions progreso-api/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@ repositories {
dependencies {
api("com.google.code.gson:gson:2.10.1")
api("com.mojang:brigadier:1.0.18")
api("org.java-websocket:Java-WebSocket:1.5.3")
}
22 changes: 22 additions & 0 deletions progreso-api/src/main/kotlin/org/progreso/api/irc/IRCClient.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package org.progreso.api.irc

import org.java_websocket.client.WebSocketClient
import org.java_websocket.handshake.ServerHandshake
import org.progreso.api.irc.packet.IRCPacket
import java.net.URI

open class IRCClient(serverUri: URI) : WebSocketClient(serverUri) {
open fun onPacket(packet: IRCPacket) {}

override fun onOpen(handshakedata: ServerHandshake) { }
override fun onClose(code: Int, reason: String, remote: Boolean) { }
override fun onError(ex: Exception) { }

override fun onMessage(message: String) {
onPacket(IRCPacket.GSON.fromJson(message, IRCPacket::class.java))
}

fun send(packet: IRCPacket) {
send(IRCPacket.GSON.toJson(packet, IRCPacket::class.java))
}
}
28 changes: 28 additions & 0 deletions progreso-api/src/main/kotlin/org/progreso/api/irc/IRCServer.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package org.progreso.api.irc

import org.java_websocket.WebSocket
import org.java_websocket.handshake.ClientHandshake
import org.java_websocket.server.WebSocketServer
import org.progreso.api.irc.packet.IRCPacket
import java.net.InetSocketAddress

open class IRCServer(address: InetSocketAddress) : WebSocketServer(address) {
open fun onPacket(socket: WebSocket, packet: IRCPacket) {}

override fun onOpen(conn: WebSocket, handshake: ClientHandshake) {}
override fun onClose(conn: WebSocket, code: Int, reason: String, remote: Boolean) {}
override fun onError(conn: WebSocket?, ex: Exception) {}
override fun onStart() {}

override fun onMessage(conn: WebSocket, message: String) {
onPacket(conn, IRCPacket.GSON.fromJson(message, IRCPacket::class.java))
}

fun send(packet: IRCPacket) {
connections.forEach { it.send(packet) }
}

fun WebSocket.send(packet: IRCPacket) {
send(IRCPacket.GSON.toJson(packet, IRCPacket::class.java))
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package org.progreso.api.irc.packet

import com.google.gson.GsonBuilder
import org.progreso.api.irc.packet.packets.IRCAuthFailedPacket
import org.progreso.api.irc.packet.packets.IRCAuthPacket
import org.progreso.api.irc.packet.packets.IRCMessagePacket
import org.progreso.api.irc.typeadapters.RuntimeTypeAdapterFactory

interface IRCPacket {
companion object {
private val GSON_FACTORY = RuntimeTypeAdapterFactory.of(IRCPacket::class.java)
.registerSubtype(IRCAuthFailedPacket::class.java)
.registerSubtype(IRCAuthPacket::class.java)
.registerSubtype(IRCMessagePacket::class.java)

val GSON = GsonBuilder()
.registerTypeAdapterFactory(GSON_FACTORY)
.create()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package org.progreso.api.irc.packet.packets

import org.progreso.api.irc.packet.IRCPacket

data class IRCAuthFailedPacket(val reason: String) : IRCPacket
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package org.progreso.api.irc.packet.packets

import org.progreso.api.irc.packet.IRCPacket

data class IRCAuthPacket(val username: String) : IRCPacket
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package org.progreso.api.irc.packet.packets

import org.progreso.api.irc.packet.IRCPacket

data class IRCMessagePacket(val author: String, val message: String) : IRCPacket
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
/*
* Copyright (C) 2011 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.progreso.api.irc.typeadapters

import com.google.gson.*
import com.google.gson.reflect.TypeToken
import com.google.gson.stream.JsonReader
import com.google.gson.stream.JsonWriter
import java.io.IOException

/**
* Adapts values whose runtime type may differ from their declaration type. This
* is necessary when a field's type is not the same type that GSON should create
* when deserializing that field.
*/
@Suppress("UNCHECKED_CAST", "unused", "MemberVisibilityCanBePrivate")
class RuntimeTypeAdapterFactory<T> private constructor(
baseType: Class<*>?,
typeFieldName: String?,
maintainType: Boolean
) : TypeAdapterFactory {
private val baseType: Class<*>
private val typeFieldName: String
private val labelToSubtype: MutableMap<String, Class<*>> = LinkedHashMap()
private val subtypeToLabel: MutableMap<Class<*>, String> = LinkedHashMap()
private val maintainType: Boolean
private var recognizeSubtypes = false

init {
if (typeFieldName == null || baseType == null) {
throw NullPointerException()
}

this.baseType = baseType
this.typeFieldName = typeFieldName
this.maintainType = maintainType
}

/**
* Ensures that this factory will handle not just the given `baseType`, but any subtype
* of that type.
*/
fun recognizeSubtypes(): RuntimeTypeAdapterFactory<T> {
recognizeSubtypes = true
return this
}

/**
* Registers `type` identified by `label`. Labels are case
* sensitive.
*
* @throws IllegalArgumentException if either `type` or `label`
* have already been registered on this type adapter.
*/
fun registerSubtype(type: Class<out T>?, label: String?): RuntimeTypeAdapterFactory<T> {
if (type == null || label == null) {
throw NullPointerException()
}
if (subtypeToLabel.containsKey(type) || labelToSubtype.containsKey(label)) {
throw IllegalArgumentException("types and labels must be unique")
}
labelToSubtype[label] = type
subtypeToLabel[type] = label
return this
}

/**
* Registers `type` identified by its [simple][Class.getSimpleName]. Labels are case sensitive.
*
* @throws IllegalArgumentException if either `type` or its simple name
* have already been registered on this type adapter.
*/
fun registerSubtype(type: Class<out T>): RuntimeTypeAdapterFactory<T> {
return registerSubtype(type, type.simpleName)
}

override fun <R : Any> create(gson: Gson, type: TypeToken<R>): TypeAdapter<R>? {
val rawType: Class<*> = type.rawType
val handle = if (recognizeSubtypes) baseType.isAssignableFrom(rawType) else baseType == rawType
if (!handle) return null
val jsonElementAdapter = gson.getAdapter(JsonElement::class.java)
val labelToDelegate: MutableMap<String, TypeAdapter<*>> = LinkedHashMap()
val subtypeToDelegate: MutableMap<Class<*>, TypeAdapter<*>> = LinkedHashMap()

for (entry: Map.Entry<String, Class<*>> in labelToSubtype.entries) {
val delegate = gson.getDelegateAdapter(this, TypeToken.get(entry.value))
labelToDelegate[entry.key] = delegate
subtypeToDelegate[entry.value] = delegate
}

return object : TypeAdapter<R>() {
@Throws(IOException::class)
override fun read(`in`: JsonReader): R {
val jsonElement = jsonElementAdapter.read(`in`)
val labelJsonElement = if (maintainType) {
jsonElement.asJsonObject[typeFieldName]
} else {
jsonElement.asJsonObject.remove(typeFieldName)
}

if (labelJsonElement == null) {
throw JsonParseException("Cannot deserialize $baseType because it does not define a field named $typeFieldName")
}

val label = labelJsonElement.asString
val delegate = labelToDelegate[label] as TypeAdapter<R>?
?: throw JsonParseException("Cannot deserialize $baseType subtype named $label; did you forget to register a subtype?")

return delegate.fromJsonTree(jsonElement)
}

@Throws(IOException::class)
override fun write(out: JsonWriter, value: R) {
val srcType: Class<*> = value.javaClass
val label = subtypeToLabel[srcType]
val delegate = subtypeToDelegate[srcType] as TypeAdapter<R>?
?: throw JsonParseException("cannot serialize ${srcType.name}; did you forget to register a subtype?")
val jsonObject = delegate.toJsonTree(value).asJsonObject
if (maintainType) {
jsonElementAdapter.write(out, jsonObject)
return
}
val clone = JsonObject()
if (jsonObject.has(typeFieldName)) {
throw JsonParseException("cannot serialize ${srcType.name} because it already defines a field named $typeFieldName")
}
clone.add(typeFieldName, JsonPrimitive(label))
for (e: Map.Entry<String?, JsonElement?> in jsonObject.entrySet()) {
clone.add(e.key, e.value)
}
jsonElementAdapter.write(out, clone)
}
}.nullSafe()
}

companion object {
/**
* Creates a new runtime type adapter using for `baseType` using `typeFieldName` as the type field name. Type field names are case sensitive.
*
* @param maintainType true if the type field should be included in deserialized objects
*/
fun <T> of(baseType: Class<T>?, typeFieldName: String?, maintainType: Boolean): RuntimeTypeAdapterFactory<T> {
return RuntimeTypeAdapterFactory(baseType, typeFieldName, maintainType)
}

/**
* Creates a new runtime type adapter using for `baseType` using `typeFieldName` as the type field name. Type field names are case sensitive.
*/
fun <T> of(baseType: Class<T>?, typeFieldName: String?): RuntimeTypeAdapterFactory<T> {
return RuntimeTypeAdapterFactory(baseType, typeFieldName, false)
}

/**
* Creates a new runtime type adapter for `baseType` using `"type"` as
* the type field name.
*/
fun <T> of(baseType: Class<T>?): RuntimeTypeAdapterFactory<T> {
return RuntimeTypeAdapterFactory(baseType, "type", false)
}
}
}
39 changes: 16 additions & 23 deletions progreso-client/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar

val mixinVersion: String by project
val forgeVersion: String by project
val mappingsChannel: String by project
Expand All @@ -8,14 +6,13 @@ val mappingsVersion: String by project
buildscript {
repositories {
mavenCentral()
maven("https://files.minecraftforge.net/maven/")
maven("https://maven.minecraftforge.net/")
maven("https://repo.spongepowered.org/maven/")
}

dependencies {
classpath("net.minecraftforge.gradle:ForgeGradle:4.+")
classpath("org.spongepowered:mixingradle:0.7-SNAPSHOT")
classpath("com.github.jengelman.gradle.plugins:shadow:6.1.0")
}
}

Expand All @@ -25,7 +22,6 @@ plugins {

apply(plugin = "net.minecraftforge.gradle")
apply(plugin = "org.spongepowered.mixin")
apply(plugin = "com.github.johnrengelman.shadow")

group = "org.progreso"

Expand Down Expand Up @@ -77,20 +73,20 @@ dependencies {
implementation(configurations["library"])
}

tasks.processResources {
from(sourceSets["main"].resources.srcDirs) {
duplicatesStrategy = DuplicatesStrategy.INCLUDE
include("mcmod.info")
expand(
mapOf(
"version" to version,
"mcversion" to "1.12.2"
tasks {
processResources {
from(sourceSets["main"].resources.srcDirs) {
duplicatesStrategy = DuplicatesStrategy.INCLUDE
include("mcmod.info")
expand(
mapOf(
"version" to version,
"mcversion" to "1.12.2"
)
)
)
}
}
}

tasks {
register<Jar>("buildApi") {
group = "progreso"

Expand All @@ -115,7 +111,7 @@ tasks {
dependsOn("buildApi", "buildApiSource", "build")
}

named<ShadowJar>("shadowJar") {
jar {
manifest.attributes(
mapOf(
"Manifest-Version" to 1.0,
Expand All @@ -135,14 +131,11 @@ tasks {
"META-INF/*.kotlin_module",
"LICENSE.txt",
"kotlin/**/*.kotlin_metadata",
"kotlin/**/*.kotlin_builtins",
"META-INF/*.version"
)

configurations = listOf(project.configurations["library"])
}

build {
dependsOn("shadowJar")
from(configurations["library"].map {
if (it.isDirectory) it else zipTree(it)
})
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
import java.util.stream.Collectors;
import java.util.stream.Stream;

@IFMLLoadingPlugin.Name("progreso")
@IFMLLoadingPlugin.MCVersion("1.12.2")
public class MixinLoader implements IFMLLoadingPlugin {
public MixinLoader() throws IOException {
MixinBootstrap.init();
Expand Down
Loading

0 comments on commit d091b42

Please sign in to comment.