Cobblesync GUI and Packet Handler Update
This commit is contained in:
10
build.gradle
10
build.gradle
@@ -47,14 +47,14 @@ dependencies {
|
|||||||
modImplementation "net.fabricmc:fabric-language-kotlin:${project.fabric_kotlin_version}"
|
modImplementation "net.fabricmc:fabric-language-kotlin:${project.fabric_kotlin_version}"
|
||||||
|
|
||||||
// Other Mod Dependencies (e.g., Cobblemon)
|
// Other Mod Dependencies (e.g., Cobblemon)
|
||||||
modImplementation "com.cobblemon:fabric:1.6.0+1.21.1-SNAPSHOT"
|
modImplementation "com.cobblemon:fabric:1.7.2+1.21.1-SNAPSHOT"
|
||||||
|
|
||||||
// JSON and GSON dependencies - add implementation first, then include
|
// JSON and GSON dependencies - add implementation first, then include
|
||||||
implementation "org.json:json:20231013"
|
implementation "org.json:json:20250517"
|
||||||
include "org.json:json:20231013"
|
include "org.json:json:20250517"
|
||||||
|
|
||||||
implementation "com.google.code.gson:gson:2.10.1"
|
implementation "com.google.code.gson:gson:2.13.2"
|
||||||
include "com.google.code.gson:gson:2.10.1"
|
include "com.google.code.gson:gson:2.13.2"
|
||||||
}
|
}
|
||||||
|
|
||||||
processResources {
|
processResources {
|
||||||
|
|||||||
@@ -1,19 +1,19 @@
|
|||||||
# Done to increase the memory available to gradle.
|
# Done to increase the memory available to gradle.
|
||||||
org.gradle.jvmargs=-Xmx1G
|
org.gradle.jvmargs=-Xmx2G
|
||||||
org.gradle.parallel=true
|
org.gradle.parallel=true
|
||||||
|
|
||||||
# Fabric Properties
|
# Fabric Properties
|
||||||
# check these on https://fabricmc.net/develop
|
# check these on https://fabricmc.net/develop
|
||||||
minecraft_version=1.21.1
|
minecraft_version=1.21.1
|
||||||
loader_version=0.16.14
|
loader_version=0.17.2
|
||||||
loom_version=1.10-SNAPSHOT
|
loom_version=1.11-SNAPSHOT
|
||||||
fabric_kotlin_version=1.13.2+kotlin.2.1.20
|
fabric_kotlin_version=1.13.6+kotlin.2.2.20
|
||||||
|
|
||||||
# Mod Properties
|
# Mod Properties
|
||||||
mod_version=1.0.0
|
mod_version=1.5.0
|
||||||
maven_group=co.sirblob
|
maven_group=co.sirblob
|
||||||
archives_base_name=cobblesync
|
archives_base_name=cobblesync
|
||||||
|
|
||||||
# Dependencies
|
# Dependencies
|
||||||
fabric_version=0.116.0+1.21.1
|
fabric_version=0.116.6+1.21.1
|
||||||
|
|
||||||
|
|||||||
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Binary file not shown.
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@@ -1,6 +1,6 @@
|
|||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.12.1-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14-bin.zip
|
||||||
networkTimeout=10000
|
networkTimeout=10000
|
||||||
validateDistributionUrl=true
|
validateDistributionUrl=true
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
|
|||||||
9
gradlew
vendored
9
gradlew
vendored
@@ -1,7 +1,7 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
#
|
#
|
||||||
# Copyright © 2015-2021 the original authors.
|
# Copyright © 2015 the original authors.
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
# you may not use this file except in compliance with the License.
|
# you may not use this file except in compliance with the License.
|
||||||
@@ -114,7 +114,6 @@ case "$( uname )" in #(
|
|||||||
NONSTOP* ) nonstop=true ;;
|
NONSTOP* ) nonstop=true ;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
|
||||||
|
|
||||||
|
|
||||||
# Determine the Java command to use to start the JVM.
|
# Determine the Java command to use to start the JVM.
|
||||||
@@ -172,7 +171,6 @@ fi
|
|||||||
# For Cygwin or MSYS, switch paths to Windows format before running java
|
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||||
if "$cygwin" || "$msys" ; then
|
if "$cygwin" || "$msys" ; then
|
||||||
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
|
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
|
||||||
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
|
|
||||||
|
|
||||||
JAVACMD=$( cygpath --unix "$JAVACMD" )
|
JAVACMD=$( cygpath --unix "$JAVACMD" )
|
||||||
|
|
||||||
@@ -205,15 +203,14 @@ fi
|
|||||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||||
|
|
||||||
# Collect all arguments for the java command:
|
# Collect all arguments for the java command:
|
||||||
# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
|
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
|
||||||
# and any embedded shellness will be escaped.
|
# and any embedded shellness will be escaped.
|
||||||
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
|
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
|
||||||
# treated as '${Hostname}' itself on the command line.
|
# treated as '${Hostname}' itself on the command line.
|
||||||
|
|
||||||
set -- \
|
set -- \
|
||||||
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
||||||
-classpath "$CLASSPATH" \
|
-jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \
|
||||||
org.gradle.wrapper.GradleWrapperMain \
|
|
||||||
"$@"
|
"$@"
|
||||||
|
|
||||||
# Stop when "xargs" is not available.
|
# Stop when "xargs" is not available.
|
||||||
|
|||||||
3
gradlew.bat
vendored
3
gradlew.bat
vendored
@@ -70,11 +70,10 @@ goto fail
|
|||||||
:execute
|
:execute
|
||||||
@rem Setup the command line
|
@rem Setup the command line
|
||||||
|
|
||||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
|
||||||
|
|
||||||
|
|
||||||
@rem Execute Gradle
|
@rem Execute Gradle
|
||||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
|
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %*
|
||||||
|
|
||||||
:end
|
:end
|
||||||
@rem End local scope for the variables with windows NT shell
|
@rem End local scope for the variables with windows NT shell
|
||||||
|
|||||||
@@ -1,42 +1,49 @@
|
|||||||
package co.sirblob
|
package co.sirblob
|
||||||
|
|
||||||
|
import co.sirblob.gui.CobbleSyncScreen
|
||||||
|
import co.sirblob.network.ClientPacketHandler
|
||||||
import com.mojang.blaze3d.platform.InputConstants
|
import com.mojang.blaze3d.platform.InputConstants
|
||||||
import net.fabricmc.api.ClientModInitializer
|
import net.fabricmc.api.ClientModInitializer
|
||||||
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents
|
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents
|
||||||
import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper
|
import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper
|
||||||
import net.minecraft.client.KeyMapping
|
import net.minecraft.client.KeyMapping
|
||||||
import org.lwjgl.glfw.GLFW
|
import org.lwjgl.glfw.GLFW
|
||||||
|
import org.slf4j.LoggerFactory
|
||||||
|
|
||||||
object CobbleSyncClient : ClientModInitializer {
|
object CobbleSyncClient : ClientModInitializer {
|
||||||
|
|
||||||
override fun onInitializeClient() {
|
private val logger = LoggerFactory.getLogger("cobblesync-client")
|
||||||
|
|
||||||
val binding1 = KeyBindingHelper.registerKeyBinding(
|
override fun onInitializeClient() {
|
||||||
KeyMapping(
|
logger.info("CobbleSync Client initializing...")
|
||||||
"key.fabric-key-binding-api-v1-testmod.test_keybinding_1",
|
|
||||||
InputConstants.Type.KEYSYM,
|
|
||||||
GLFW.GLFW_KEY_U,
|
|
||||||
"key.category.first.test"
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
ClientTickEvents.END_CLIENT_TICK.register { client ->
|
// Register client-side network handlers
|
||||||
while (binding1.consumeClick()) {
|
ClientPacketHandler.register()
|
||||||
|
|
||||||
var player = client.player
|
// Register keybind for opening the CobbleSync GUI
|
||||||
|
val openGuiKeybind =
|
||||||
// client.player?.sendSystemMessage(
|
KeyBindingHelper.registerKeyBinding(
|
||||||
// Component.literal("Key 1 was pressed!")
|
KeyMapping(
|
||||||
// .withStyle { style ->
|
"key.cobblesync.open_gui",
|
||||||
// style.withColor(0x00FF00)
|
InputConstants.Type.KEYSYM,
|
||||||
// }
|
GLFW.GLFW_KEY_U,
|
||||||
// )
|
"key.categories.cobblesync"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
if(player != null) {
|
// Handle keybind press
|
||||||
|
ClientTickEvents.END_CLIENT_TICK.register { client ->
|
||||||
|
while (openGuiKeybind.consumeClick()) {
|
||||||
|
val player = client.player
|
||||||
|
|
||||||
|
if (player != null && client.screen == null) {
|
||||||
|
// Open the CobbleSync GUI
|
||||||
|
client.setScreen(CobbleSyncScreen())
|
||||||
|
logger.info("Opened CobbleSync GUI")
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
logger.info("CobbleSync Client initialized!")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
151
src/client/kotlin/co/sirblob/gui/CobbleSyncScreen.kt
Normal file
151
src/client/kotlin/co/sirblob/gui/CobbleSyncScreen.kt
Normal file
@@ -0,0 +1,151 @@
|
|||||||
|
package co.sirblob.gui
|
||||||
|
|
||||||
|
import co.sirblob.network.CobbleSyncPackets
|
||||||
|
import net.fabricmc.api.EnvType
|
||||||
|
import net.fabricmc.api.Environment
|
||||||
|
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking
|
||||||
|
import net.minecraft.client.gui.GuiGraphics
|
||||||
|
import net.minecraft.client.gui.components.Button
|
||||||
|
import net.minecraft.client.gui.screens.Screen
|
||||||
|
import net.minecraft.network.chat.Component
|
||||||
|
|
||||||
|
@Environment(EnvType.CLIENT)
|
||||||
|
class CobbleSyncScreen : Screen(Component.literal("CobbleSync")) {
|
||||||
|
|
||||||
|
// Status message to display feedback
|
||||||
|
private var statusMessage: Component = Component.literal("")
|
||||||
|
private var statusColor: Int = 0xFFFFFF
|
||||||
|
|
||||||
|
// Buttons
|
||||||
|
private lateinit var syncButton: Button
|
||||||
|
private lateinit var loadButton: Button
|
||||||
|
private lateinit var closeButton: Button
|
||||||
|
|
||||||
|
override fun init() {
|
||||||
|
super.init()
|
||||||
|
|
||||||
|
val buttonWidth = 200
|
||||||
|
val buttonHeight = 20
|
||||||
|
val centerX = width / 2
|
||||||
|
val centerY = height / 2
|
||||||
|
|
||||||
|
// Sync Button - uploads Box 30 to the server
|
||||||
|
syncButton = Button.builder(Component.literal("⬆ Sync Box 30")) { _ ->
|
||||||
|
setStatus(Component.literal("Syncing..."), 0xFFFF55)
|
||||||
|
ClientPlayNetworking.send(CobbleSyncPackets.SyncRequestPayload())
|
||||||
|
}
|
||||||
|
.bounds(centerX - buttonWidth / 2, centerY - 40, buttonWidth, buttonHeight)
|
||||||
|
.build()
|
||||||
|
|
||||||
|
// Load Button - downloads saved Pokemon to Box 1
|
||||||
|
loadButton = Button.builder(Component.literal("⬇ Load to Box 1")) { _ ->
|
||||||
|
setStatus(Component.literal("Loading..."), 0xFFFF55)
|
||||||
|
ClientPlayNetworking.send(CobbleSyncPackets.LoadRequestPayload())
|
||||||
|
}
|
||||||
|
.bounds(centerX - buttonWidth / 2, centerY - 10, buttonWidth, buttonHeight)
|
||||||
|
.build()
|
||||||
|
|
||||||
|
// Close Button
|
||||||
|
closeButton = Button.builder(Component.literal("Close")) { _ ->
|
||||||
|
onClose()
|
||||||
|
}
|
||||||
|
.bounds(centerX - buttonWidth / 2, centerY + 30, buttonWidth, buttonHeight)
|
||||||
|
.build()
|
||||||
|
|
||||||
|
addRenderableWidget(syncButton)
|
||||||
|
addRenderableWidget(loadButton)
|
||||||
|
addRenderableWidget(closeButton)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun render(guiGraphics: GuiGraphics, mouseX: Int, mouseY: Int, partialTick: Float) {
|
||||||
|
// Render background
|
||||||
|
renderBackground(guiGraphics, mouseX, mouseY, partialTick)
|
||||||
|
|
||||||
|
// Draw title
|
||||||
|
guiGraphics.drawCenteredString(
|
||||||
|
font,
|
||||||
|
Component.literal("§6§lCobbleSync"),
|
||||||
|
width / 2,
|
||||||
|
height / 2 - 80,
|
||||||
|
0xFFFFFF
|
||||||
|
)
|
||||||
|
|
||||||
|
// Draw subtitle/description
|
||||||
|
guiGraphics.drawCenteredString(
|
||||||
|
font,
|
||||||
|
Component.literal("§7Sync your Pokémon across servers"),
|
||||||
|
width / 2,
|
||||||
|
height / 2 - 65,
|
||||||
|
0xAAAAAA
|
||||||
|
)
|
||||||
|
|
||||||
|
// Draw separator line
|
||||||
|
guiGraphics.fill(
|
||||||
|
width / 2 - 100,
|
||||||
|
height / 2 - 55,
|
||||||
|
width / 2 + 100,
|
||||||
|
height / 2 - 54,
|
||||||
|
0xFF444444.toInt()
|
||||||
|
)
|
||||||
|
|
||||||
|
// Draw status message
|
||||||
|
if (statusMessage.string.isNotEmpty()) {
|
||||||
|
guiGraphics.drawCenteredString(
|
||||||
|
font,
|
||||||
|
statusMessage,
|
||||||
|
width / 2,
|
||||||
|
height / 2 + 60,
|
||||||
|
statusColor
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw info text
|
||||||
|
guiGraphics.drawCenteredString(
|
||||||
|
font,
|
||||||
|
Component.literal("§8Sync: Upload Box 30 (max 12 Pokémon)"),
|
||||||
|
width / 2,
|
||||||
|
height / 2 + 80,
|
||||||
|
0x888888
|
||||||
|
)
|
||||||
|
guiGraphics.drawCenteredString(
|
||||||
|
font,
|
||||||
|
Component.literal("§8Load: Download to Box 1 (must be empty)"),
|
||||||
|
width / 2,
|
||||||
|
height / 2 + 92,
|
||||||
|
0x888888
|
||||||
|
)
|
||||||
|
|
||||||
|
super.render(guiGraphics, mouseX, mouseY, partialTick)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun isPauseScreen(): Boolean = false
|
||||||
|
|
||||||
|
fun setStatus(message: Component, color: Int) {
|
||||||
|
this.statusMessage = message
|
||||||
|
this.statusColor = color
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
// Singleton instance for updating status from network handlers
|
||||||
|
var currentInstance: CobbleSyncScreen? = null
|
||||||
|
private set
|
||||||
|
|
||||||
|
fun open(screen: CobbleSyncScreen) {
|
||||||
|
currentInstance = screen
|
||||||
|
}
|
||||||
|
|
||||||
|
fun close() {
|
||||||
|
currentInstance = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onClose() {
|
||||||
|
CobbleSyncScreen.close()
|
||||||
|
super.onClose()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun added() {
|
||||||
|
super.added()
|
||||||
|
CobbleSyncScreen.open(this)
|
||||||
|
}
|
||||||
|
}
|
||||||
27
src/client/kotlin/co/sirblob/network/ClientPacketHandler.kt
Normal file
27
src/client/kotlin/co/sirblob/network/ClientPacketHandler.kt
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
package co.sirblob.network
|
||||||
|
|
||||||
|
import co.sirblob.gui.CobbleSyncScreen
|
||||||
|
import net.fabricmc.api.EnvType
|
||||||
|
import net.fabricmc.api.Environment
|
||||||
|
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking
|
||||||
|
import net.minecraft.network.chat.Component
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Client-side packet handlers for CobbleSync
|
||||||
|
*/
|
||||||
|
@Environment(EnvType.CLIENT)
|
||||||
|
object ClientPacketHandler {
|
||||||
|
|
||||||
|
fun register() {
|
||||||
|
// Register handler for sync response
|
||||||
|
ClientPlayNetworking.registerGlobalReceiver(CobbleSyncPackets.SYNC_RESPONSE_ID) { payload, context ->
|
||||||
|
context.client().execute {
|
||||||
|
val screen = CobbleSyncScreen.currentInstance
|
||||||
|
if (screen != null) {
|
||||||
|
val color = if (payload.success) 0x55FF55 else 0xFF5555
|
||||||
|
screen.setStatus(Component.literal(payload.message), color)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,158 +1,283 @@
|
|||||||
package co.sirblob
|
package co.sirblob
|
||||||
|
|
||||||
import com.cobblemon.mod.common.api.text.red
|
import co.sirblob.network.ServerPacketHandler
|
||||||
import com.cobblemon.mod.common.api.text.green
|
|
||||||
import com.cobblemon.mod.common.api.text.blue
|
import com.cobblemon.mod.common.api.text.blue
|
||||||
import com.cobblemon.mod.common.api.pokemon.PokemonSpecies
|
import com.cobblemon.mod.common.api.text.green
|
||||||
import com.cobblemon.mod.common.api.pokemon.stats.Stat
|
import com.cobblemon.mod.common.api.text.red
|
||||||
import com.cobblemon.mod.common.api.pokemon.stats.Stats
|
|
||||||
import com.cobblemon.mod.common.api.storage.pc.PCBox
|
|
||||||
import com.cobblemon.mod.common.util.pc
|
import com.cobblemon.mod.common.util.pc
|
||||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
|
||||||
import com.cobblemon.mod.common.pokemon.Species
|
|
||||||
import com.cobblemon.mod.common.Cobblemon
|
|
||||||
import com.cobblemon.mod.relocations.oracle.truffle.regex.tregex.util.json.Json
|
|
||||||
import org.json.JSONObject
|
|
||||||
import com.mojang.brigadier.Command
|
|
||||||
import com.mojang.brigadier.arguments.IntegerArgumentType
|
|
||||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder
|
|
||||||
import com.mojang.brigadier.context.CommandContext
|
|
||||||
import com.google.gson.JsonObject
|
import com.google.gson.JsonObject
|
||||||
import com.google.gson.JsonParser
|
import com.google.gson.JsonParser
|
||||||
|
import com.mojang.brigadier.Command
|
||||||
|
import com.mojang.brigadier.builder.LiteralArgumentBuilder
|
||||||
|
import com.mojang.brigadier.context.CommandContext
|
||||||
import net.fabricmc.api.ModInitializer
|
import net.fabricmc.api.ModInitializer
|
||||||
import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback
|
import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback
|
||||||
import net.minecraft.commands.CommandSourceStack
|
import net.minecraft.commands.CommandSourceStack
|
||||||
import net.minecraft.network.chat.Component
|
import net.minecraft.network.chat.Component
|
||||||
import net.minecraft.core.RegistryAccess
|
import org.json.JSONObject
|
||||||
import net.minecraft.resources.ResourceLocation
|
|
||||||
import org.slf4j.LoggerFactory
|
import org.slf4j.LoggerFactory
|
||||||
|
|
||||||
|
|
||||||
object CobbleSync : ModInitializer {
|
object CobbleSync : ModInitializer {
|
||||||
|
|
||||||
private val logger = LoggerFactory.getLogger("cobblesync")
|
private val logger = LoggerFactory.getLogger("cobblesync")
|
||||||
private val request = Request("https://authserver.sirblob.co")
|
private val request = Request("https://authserver.sirblob.co")
|
||||||
|
|
||||||
override fun onInitialize() {
|
override fun onInitialize() {
|
||||||
|
logger.info("CobbleSync initializing...")
|
||||||
|
|
||||||
CommandRegistrationCallback.EVENT.register(CommandRegistrationCallback { dispatcher, _, _ ->
|
// Register network packet handlers for GUI communication
|
||||||
dispatcher.register(
|
ServerPacketHandler.register()
|
||||||
LiteralArgumentBuilder.literal<CommandSourceStack>("cobblesync")
|
logger.info("Registered CobbleSync network handlers")
|
||||||
.then(
|
|
||||||
LiteralArgumentBuilder.literal<CommandSourceStack>("sync")
|
|
||||||
.executes(Command<CommandSourceStack> { context: CommandContext<CommandSourceStack> ->
|
|
||||||
|
|
||||||
val player = context.source.playerOrException
|
|
||||||
player.sendSystemMessage(Component.literal("Syncing box...").red())
|
|
||||||
|
|
||||||
val box30 = player.pc().boxes.get(29)
|
|
||||||
var pokemonCount = 0
|
|
||||||
|
|
||||||
box30.filterNotNull().forEach { pokemon ->
|
CommandRegistrationCallback.EVENT.register(
|
||||||
player.sendSystemMessage(
|
CommandRegistrationCallback { dispatcher, _, _ ->
|
||||||
Component.literal("Syncing Pokémon: ${pokemon.species.name} (Level ${pokemon.level})")
|
dispatcher.register(
|
||||||
.blue()
|
LiteralArgumentBuilder.literal<CommandSourceStack>("cobblesync")
|
||||||
|
.then(
|
||||||
|
LiteralArgumentBuilder.literal<CommandSourceStack>(
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
.executes(
|
||||||
|
Command<CommandSourceStack> {
|
||||||
|
context:
|
||||||
|
CommandContext<
|
||||||
|
CommandSourceStack>
|
||||||
|
->
|
||||||
|
val player =
|
||||||
|
context.source
|
||||||
|
.playerOrException
|
||||||
|
player.sendSystemMessage(
|
||||||
|
Component.literal(
|
||||||
|
"Syncing box..."
|
||||||
|
)
|
||||||
|
.red()
|
||||||
|
)
|
||||||
|
|
||||||
|
val box30 =
|
||||||
|
player.pc().boxes.get(29)
|
||||||
|
var pokemonCount = 0
|
||||||
|
|
||||||
|
box30.filterNotNull().forEach {
|
||||||
|
pokemon ->
|
||||||
|
player.sendSystemMessage(
|
||||||
|
Component.literal(
|
||||||
|
"Syncing Pokémon: ${pokemon.species.name} (Level ${pokemon.level})"
|
||||||
|
)
|
||||||
|
.blue()
|
||||||
|
)
|
||||||
|
pokemonCount++
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pokemonCount < 1) {
|
||||||
|
player.sendSystemMessage(
|
||||||
|
Component.literal(
|
||||||
|
"[Sync Failed] Box 1 is empty!"
|
||||||
|
)
|
||||||
|
.red()
|
||||||
|
)
|
||||||
|
return@Command 1
|
||||||
|
} else if (pokemonCount > 12) {
|
||||||
|
player.sendSystemMessage(
|
||||||
|
Component.literal(
|
||||||
|
"[Sync Failed] Box 1 has too many pokemon!"
|
||||||
|
)
|
||||||
|
.red()
|
||||||
|
)
|
||||||
|
return@Command 1
|
||||||
|
}
|
||||||
|
|
||||||
|
var obj =
|
||||||
|
box30.saveToJSON(
|
||||||
|
JsonObject(),
|
||||||
|
player.registryAccess()
|
||||||
|
)
|
||||||
|
|
||||||
|
val payload =
|
||||||
|
JSONObject()
|
||||||
|
.put(
|
||||||
|
"pokemon",
|
||||||
|
obj.toString()
|
||||||
|
)
|
||||||
|
.put(
|
||||||
|
"count",
|
||||||
|
pokemonCount
|
||||||
|
)
|
||||||
|
|
||||||
|
logger.info(
|
||||||
|
"/api/cobblesync/" +
|
||||||
|
player.uuid
|
||||||
|
.toString()
|
||||||
|
)
|
||||||
|
|
||||||
|
try {
|
||||||
|
var response =
|
||||||
|
request.POST(
|
||||||
|
"/api/cobblesync/" +
|
||||||
|
player.uuid
|
||||||
|
.toString(),
|
||||||
|
payload
|
||||||
|
)
|
||||||
|
|
||||||
|
logger.info(response.toString())
|
||||||
|
|
||||||
|
player.sendSystemMessage(
|
||||||
|
Component.literal(
|
||||||
|
"Box 30 synced successfully!"
|
||||||
|
)
|
||||||
|
.green()
|
||||||
|
)
|
||||||
|
} catch (e: HTTPException) {
|
||||||
|
logger.error(
|
||||||
|
"HTTP Exception: ${e.message}"
|
||||||
|
)
|
||||||
|
player.sendSystemMessage(
|
||||||
|
Component.literal(
|
||||||
|
"Error syncing box 30!"
|
||||||
|
)
|
||||||
|
.red()
|
||||||
|
)
|
||||||
|
return@Command 1
|
||||||
|
} catch (e: Exception) {
|
||||||
|
logger.error(
|
||||||
|
"Exception: ${e.message}"
|
||||||
|
)
|
||||||
|
player.sendSystemMessage(
|
||||||
|
Component.literal(
|
||||||
|
"An unexpected error occurred!"
|
||||||
|
)
|
||||||
|
.red()
|
||||||
|
)
|
||||||
|
return@Command 1
|
||||||
|
}
|
||||||
|
|
||||||
|
1
|
||||||
|
}
|
||||||
|
)
|
||||||
)
|
)
|
||||||
pokemonCount++
|
.then(
|
||||||
}
|
LiteralArgumentBuilder.literal<CommandSourceStack>(
|
||||||
|
"load"
|
||||||
|
)
|
||||||
|
.executes(
|
||||||
|
Command<CommandSourceStack> {
|
||||||
|
context:
|
||||||
|
CommandContext<
|
||||||
|
CommandSourceStack>
|
||||||
|
->
|
||||||
|
val player =
|
||||||
|
context.source
|
||||||
|
.playerOrException
|
||||||
|
|
||||||
if (pokemonCount < 1) {
|
val pc = player.pc()
|
||||||
player.sendSystemMessage(Component.literal("[Sync Failed] Box 1 is empty!").red())
|
player.sendSystemMessage(
|
||||||
return@Command 1
|
Component.literal(
|
||||||
} else if (pokemonCount > 12) {
|
"Syncing box..."
|
||||||
player.sendSystemMessage(Component.literal("[Sync Failed] Box 1 has too many pokemon!").red())
|
)
|
||||||
return@Command 1
|
.green()
|
||||||
}
|
)
|
||||||
|
|
||||||
var obj = box30.saveToJSON(JsonObject(), player.registryAccess())
|
var box1 = pc.boxes.get(0)
|
||||||
|
|
||||||
val payload = JSONObject()
|
var pokemonCount = 0
|
||||||
.put("pokemon", obj.toString())
|
box1.pc.forEach({ _ ->
|
||||||
.put("count", pokemonCount)
|
pokemonCount++
|
||||||
|
})
|
||||||
|
|
||||||
logger.info("/api/cobblesync/" + player.uuid.toString())
|
if (pokemonCount > 0) {
|
||||||
|
player.sendSystemMessage(
|
||||||
|
Component.literal(
|
||||||
|
"[Load Failed] Box 1 is not empty!"
|
||||||
|
)
|
||||||
|
.red()
|
||||||
|
)
|
||||||
|
return@Command 1
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
var response = request.POST("/api/cobblesync/" + player.uuid.toString(), payload)
|
|
||||||
|
|
||||||
logger.info(response.toString())
|
var response =
|
||||||
|
request.GET(
|
||||||
|
"/api/cobblesync/" +
|
||||||
|
player.uuid
|
||||||
|
.toString()
|
||||||
|
)
|
||||||
|
logger.info(response.toString())
|
||||||
|
|
||||||
player.sendSystemMessage(Component.literal("Box 30 synced successfully!").green())
|
if (response.getInt("status") !=
|
||||||
|
200
|
||||||
|
) {
|
||||||
|
player.sendSystemMessage(
|
||||||
|
Component.literal(
|
||||||
|
"Failed to load box 1!"
|
||||||
|
)
|
||||||
|
.red()
|
||||||
|
)
|
||||||
|
return@Command 1
|
||||||
|
}
|
||||||
|
|
||||||
} catch (e: HTTPException) {
|
var obj =
|
||||||
logger.error("HTTP Exception: ${e.message}")
|
JsonParser.parseString(
|
||||||
player.sendSystemMessage(Component.literal("Error syncing box 30!").red())
|
response.getString(
|
||||||
return@Command 1
|
"pokemon"
|
||||||
} catch (e: Exception) {
|
)
|
||||||
logger.error("Exception: ${e.message}")
|
)
|
||||||
player.sendSystemMessage(Component.literal("An unexpected error occurred!").red())
|
.asJsonObject
|
||||||
return@Command 1
|
|
||||||
}
|
|
||||||
|
|
||||||
1
|
var newBox =
|
||||||
})
|
box1.loadFromJSON(
|
||||||
|
obj,
|
||||||
|
player.registryAccess()
|
||||||
|
)
|
||||||
|
|
||||||
|
newBox.pc.filterNotNull()
|
||||||
|
.forEach { pokemon ->
|
||||||
|
player.sendSystemMessage(
|
||||||
|
Component
|
||||||
|
.literal(
|
||||||
|
"Received Pokémon: ${pokemon.species.name} (Level ${pokemon.level})"
|
||||||
|
)
|
||||||
|
.blue()
|
||||||
|
)
|
||||||
|
|
||||||
|
box1.pc.add(pokemon)
|
||||||
|
}
|
||||||
|
|
||||||
|
player.sendSystemMessage(
|
||||||
|
Component.literal(
|
||||||
|
"Box 1 loaded successfully!"
|
||||||
|
)
|
||||||
|
.green()
|
||||||
|
)
|
||||||
|
} catch (e: HTTPException) {
|
||||||
|
logger.error(
|
||||||
|
"HTTP Exception: ${e.message}"
|
||||||
|
)
|
||||||
|
player.sendSystemMessage(
|
||||||
|
Component.literal(
|
||||||
|
"Error loading box 1!"
|
||||||
|
)
|
||||||
|
.red()
|
||||||
|
)
|
||||||
|
return@Command 1
|
||||||
|
} catch (e: Exception) {
|
||||||
|
logger.error(
|
||||||
|
"Exception: ${e.message}"
|
||||||
|
)
|
||||||
|
player.sendSystemMessage(
|
||||||
|
Component.literal(
|
||||||
|
"An unexpected error occurred!"
|
||||||
|
)
|
||||||
|
.red()
|
||||||
|
)
|
||||||
|
return@Command 1
|
||||||
|
}
|
||||||
|
|
||||||
|
1
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
)
|
)
|
||||||
.then(
|
}
|
||||||
LiteralArgumentBuilder.literal<CommandSourceStack>("load")
|
)
|
||||||
.executes(Command<CommandSourceStack> { context: CommandContext<CommandSourceStack> ->
|
|
||||||
val player = context.source.playerOrException
|
|
||||||
|
|
||||||
val pc = player.pc()
|
|
||||||
player.sendSystemMessage(Component.literal("Syncing box...").green())
|
|
||||||
|
|
||||||
var box1 = pc.boxes.get(0)
|
|
||||||
|
|
||||||
var pokemonCount = 0
|
|
||||||
box1.pc.forEach({ _ ->
|
|
||||||
pokemonCount++
|
|
||||||
})
|
|
||||||
|
|
||||||
if (pokemonCount > 0) {
|
|
||||||
player.sendSystemMessage(Component.literal("[Load Failed] Box 1 is not empty!").red())
|
|
||||||
return@Command 1
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
|
|
||||||
var response = request.GET("/api/cobblesync/" + player.uuid.toString())
|
|
||||||
logger.info(response.toString())
|
|
||||||
|
|
||||||
if (response.getInt("status") != 200) {
|
|
||||||
player.sendSystemMessage(Component.literal("Failed to load box 1!").red())
|
|
||||||
return@Command 1
|
|
||||||
}
|
|
||||||
|
|
||||||
var obj = JsonParser.parseString(response.getString("pokemon")).asJsonObject
|
|
||||||
|
|
||||||
var newBox = box1.loadFromJSON(obj, player.registryAccess())
|
|
||||||
|
|
||||||
newBox.pc.filterNotNull().forEach { pokemon ->
|
|
||||||
player.sendSystemMessage(
|
|
||||||
Component.literal("Received Pokémon: ${pokemon.species.name} (Level ${pokemon.level})")
|
|
||||||
.blue()
|
|
||||||
)
|
|
||||||
|
|
||||||
box1.pc.add(pokemon)
|
|
||||||
}
|
|
||||||
|
|
||||||
player.sendSystemMessage(Component.literal("Box 1 loaded successfully!").green())
|
|
||||||
|
|
||||||
} catch (e: HTTPException) {
|
|
||||||
logger.error("HTTP Exception: ${e.message}")
|
|
||||||
player.sendSystemMessage(Component.literal("Error loading box 1!").red())
|
|
||||||
return@Command 1
|
|
||||||
} catch (e: Exception) {
|
|
||||||
logger.error("Exception: ${e.message}")
|
|
||||||
player.sendSystemMessage(Component.literal("An unexpected error occurred!").red())
|
|
||||||
return@Command 1
|
|
||||||
}
|
|
||||||
|
|
||||||
1
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
))
|
|
||||||
})
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
75
src/main/kotlin/co/sirblob/network/CobbleSyncPackets.kt
Normal file
75
src/main/kotlin/co/sirblob/network/CobbleSyncPackets.kt
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
package co.sirblob.network
|
||||||
|
|
||||||
|
import net.minecraft.network.FriendlyByteBuf
|
||||||
|
import net.minecraft.network.codec.StreamCodec
|
||||||
|
import net.minecraft.network.protocol.common.custom.CustomPacketPayload
|
||||||
|
import net.minecraft.resources.ResourceLocation
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Network packet definitions for CobbleSync client-server communication
|
||||||
|
*/
|
||||||
|
object CobbleSyncPackets {
|
||||||
|
|
||||||
|
// Packet IDs
|
||||||
|
val SYNC_REQUEST_ID = CustomPacketPayload.Type<SyncRequestPayload>(
|
||||||
|
ResourceLocation.fromNamespaceAndPath("cobblesync", "sync_request")
|
||||||
|
)
|
||||||
|
val LOAD_REQUEST_ID = CustomPacketPayload.Type<LoadRequestPayload>(
|
||||||
|
ResourceLocation.fromNamespaceAndPath("cobblesync", "load_request")
|
||||||
|
)
|
||||||
|
val SYNC_RESPONSE_ID = CustomPacketPayload.Type<SyncResponsePayload>(
|
||||||
|
ResourceLocation.fromNamespaceAndPath("cobblesync", "sync_response")
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Client -> Server: Request to sync Box 30
|
||||||
|
*/
|
||||||
|
class SyncRequestPayload : CustomPacketPayload {
|
||||||
|
override fun type(): CustomPacketPayload.Type<out CustomPacketPayload> = SYNC_REQUEST_ID
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
val STREAM_CODEC: StreamCodec<FriendlyByteBuf, SyncRequestPayload> = StreamCodec.of(
|
||||||
|
{ _, _ -> }, // encode - nothing to write
|
||||||
|
{ _ -> SyncRequestPayload() } // decode - just create instance
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Client -> Server: Request to load Pokemon to Box 1
|
||||||
|
*/
|
||||||
|
class LoadRequestPayload : CustomPacketPayload {
|
||||||
|
override fun type(): CustomPacketPayload.Type<out CustomPacketPayload> = LOAD_REQUEST_ID
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
val STREAM_CODEC: StreamCodec<FriendlyByteBuf, LoadRequestPayload> = StreamCodec.of(
|
||||||
|
{ _, _ -> },
|
||||||
|
{ _ -> LoadRequestPayload() }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Server -> Client: Response with status message
|
||||||
|
*/
|
||||||
|
class SyncResponsePayload(
|
||||||
|
val success: Boolean,
|
||||||
|
val message: String
|
||||||
|
) : CustomPacketPayload {
|
||||||
|
override fun type(): CustomPacketPayload.Type<out CustomPacketPayload> = SYNC_RESPONSE_ID
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
val STREAM_CODEC: StreamCodec<FriendlyByteBuf, SyncResponsePayload> = StreamCodec.of(
|
||||||
|
{ buf, payload ->
|
||||||
|
buf.writeBoolean(payload.success)
|
||||||
|
buf.writeUtf(payload.message)
|
||||||
|
},
|
||||||
|
{ buf ->
|
||||||
|
val success = buf.readBoolean()
|
||||||
|
val message = buf.readUtf()
|
||||||
|
SyncResponsePayload(success, message)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
135
src/main/kotlin/co/sirblob/network/ServerPacketHandler.kt
Normal file
135
src/main/kotlin/co/sirblob/network/ServerPacketHandler.kt
Normal file
@@ -0,0 +1,135 @@
|
|||||||
|
package co.sirblob.network
|
||||||
|
|
||||||
|
import co.sirblob.HTTPException
|
||||||
|
import co.sirblob.Request
|
||||||
|
import com.cobblemon.mod.common.util.pc
|
||||||
|
import com.google.gson.JsonObject
|
||||||
|
import com.google.gson.JsonParser
|
||||||
|
import net.fabricmc.fabric.api.networking.v1.PayloadTypeRegistry
|
||||||
|
import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking
|
||||||
|
import net.minecraft.server.level.ServerPlayer
|
||||||
|
import org.json.JSONObject
|
||||||
|
import org.slf4j.LoggerFactory
|
||||||
|
|
||||||
|
/** Server-side packet handlers for CobbleSync operations */
|
||||||
|
object ServerPacketHandler {
|
||||||
|
|
||||||
|
private val logger = LoggerFactory.getLogger("cobblesync")
|
||||||
|
private val request = Request("https://authserver.sirblob.co")
|
||||||
|
|
||||||
|
fun register() {
|
||||||
|
// Register packet types
|
||||||
|
PayloadTypeRegistry.playC2S()
|
||||||
|
.register(
|
||||||
|
CobbleSyncPackets.SYNC_REQUEST_ID,
|
||||||
|
CobbleSyncPackets.SyncRequestPayload.STREAM_CODEC
|
||||||
|
)
|
||||||
|
PayloadTypeRegistry.playC2S()
|
||||||
|
.register(
|
||||||
|
CobbleSyncPackets.LOAD_REQUEST_ID,
|
||||||
|
CobbleSyncPackets.LoadRequestPayload.STREAM_CODEC
|
||||||
|
)
|
||||||
|
PayloadTypeRegistry.playS2C()
|
||||||
|
.register(
|
||||||
|
CobbleSyncPackets.SYNC_RESPONSE_ID,
|
||||||
|
CobbleSyncPackets.SyncResponsePayload.STREAM_CODEC
|
||||||
|
)
|
||||||
|
|
||||||
|
// Register handlers
|
||||||
|
ServerPlayNetworking.registerGlobalReceiver(CobbleSyncPackets.SYNC_REQUEST_ID) { _, context
|
||||||
|
->
|
||||||
|
val player = context.player()
|
||||||
|
context.server().execute { handleSyncRequest(player) }
|
||||||
|
}
|
||||||
|
|
||||||
|
ServerPlayNetworking.registerGlobalReceiver(CobbleSyncPackets.LOAD_REQUEST_ID) { _, context
|
||||||
|
->
|
||||||
|
val player = context.player()
|
||||||
|
context.server().execute { handleLoadRequest(player) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun handleSyncRequest(player: ServerPlayer) {
|
||||||
|
try {
|
||||||
|
val box30 = player.pc().boxes[29]
|
||||||
|
var pokemonCount = 0
|
||||||
|
|
||||||
|
box30.filterNotNull().forEach { pokemon ->
|
||||||
|
logger.info("Syncing Pokémon: ${pokemon.species.name} (Level ${pokemon.level})")
|
||||||
|
pokemonCount++
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pokemonCount < 1) {
|
||||||
|
sendResponse(player, false, "Box 30 is empty!")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pokemonCount > 12) {
|
||||||
|
sendResponse(player, false, "Box 30 has too many Pokémon! (Max 12)")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val obj = box30.saveToJSON(JsonObject(), player.registryAccess())
|
||||||
|
|
||||||
|
val payload = JSONObject().put("pokemon", obj.toString()).put("count", pokemonCount)
|
||||||
|
|
||||||
|
logger.info("/api/cobblesync/${player.uuid}")
|
||||||
|
|
||||||
|
val response = request.POST("/api/cobblesync/${player.uuid}", payload)
|
||||||
|
logger.info(response.toString())
|
||||||
|
|
||||||
|
sendResponse(player, true, "Successfully synced $pokemonCount Pokémon!")
|
||||||
|
} catch (e: HTTPException) {
|
||||||
|
logger.error("HTTP Exception: ${e.message}")
|
||||||
|
sendResponse(player, false, "Server error: ${e.message}")
|
||||||
|
} catch (e: Exception) {
|
||||||
|
logger.error("Exception: ${e.message}")
|
||||||
|
sendResponse(player, false, "An unexpected error occurred!")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun handleLoadRequest(player: ServerPlayer) {
|
||||||
|
try {
|
||||||
|
val pc = player.pc()
|
||||||
|
val box1 = pc.boxes[0]
|
||||||
|
|
||||||
|
var pokemonCount = 0
|
||||||
|
box1.filterNotNull().forEach { _ -> pokemonCount++ }
|
||||||
|
|
||||||
|
if (pokemonCount > 0) {
|
||||||
|
sendResponse(player, false, "Box 1 is not empty!")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val response = request.GET("/api/cobblesync/${player.uuid}")
|
||||||
|
logger.info(response.toString())
|
||||||
|
|
||||||
|
if (response.getInt("status") != 200) {
|
||||||
|
sendResponse(player, false, "No saved Pokémon found!")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val obj = JsonParser.parseString(response.getString("pokemon")).asJsonObject
|
||||||
|
val newBox = box1.loadFromJSON(obj, player.registryAccess())
|
||||||
|
|
||||||
|
var loadedCount = 0
|
||||||
|
newBox.pc.filterNotNull().forEach { pokemon ->
|
||||||
|
logger.info("Loading Pokémon: ${pokemon.species.name} (Level ${pokemon.level})")
|
||||||
|
box1.pc.add(pokemon)
|
||||||
|
loadedCount++
|
||||||
|
}
|
||||||
|
|
||||||
|
sendResponse(player, true, "Successfully loaded $loadedCount Pokémon!")
|
||||||
|
} catch (e: HTTPException) {
|
||||||
|
logger.error("HTTP Exception: ${e.message}")
|
||||||
|
sendResponse(player, false, "Server error: ${e.message}")
|
||||||
|
} catch (e: Exception) {
|
||||||
|
logger.error("Exception: ${e.message}")
|
||||||
|
sendResponse(player, false, "An unexpected error occurred!")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun sendResponse(player: ServerPlayer, success: Boolean, message: String) {
|
||||||
|
ServerPlayNetworking.send(player, CobbleSyncPackets.SyncResponsePayload(success, message))
|
||||||
|
}
|
||||||
|
}
|
||||||
4
src/main/resources/assets/cobblesync/lang/en_us.json
Normal file
4
src/main/resources/assets/cobblesync/lang/en_us.json
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"key.cobblesync.open_gui": "Open CobbleSync",
|
||||||
|
"key.categories.cobblesync": "CobbleSync"
|
||||||
|
}
|
||||||
@@ -3,13 +3,13 @@
|
|||||||
"id": "cobblesync",
|
"id": "cobblesync",
|
||||||
"version": "${version}",
|
"version": "${version}",
|
||||||
"name": "CobbleSync",
|
"name": "CobbleSync",
|
||||||
"description": "This is an example description! Tell everyone what your mod is about!",
|
"description": "Sync your Pokémon between servers!",
|
||||||
"authors": [
|
"authors": [
|
||||||
"Sir_Blob_"
|
"Sir_Blob_"
|
||||||
],
|
],
|
||||||
"contact": {
|
"contact": {
|
||||||
"homepage": "https://fabricmc.net/",
|
"homepage": "https://fabricmc.net/",
|
||||||
"sources": "https://github.com/FabricMC/fabric-example-mod"
|
"sources": "https://git.sirblob.co/GMMC/Cobblesync"
|
||||||
},
|
},
|
||||||
"license": "CC0-1.0",
|
"license": "CC0-1.0",
|
||||||
"icon": "assets/cobblesync/icon.png",
|
"icon": "assets/cobblesync/icon.png",
|
||||||
|
|||||||
Reference in New Issue
Block a user