Compare commits

...
Author SHA1 Message Date
Deltric 6743dd4dff Cherry picked Polymeta's species fix. 2025-01-22 00:44:43 -06:00
5 changed files with 77 additions and 8 deletions
@@ -8,12 +8,14 @@
package com.cobblemon.mod.common.api.storage
import com.cobblemon.mod.common.Cobblemon
import com.cobblemon.mod.common.CobblemonNetwork.sendPacket
import com.cobblemon.mod.common.api.net.NetworkPacket
import com.cobblemon.mod.common.api.reactive.Observable
import com.cobblemon.mod.common.api.storage.factory.FileBackedPokemonStoreFactory
import com.cobblemon.mod.common.api.storage.factory.PokemonStoreFactory
import com.cobblemon.mod.common.pokemon.Pokemon
import com.cobblemon.mod.common.util.DataKeys
import com.google.gson.JsonObject
import java.util.UUID
import net.minecraft.core.RegistryAccess
@@ -147,10 +149,14 @@ abstract class PokemonStore<T : StorePosition> : Iterable<Pokemon> {
operator fun get(uuid: UUID) = find { it.uuid == uuid }
open fun handleInvalidSpeciesNBT(nbt: CompoundTag) {}
open fun handleInvalidSpeciesNBT(nbt: CompoundTag) {
Cobblemon.LOGGER.error("Failed to read unknown species: ${nbt.getString(DataKeys.POKEMON_SPECIES_IDENTIFIER)}")
}
abstract fun saveToNBT(nbt: CompoundTag, registryAccess: RegistryAccess): CompoundTag
abstract fun loadFromNBT(nbt: CompoundTag, registryAccess: RegistryAccess): PokemonStore<T>
open fun handleInvalidSpeciesJSON(json: JsonObject) {}
open fun handleInvalidSpeciesJSON(json: JsonObject) {
Cobblemon.LOGGER.error("Failed to read unknown species: ${json.get(DataKeys.POKEMON_SPECIES_IDENTIFIER).asString}")
}
abstract fun saveToJSON(json: JsonObject, registryAccess: RegistryAccess): JsonObject
abstract fun loadFromJSON(json: JsonObject, registryAccess: RegistryAccess): PokemonStore<T>
abstract fun savePositionToNBT(position: T, nbt: CompoundTag)
@@ -14,6 +14,7 @@ import com.cobblemon.mod.common.datafixer.fix.EvolutionProxyNestingFix
import com.cobblemon.mod.common.datafixer.fix.FeatureFix
import com.cobblemon.mod.common.datafixer.fix.IvEvToIdentifierFix
import com.cobblemon.mod.common.datafixer.fix.MovesetJsonFix
import com.cobblemon.mod.common.datafixer.fix.RaisedPPStagesFix
import com.cobblemon.mod.common.datafixer.fix.ShoulderStateJsonFix
import com.cobblemon.mod.common.datafixer.fix.TeraTypeFix
import com.cobblemon.mod.common.datafixer.fix.TradeableMissingFix
@@ -87,6 +88,7 @@ object CobblemonSchemas {
builder.addFixer(FeatureFix(schema1))
builder.addFixer(MovesetJsonFix(schema1))
builder.addFixer(ShoulderStateJsonFix(schema1))
builder.addFixer(RaisedPPStagesFix(schema1))
}
private class CobblemonDataFixerCodec<R>(private val baseCodec: Codec<R>, private val typeReference: TypeReference) : Codec<R> {
@@ -0,0 +1,38 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.datafixer.fix
import com.mojang.datafixers.schemas.Schema
import com.mojang.serialization.Dynamic
class RaisedPPStagesFix(output: Schema) : PokemonFix(output) {
override fun fixPokemonData(dynamic: Dynamic<*>): Dynamic<*> {
var result = processPPStages(dynamic, "MoveSet")
result = processPPStages(result, "BenchedMoves")
return result
}
private fun processPPStages(dynamic: Dynamic<*>, key: String): Dynamic<*> {
var moveSetJson = dynamic.get(key).asListOpt { it }.result()
if (!moveSetJson.isPresent) {
return dynamic
}
var moves = moveSetJson.get()
for(i in 0..moves.size) {
var move = moves.getOrNull(i)
if(move != null && move.get("RaisedPPStages").asNumber(0).toInt() > 3) {
moves[i] = move.set("RaisedPPStages", dynamic.createInt(3))
}
}
return dynamic.set(key, dynamic.createList(moves.stream()))
}
}
@@ -30,6 +30,7 @@ import com.cobblemon.mod.common.api.pokemon.evolution.PreEvolution
import com.cobblemon.mod.common.api.pokemon.experience.ExperienceGroups
import com.cobblemon.mod.common.api.pokemon.moves.Learnset
import com.cobblemon.mod.common.api.pokemon.stats.Stat
import com.cobblemon.mod.common.api.storage.InvalidSpeciesException
import com.cobblemon.mod.common.api.types.ElementalType
import com.cobblemon.mod.common.api.types.ElementalTypes
import com.cobblemon.mod.common.entity.PoseType.Companion.FLYING_POSES
@@ -39,7 +40,6 @@ import com.cobblemon.mod.common.net.IntSize
import com.cobblemon.mod.common.pokemon.abilities.HiddenAbility
import com.cobblemon.mod.common.pokemon.ai.PokemonBehaviour
import com.cobblemon.mod.common.pokemon.lighthing.LightingData
import com.cobblemon.mod.common.util.codec.CodecUtils
import com.cobblemon.mod.common.util.readEntityDimensions
import com.cobblemon.mod.common.util.readEnumConstant
import com.cobblemon.mod.common.util.readIdentifier
@@ -50,6 +50,7 @@ import com.cobblemon.mod.common.util.writeIdentifier
import com.cobblemon.mod.common.util.writeSizedInt
import com.cobblemon.mod.common.util.writeString
import com.mojang.serialization.Codec
import com.mojang.serialization.DataResult
import net.minecraft.network.RegistryFriendlyByteBuf
import net.minecraft.network.chat.Component
import net.minecraft.network.chat.MutableComponent
@@ -353,13 +354,13 @@ class Species : ClientDataSynchronizer<Species>, ShowdownIdentifiable {
// TODO: Registries have dedicated Codecs, migrate to that once this is a proper registry impl
/**
* A [Codec] that maps to/from an [Identifier] associated as [Species.resourceIdentifier].
* A [Codec] that maps to/from an [ResourceLocation] associated as [Species.resourceIdentifier].
* Uses [PokemonSpecies.getByIdentifier] to query.
*/
@JvmStatic
val BY_IDENTIFIER_CODEC: Codec<Species> = CodecUtils.createByIdentifierCodec(
PokemonSpecies::getByIdentifier,
val BY_IDENTIFIER_CODEC: Codec<Species> = ResourceLocation.CODEC.comapFlatMap(
{ identifier -> DataResult.success(PokemonSpecies.getByIdentifier(identifier) ?: throw InvalidSpeciesException(identifier)) },
Species::resourceIdentifier
) { identifier -> "No species for ID $identifier" }
)
}
}
@@ -20,7 +20,10 @@ import com.cobblemon.mod.common.pokemon.evolution.controller.ServerEvolutionCont
import com.cobblemon.mod.common.pokemon.status.PersistentStatusContainer
import com.cobblemon.mod.common.util.DataKeys
import com.cobblemon.mod.common.util.codec.CodecUtils
import com.mojang.datafixers.util.Pair
import com.mojang.serialization.Codec
import com.mojang.serialization.DataResult
import com.mojang.serialization.DynamicOps
import com.mojang.serialization.MapCodec
import com.mojang.serialization.codecs.RecordCodecBuilder
import net.minecraft.core.UUIDUtil
@@ -82,7 +85,26 @@ internal data class PokemonP2(
PokemonProperties.CUSTOM_PROPERTIES_CODEC.optionalFieldOf(DataKeys.POKEMON_DATA, arrayListOf()).forGetter(PokemonP2::customProperties),
Nature.BY_IDENTIFIER_CODEC.fieldOf(DataKeys.POKEMON_NATURE).forGetter(PokemonP2::nature),
Nature.BY_IDENTIFIER_CODEC.optionalFieldOf(DataKeys.POKEMON_MINTED_NATURE).forGetter(PokemonP2::mintedNature),
ItemStack.CODEC.optionalFieldOf(DataKeys.HELD_ITEM, ItemStack.EMPTY).forGetter(PokemonP2::heldItem),
ItemStack.CODEC.mapResult(object: Codec.ResultFunction<ItemStack> {
override fun <T : Any> apply(
ops: DynamicOps<T>,
input: T,
a: DataResult<Pair<ItemStack, T>>
): DataResult<Pair<ItemStack, T>> {
a.error().ifPresent {
Cobblemon.LOGGER.error("Failed to read held item due to following error: ${it.message()}")
}
return DataResult.success(a.result().orElse(Pair.of(ItemStack.EMPTY, input)))
}
override fun <T : Any> coApply(
ops: DynamicOps<T>,
input: ItemStack?,
t: DataResult<T>
): DataResult<T> {
return t
}
}).optionalFieldOf(DataKeys.HELD_ITEM, ItemStack.EMPTY).forGetter(PokemonP2::heldItem),
CompoundTag.CODEC.fieldOf(DataKeys.POKEMON_PERSISTENT_DATA).forGetter(PokemonP2::persistentData),
UUIDUtil.LENIENT_CODEC.optionalFieldOf(DataKeys.TETHERING_ID).forGetter(PokemonP2::tetheringId),
TeraType.BY_IDENTIFIER_CODEC.fieldOf(DataKeys.POKEMON_TERA_TYPE).forGetter(PokemonP2::teraType),