192 lines
7.0 KiB
Kotlin
192 lines
7.0 KiB
Kotlin
package co.sirblob.network
|
|
|
|
import co.sirblob.HTTPException
|
|
import co.sirblob.Request
|
|
import com.cobblemon.mod.common.api.text.red
|
|
import com.cobblemon.mod.common.pokemon.Pokemon
|
|
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 net.minecraft.world.item.ItemStack
|
|
import net.minecraft.network.chat.Component
|
|
import com.cobblemon.mod.common.api.text.red
|
|
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())
|
|
|
|
// Remove held items from the JSON to prevent duping/transferring items
|
|
obj.entrySet().forEach { entry ->
|
|
if (entry.value.isJsonObject) {
|
|
entry.value.asJsonObject.remove("HeldItem")
|
|
}
|
|
}
|
|
|
|
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()
|
|
|
|
// Fetch synced Pokemon from the server
|
|
val response = request.GET("/api/cobblesync/${player.uuid}")
|
|
logger.info(response.toString())
|
|
|
|
if (response.getInt("status") == 403) {
|
|
sendResponse(player, false, "Player already synced/loaded")
|
|
return
|
|
}
|
|
|
|
if (response.getInt("status") != 200) {
|
|
sendResponse(player, false, "No saved Pokémon found!")
|
|
return
|
|
}
|
|
|
|
val obj = JsonParser.parseString(response.getString("pokemon")).asJsonObject
|
|
|
|
val pokemonToLoad = mutableListOf<Pokemon>()
|
|
obj.entrySet().forEach { entry ->
|
|
if (entry.key.startsWith("Slot")) {
|
|
val pokemonJson = entry.value.asJsonObject
|
|
val pokemon = Pokemon.loadFromJSON(player.registryAccess()!!, pokemonJson)
|
|
if (pokemon != null) {
|
|
pokemonToLoad.add(pokemon)
|
|
}
|
|
}
|
|
}
|
|
|
|
if (pokemonToLoad.isEmpty()) {
|
|
sendResponse(player, false, "No Pokémon to load!")
|
|
return
|
|
}
|
|
|
|
// Count available empty slots across all boxes
|
|
var emptySlots = 0
|
|
for (box in pc.boxes) {
|
|
for (slot in 0 until 30) { // Each box has 30 slots
|
|
if (box[slot] == null) {
|
|
emptySlots++
|
|
}
|
|
}
|
|
}
|
|
|
|
if (emptySlots < pokemonToLoad.size) {
|
|
sendResponse(
|
|
player,
|
|
false,
|
|
"Not enough empty slots! Need ${pokemonToLoad.size}, have $emptySlots"
|
|
)
|
|
return
|
|
}
|
|
|
|
// Add Pokemon to empty slots across all boxes
|
|
var loadedCount = 0
|
|
for (pokemon in pokemonToLoad) {
|
|
var placed = false
|
|
for (box in pc.boxes) {
|
|
if (placed) break
|
|
for (slot in 0 until 30) {
|
|
if (box[slot] == null) {
|
|
box[slot] = pokemon
|
|
logger.info(
|
|
"Loaded Pokémon: ${pokemon.species.name} (Level ${pokemon.level}) to slot $slot"
|
|
)
|
|
loadedCount++
|
|
placed = true
|
|
break
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
sendResponse(player, true, "Successfully loaded $loadedCount Pokémon to empty slots!")
|
|
} 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))
|
|
}
|
|
}
|