From a286fc0899f380a8793122fbe9a2680e93a4f32c Mon Sep 17 00:00:00 2001 From: Paul Date: Fri, 4 Nov 2022 23:17:45 +1000 Subject: [PATCH 1/3] Fixed syncing of learnset, stabilize registry sync order, fix client logging warnings for ability parsing when it shouldn't be doing it --- .../pokemod/common/api/moves/MoveTemplate.kt | 1 + .../cablemc/pokemod/common/api/moves/Moves.kt | 13 +++++++++ .../common/api/pokemon/moves/Learnset.kt | 27 +++++++++++++++++++ .../client/entity/PokemonClientDelegate.kt | 1 + .../common/data/CobbledDataProvider.kt | 2 +- .../pokemod/common/pokemon/FormData.kt | 9 +++++-- .../cablemc/pokemod/common/pokemon/Pokemon.kt | 2 +- .../cablemc/pokemod/common/pokemon/Species.kt | 2 ++ 8 files changed, 53 insertions(+), 4 deletions(-) diff --git a/common/src/main/kotlin/com/cablemc/pokemod/common/api/moves/MoveTemplate.kt b/common/src/main/kotlin/com/cablemc/pokemod/common/api/moves/MoveTemplate.kt index 862ba5a7ae..f8cceb060a 100644 --- a/common/src/main/kotlin/com/cablemc/pokemod/common/api/moves/MoveTemplate.kt +++ b/common/src/main/kotlin/com/cablemc/pokemod/common/api/moves/MoveTemplate.kt @@ -43,6 +43,7 @@ open class MoveTemplate( val effectChance: Double, val effectStatus: String ) { + var id = 0 val displayName: MutableText get() = lang("move.$name") val description: MutableText diff --git a/common/src/main/kotlin/com/cablemc/pokemod/common/api/moves/Moves.kt b/common/src/main/kotlin/com/cablemc/pokemod/common/api/moves/Moves.kt index 884a8dc503..28b83a39e2 100644 --- a/common/src/main/kotlin/com/cablemc/pokemod/common/api/moves/Moves.kt +++ b/common/src/main/kotlin/com/cablemc/pokemod/common/api/moves/Moves.kt @@ -42,18 +42,31 @@ object Moves : JsonDataRegistry { override val observable = SimpleObservable() private val allMoves = mutableMapOf() + private val idMapping = mutableMapOf() override fun reload(data: Map) { this.allMoves.clear() data.forEach { (identifier, moveTemplate) -> this.allMoves[identifier.path] = moveTemplate } + applyIDs() Pokemod.LOGGER.info("Loaded {} moves", this.allMoves.size) this.observable.emit(this) } + private fun applyIDs() { + var id = 0 + this.allMoves.values + .sortedBy { it.name } + .forEach { + it.id = id++ + idMapping[it.id] = it + } + } + override fun sync(player: ServerPlayerEntity) { MovesRegistrySyncPacket().sendToPlayer(player) } fun getByName(name: String) = allMoves[name.lowercase()] + fun getByNumericalId(id: Int) = idMapping[id]!! fun getByNameOrDummy(name: String) = allMoves[name.lowercase()] ?: MoveTemplate.dummy(name.lowercase()) fun getExceptional() = getByName("tackle") ?: allMoves.values.random() fun count() = allMoves.size diff --git a/common/src/main/kotlin/com/cablemc/pokemod/common/api/pokemon/moves/Learnset.kt b/common/src/main/kotlin/com/cablemc/pokemod/common/api/pokemon/moves/Learnset.kt index 9c2b42faef..f1cee310b7 100644 --- a/common/src/main/kotlin/com/cablemc/pokemod/common/api/pokemon/moves/Learnset.kt +++ b/common/src/main/kotlin/com/cablemc/pokemod/common/api/pokemon/moves/Learnset.kt @@ -10,8 +10,12 @@ package com.cablemc.pokemod.common.api.pokemon.moves import com.cablemc.pokemod.common.api.moves.MoveTemplate import com.cablemc.pokemod.common.api.moves.Moves +import com.cablemc.pokemod.common.net.IntSize import com.cablemc.pokemod.common.util.isInt +import com.cablemc.pokemod.common.util.readSizedInt +import com.cablemc.pokemod.common.util.writeSizedInt import com.google.gson.JsonElement +import net.minecraft.network.PacketByteBuf open class Learnset { class Interpreter( @@ -81,4 +85,27 @@ open class Learnset { .sortedBy { it.key } .flatMap { it.value } .toSet() + + fun encodeLevelUpMoves(buffer: PacketByteBuf) { + buffer.writeSizedInt(IntSize.U_BYTE, levelUpMoves.size) + for ((level, moves) in levelUpMoves) { + buffer.writeSizedInt(IntSize.U_SHORT, level) + buffer.writeSizedInt(IntSize.U_BYTE, moves.size) + for (move in moves) { + buffer.writeSizedInt(IntSize.U_SHORT, move.id) + } + } + } + + fun decodeLevelUpMoves(buffer: PacketByteBuf) { + repeat(times = buffer.readSizedInt(IntSize.U_BYTE)) { + val level = buffer.readSizedInt(IntSize.U_SHORT) + val moves = mutableListOf() + repeat(times = buffer.readSizedInt(IntSize.U_BYTE)) { + val move = Moves.getByNumericalId(buffer.readSizedInt(IntSize.U_SHORT)) + moves.add(move) + } + levelUpMoves[level] = moves + } + } } \ No newline at end of file diff --git a/common/src/main/kotlin/com/cablemc/pokemod/common/client/entity/PokemonClientDelegate.kt b/common/src/main/kotlin/com/cablemc/pokemod/common/client/entity/PokemonClientDelegate.kt index 0c5f846ad9..3eefd6ed39 100644 --- a/common/src/main/kotlin/com/cablemc/pokemod/common/client/entity/PokemonClientDelegate.kt +++ b/common/src/main/kotlin/com/cablemc/pokemod/common/client/entity/PokemonClientDelegate.kt @@ -42,6 +42,7 @@ class PokemonClientDelegate : PoseableEntityState(), PokemonSideD private val minimumFallSpeed = -0.1F private val intensityVelocityCap = -0.5F override fun changePokemon(pokemon: Pokemon) { + pokemon.isClient = true entity.subscriptions.add(entity.species.subscribeIncludingCurrent { currentPose = null entity.pokemon.species = PokemonSpecies.getByIdentifier(Identifier(it))!! // TODO exception handling diff --git a/common/src/main/kotlin/com/cablemc/pokemod/common/data/CobbledDataProvider.kt b/common/src/main/kotlin/com/cablemc/pokemod/common/data/CobbledDataProvider.kt index c216e90f57..cc92613b9d 100644 --- a/common/src/main/kotlin/com/cablemc/pokemod/common/data/CobbledDataProvider.kt +++ b/common/src/main/kotlin/com/cablemc/pokemod/common/data/CobbledDataProvider.kt @@ -27,7 +27,7 @@ internal object CobbledDataProvider : DataProvider { // Both Forge n Fabric keep insertion order so if a registry depends on another simply register it after var canReload = true - private val registries = hashMapOf() + private val registries = linkedMapOf() fun registerDefaults() { this.register(Moves) diff --git a/common/src/main/kotlin/com/cablemc/pokemod/common/pokemon/FormData.kt b/common/src/main/kotlin/com/cablemc/pokemod/common/pokemon/FormData.kt index 820389e409..c2f9c738f5 100644 --- a/common/src/main/kotlin/com/cablemc/pokemod/common/pokemon/FormData.kt +++ b/common/src/main/kotlin/com/cablemc/pokemod/common/pokemon/FormData.kt @@ -13,12 +13,12 @@ import com.cablemc.pokemod.common.api.drop.DropTable import com.cablemc.pokemod.common.api.moves.MoveTemplate import com.cablemc.pokemod.common.api.net.Decodable import com.cablemc.pokemod.common.api.net.Encodable -import com.cablemc.pokemod.common.api.pokemon.moves.Learnset import com.cablemc.pokemod.common.api.pokemon.effect.ShoulderEffect import com.cablemc.pokemod.common.api.pokemon.egg.EggGroup import com.cablemc.pokemod.common.api.pokemon.evolution.Evolution import com.cablemc.pokemod.common.api.pokemon.evolution.PreEvolution import com.cablemc.pokemod.common.api.pokemon.experience.ExperienceGroup +import com.cablemc.pokemod.common.api.pokemon.moves.Learnset import com.cablemc.pokemod.common.api.pokemon.stats.Stat import com.cablemc.pokemod.common.api.pokemon.stats.Stats import com.cablemc.pokemod.common.api.types.ElementalType @@ -62,7 +62,7 @@ class FormData( @SerializedName("shoulderEffects") private val _shoulderEffects: MutableList? = null, @SerializedName("moves") - private val _moves: Learnset? = null, + private var _moves: Learnset? = null, @SerializedName("evolutions") private val _evolutions: MutableSet? = null, @SerializedName("abilities") @@ -219,6 +219,8 @@ class FormData( buffer.writeNullable(this._height) { pb, height -> pb.writeFloat(height) } buffer.writeNullable(this._weight) { pb, weight -> pb.writeFloat(weight) } buffer.writeNullable(this._pokedex) { pb1, pokedex -> pb1.writeCollection(pokedex) { pb2, line -> pb2.writeString(line) } } + buffer.writeBoolean(_moves != null) + _moves?.encodeLevelUpMoves(buffer) } override fun decode(buffer: PacketByteBuf) { @@ -232,5 +234,8 @@ class FormData( this._height = buffer.readNullable { pb -> pb.readFloat() } this._weight = buffer.readNullable { pb -> pb.readFloat() } this._pokedex = buffer.readNullable { pb -> pb.readList { it.readString() } } + if (buffer.readBoolean()) { + _moves = Learnset().also { it.decodeLevelUpMoves(buffer) } + } } } diff --git a/common/src/main/kotlin/com/cablemc/pokemod/common/pokemon/Pokemon.kt b/common/src/main/kotlin/com/cablemc/pokemod/common/pokemon/Pokemon.kt index 9ec20a4f34..9dacb77f2a 100644 --- a/common/src/main/kotlin/com/cablemc/pokemod/common/pokemon/Pokemon.kt +++ b/common/src/main/kotlin/com/cablemc/pokemod/common/pokemon/Pokemon.kt @@ -332,7 +332,7 @@ open class Pokemon { } } - private var isClient = false + var isClient = false val storeCoordinates = SettableObservable?>(null) // We want non-optional evolutions to trigger first to avoid unnecessary packets and any cost associate with an optional one that would just be lost diff --git a/common/src/main/kotlin/com/cablemc/pokemod/common/pokemon/Species.kt b/common/src/main/kotlin/com/cablemc/pokemod/common/pokemon/Species.kt index 96e52db0d4..e285ef610a 100644 --- a/common/src/main/kotlin/com/cablemc/pokemod/common/pokemon/Species.kt +++ b/common/src/main/kotlin/com/cablemc/pokemod/common/pokemon/Species.kt @@ -148,6 +148,7 @@ class Species : ClientDataSynchronizer { buffer.writeNullable(this.secondaryType) { pb, type -> pb.writeString(type.name) } buffer.writeCollection(this.pokedex) { pb, line -> pb.writeString(line) } buffer.writeCollection(this.forms) { pb, form -> form.encode(pb) } + moves.encodeLevelUpMoves(buffer) } override fun decode(buffer: PacketByteBuf) { @@ -162,6 +163,7 @@ class Species : ClientDataSynchronizer { pokedex += buffer.readList { pb -> pb.readString() } forms.clear() forms += buffer.readList{ pb -> FormData().apply { decode(pb) } }.filterNotNull() + moves.decodeLevelUpMoves(buffer) } } From 22291bd1c700ae2e5af10942983e4ebecbd4a2a0 Mon Sep 17 00:00:00 2001 From: Paul Date: Fri, 4 Nov 2022 23:24:28 +1000 Subject: [PATCH 2/3] Make isClient internal --- .../main/kotlin/com/cablemc/pokemod/common/pokemon/Pokemon.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/src/main/kotlin/com/cablemc/pokemod/common/pokemon/Pokemon.kt b/common/src/main/kotlin/com/cablemc/pokemod/common/pokemon/Pokemon.kt index 9dacb77f2a..9d1cf198c8 100644 --- a/common/src/main/kotlin/com/cablemc/pokemod/common/pokemon/Pokemon.kt +++ b/common/src/main/kotlin/com/cablemc/pokemod/common/pokemon/Pokemon.kt @@ -332,7 +332,7 @@ open class Pokemon { } } - var isClient = false + internal var isClient = false val storeCoordinates = SettableObservable?>(null) // We want non-optional evolutions to trigger first to avoid unnecessary packets and any cost associate with an optional one that would just be lost From 7cacd1048744c02af691faedd62e6d8f24178ae0 Mon Sep 17 00:00:00 2001 From: Paul Date: Fri, 4 Nov 2022 23:27:09 +1000 Subject: [PATCH 3/3] Use writeNullable and readNullable for _moves --- .../kotlin/com/cablemc/pokemod/common/pokemon/FormData.kt | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/common/src/main/kotlin/com/cablemc/pokemod/common/pokemon/FormData.kt b/common/src/main/kotlin/com/cablemc/pokemod/common/pokemon/FormData.kt index c2f9c738f5..beec4d9195 100644 --- a/common/src/main/kotlin/com/cablemc/pokemod/common/pokemon/FormData.kt +++ b/common/src/main/kotlin/com/cablemc/pokemod/common/pokemon/FormData.kt @@ -220,7 +220,7 @@ class FormData( buffer.writeNullable(this._weight) { pb, weight -> pb.writeFloat(weight) } buffer.writeNullable(this._pokedex) { pb1, pokedex -> pb1.writeCollection(pokedex) { pb2, line -> pb2.writeString(line) } } buffer.writeBoolean(_moves != null) - _moves?.encodeLevelUpMoves(buffer) + buffer.writeNullable(_moves) { buf, moves -> moves.encodeLevelUpMoves(buf)} } override fun decode(buffer: PacketByteBuf) { @@ -234,8 +234,6 @@ class FormData( this._height = buffer.readNullable { pb -> pb.readFloat() } this._weight = buffer.readNullable { pb -> pb.readFloat() } this._pokedex = buffer.readNullable { pb -> pb.readList { it.readString() } } - if (buffer.readBoolean()) { - _moves = Learnset().also { it.decodeLevelUpMoves(buffer) } - } + this._moves = buffer.readNullable { pb -> Learnset().also { it.decodeLevelUpMoves(pb) }} } }