Compare commits

...
Author SHA1 Message Date
Plastered_Crab 35b2b33eb4 mega keystone? more like iron helmet 2026-09-14 23:03:03 -07:00
Plastered_Crab 9900fbf3d6 Get back to parity with main 2026-09-14 15:38:52 -07:00
Plastered_Crab 1e8d012371 Add in all non ZA and MD mega stones 2026-09-14 14:20:49 -07:00
Plastered_Crab 82ef84d82b Merge branch 'main' into mega-space-program
# Conflicts:
#	common/src/main/java/com/cobblemon/mod/common/mixin/ClientPacketListenerMixin.java
#	common/src/main/kotlin/com/cobblemon/mod/common/api/molang/function/EvolutionMoLangFunctions.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/api/molang/function/PokemonMoLangFunctions.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/api/tms/TechnicalMachines.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/block/entity/PokeSnackBlockEntity.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/block/tmmachine/TMMachineMenu.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/client/gui/summary/Summary.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/client/render/models/blockbench/pokemon/gen1/RattataAlolanModel.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/client/render/models/blockbench/pokemon/gen1/RattataModel.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/net/messages/client/pokemon/update/evolution/ClientboundSeatAssignmentPacket.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/pokemon/requirements/StatCompareRequirement.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/pokemon/requirements/StatEqualRequirement.kt
#	common/src/main/resources/data/cobblemon/species/generation5/panpour.json
#	common/src/main/resources/data/cobblemon/species/generation8/duraludon.json
2026-09-12 16:15:46 -07:00
Plastered_Crab c0154cd82d Add Mega Shards and Mega Stones as well as simple "mega bond" increasing system 2026-09-12 16:02:03 -07:00
Plastered_Crab 1c9c833a49 Add Mega Shards and Mega Stones as well as simple "mega bond" increasing system 2026-09-12 15:52:50 -07:00
Plastered_Crab 901e3e09e1 Add Mega Shards and Mega Stones as well as simple "mega bond" increasing system 2026-09-12 14:44:44 -07:00
Plastered_Crab 94c159b42b Meteors land where they should and test spawning minior / dropping items 2026-08-03 20:17:00 -07:00
Hiroku 3c80a61011 Started on implementing falling stars, they hit the ground weirdly 2026-07-24 14:25:13 +10:00
Paul e29087c805 Added molang TransformationRequirement 2026-06-12 15:18:51 +10:00
Paul e850253d88 Implemented action-effect driven temporary form reversion and custom Schedulables in action effects 2026-06-12 14:42:14 +10:00
Paul bbb692f521 Moved transformation progress to a common location and reduced the Transformation tree complexity. Progress works for forms 2026-06-12 12:22:15 +10:00
Paul da1d67bbe6 Clean up parentForm mechanism in FormData 2026-06-08 09:01:24 +10:00
Paul 792834f219 Oh yeah compilation should succeed 2026-06-04 18:27:37 +10:00
Paul 94b31cd658 Remove comment 2026-06-04 18:08:52 +10:00
Paul 19364f39c6 Renaming and restructuring of the actual starting of transformations, added FormEvents 2026-06-04 14:45:13 +10:00
Paul 2fc8f6b9df Oi you got a loicense for that television bruv 2026-05-31 22:15:06 +10:00
Paul 9089ff3bbb Why is the species schema JSON malformed 2026-05-31 21:47:02 +10:00
Paul 90f581051c Simplifications and straightening of transformation controller class tree and codecs 2026-05-31 21:43:06 +10:00
Paul 061bdcc478 Action effect improvements for form transition effects, some cleanup of TemporaryForm reverting 2026-05-31 14:52:12 +10:00
Paul 6811394f71 Compilation fixes and merge conflict resolutions 2026-05-30 13:08:20 +10:00
Paul 1235a70323 Conflict resolve maybe 2026-05-26 21:15:00 +10:00
Segfault Guy d94952347f Portrait updates and form effects. 2025-04-30 00:30:06 -04:00
Segfault Guy 7fe6141640 form20 blaze it 2025-04-20 23:41:12 -04:00
Segfault Guy 4b1653ca6c Merge remote-tracking branch 'origin/main' into form_changes 2025-04-20 20:53:54 -04:00
Segfault Guy 7265ab57b9 Apply species schema changes to evolutions. 2025-04-11 01:47:41 -04:00
Segfault Guy 27e3a95b06 cleanup test changes 2025-04-11 01:17:29 -04:00
Segfault Guy 38de3c6267 In-battle form changes and PokemonProperties form completion. 2025-04-09 00:18:10 -04:00
Segfault Guy 376e5ac906 Merge branch 'main' into form_changes 2025-03-18 22:26:00 -04:00
Segfault Guy b225283dcc Toggleable, deferrable, and wild forms. 2025-03-12 23:00:29 -04:00
Segfault Guy b90f852a71 Clear invalid forms on species change. 2025-02-24 20:12:23 -05:00
Segfault Guy fdf7a9703a coalesce temp and perm forms under same property and instead deserialize by custom adapter instead of having unique properties. 2025-02-23 23:21:43 -05:00
Segfault Guy bb41f28342 Merge remote-tracking branch 'origin/main' into form_changes 2025-02-18 22:33:23 -05:00
Segfault Guy c5ee7ebe7a Fix ability registration for forms. 2025-02-11 21:40:35 -05:00
Segfault Guy f6ae10e1d9 It's about f(orm)cking time. 2025-02-03 23:38:53 -05:00
Segfault GuyandSegfault Guy b2070b53fb Changing form... changes form? Wow! 2024-12-03 23:41:17 -05:00
Segfault GuyandSegfault Guy 7fb873dc2c Showdown Form and Species registration rework. 2024-12-03 23:10:25 -05:00
Segfault GuyandSegfault Guy 641f529de3 Better Form and Evolution triggering. 2024-12-03 19:12:41 -05:00
Segfault GuyandSegfault Guy db9fb4fefa Refactor Evolution and add Transformation to expand application of Evolution events and requirements. 2024-12-02 23:13:57 -05:00
1011 changed files with 8006 additions and 4937 deletions
+2 -2
View File
@@ -1,9 +1,9 @@
import utilities.isSnapshot
import utilities.version
import java.time.OffsetDateTime import java.time.OffsetDateTime
import java.time.ZoneOffset import java.time.ZoneOffset
import java.time.format.DateTimeFormatter import java.time.format.DateTimeFormatter
import utilities.isSnapshot
import utilities.version
/* /*
* *
@@ -8,7 +8,6 @@
package com.cobblemon.mod.common.mixin; package com.cobblemon.mod.common.mixin;
import com.cobblemon.mod.common.CobblemonNetwork;
import com.cobblemon.mod.common.OrientationControllable; import com.cobblemon.mod.common.OrientationControllable;
import com.cobblemon.mod.common.api.orientation.OrientationController; import com.cobblemon.mod.common.api.orientation.OrientationController;
import com.cobblemon.mod.common.api.pokemon.effect.ShoulderEffectRegistry; import com.cobblemon.mod.common.api.pokemon.effect.ShoulderEffectRegistry;
@@ -18,7 +17,6 @@ import com.cobblemon.mod.common.api.riding.behaviour.types.liquid.SubmarineBehav
import com.cobblemon.mod.common.client.entity.PokemonClientDelegate; import com.cobblemon.mod.common.client.entity.PokemonClientDelegate;
import com.cobblemon.mod.common.client.render.MatrixWrapper; import com.cobblemon.mod.common.client.render.MatrixWrapper;
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity; import com.cobblemon.mod.common.entity.pokemon.PokemonEntity;
import com.cobblemon.mod.common.net.messages.server.orientation.ServerboundUpdateOrientationPacket;
import com.llamalad7.mixinextras.injector.wrapoperation.Operation; import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.level.ServerPlayer;
@@ -10,9 +10,7 @@ package com.cobblemon.mod.common.mixin.accessor;
import net.minecraft.client.gui.components.StateSwitchingButton; import net.minecraft.client.gui.components.StateSwitchingButton;
import net.minecraft.client.gui.screens.recipebook.RecipeBookComponent; import net.minecraft.client.gui.screens.recipebook.RecipeBookComponent;
import net.minecraft.network.chat.Component;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Mutable;
import org.spongepowered.asm.mixin.gen.Accessor; import org.spongepowered.asm.mixin.gen.Accessor;
@Mixin(RecipeBookComponent.class) @Mixin(RecipeBookComponent.class)
@@ -15,11 +15,9 @@ import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
import com.llamalad7.mixinextras.sugar.Local; import com.llamalad7.mixinextras.sugar.Local;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.core.NonNullList; import net.minecraft.core.NonNullList;
import net.minecraft.world.Containers; import net.minecraft.world.Containers;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.item.alchemy.PotionBrewing; import net.minecraft.world.item.alchemy.PotionBrewing;
import net.minecraft.world.item.crafting.RecipeHolder; import net.minecraft.world.item.crafting.RecipeHolder;
import net.minecraft.world.item.crafting.RecipeManager; import net.minecraft.world.item.crafting.RecipeManager;
@@ -34,6 +32,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
@Mixin(BrewingStandBlockEntity.class) @Mixin(BrewingStandBlockEntity.class)
public class BrewingStandBlockEntityMixin { public class BrewingStandBlockEntityMixin {
@@ -9,17 +9,11 @@
package com.cobblemon.mod.common.mixin.brewing; package com.cobblemon.mod.common.mixin.brewing;
import com.cobblemon.mod.common.duck.RecipeAwareSlot; import com.cobblemon.mod.common.duck.RecipeAwareSlot;
import com.cobblemon.mod.common.item.crafting.brewingstand.BrewingStandRecipe;
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
import com.llamalad7.mixinextras.sugar.Local;
import net.minecraft.world.Container; import net.minecraft.world.Container;
import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.inventory.BrewingStandMenu; import net.minecraft.world.inventory.BrewingStandMenu;
import net.minecraft.world.inventory.ContainerData; import net.minecraft.world.inventory.ContainerData;
import net.minecraft.world.inventory.Slot; import net.minecraft.world.inventory.Slot;
import net.minecraft.world.item.ItemStack;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Inject;
@@ -13,7 +13,6 @@ import com.cobblemon.mod.common.item.crafting.brewingstand.BrewingStandRecipe;
import net.minecraft.world.inventory.BrewingStandMenu; import net.minecraft.world.inventory.BrewingStandMenu;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.crafting.RecipeManager; import net.minecraft.world.item.crafting.RecipeManager;
import net.minecraft.world.level.Level;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
@@ -19,7 +19,6 @@ import net.minecraft.client.Camera;
import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.BlockGetter; import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.Vec3;
import org.joml.Quaternionf;
import org.joml.Vector3f; import org.joml.Vector3f;
import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
@@ -10,9 +10,7 @@ package com.cobblemon.mod.common.mixin.client;
import com.cobblemon.mod.common.CobblemonRecipeCategories; import com.cobblemon.mod.common.CobblemonRecipeCategories;
import com.cobblemon.mod.common.item.crafting.CookingPotBookCategory; import com.cobblemon.mod.common.item.crafting.CookingPotBookCategory;
import com.cobblemon.mod.common.item.crafting.CookingPotRecipe;
import com.cobblemon.mod.common.item.crafting.CookingPotRecipeBase; import com.cobblemon.mod.common.item.crafting.CookingPotRecipeBase;
import com.cobblemon.mod.common.item.crafting.CookingPotShapelessRecipe;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
@@ -97,10 +97,10 @@ import com.cobblemon.mod.common.pokemon.Pokemon
import com.cobblemon.mod.common.pokemon.aspects.ALPHA_ASPECT import com.cobblemon.mod.common.pokemon.aspects.ALPHA_ASPECT
import com.cobblemon.mod.common.pokemon.aspects.CHARACTERISTIC_RAINBOW_ASPECT import com.cobblemon.mod.common.pokemon.aspects.CHARACTERISTIC_RAINBOW_ASPECT
import com.cobblemon.mod.common.pokemon.aspects.COSMETIC_SLOT_ASPECT import com.cobblemon.mod.common.pokemon.aspects.COSMETIC_SLOT_ASPECT
import com.cobblemon.mod.common.pokemon.aspects.FORM_ASPECTS
import com.cobblemon.mod.common.pokemon.aspects.GENDER_ASPECT import com.cobblemon.mod.common.pokemon.aspects.GENDER_ASPECT
import com.cobblemon.mod.common.pokemon.aspects.MARK_ASPECT import com.cobblemon.mod.common.pokemon.aspects.MARK_ASPECT
import com.cobblemon.mod.common.pokemon.aspects.SHINY_ASPECT import com.cobblemon.mod.common.pokemon.aspects.SHINY_ASPECT
import com.cobblemon.mod.common.pokemon.evolution.variants.BlockClickEvolution
import com.cobblemon.mod.common.pokemon.feature.SlowpokeTailRegrowthSpeciesFeature import com.cobblemon.mod.common.pokemon.feature.SlowpokeTailRegrowthSpeciesFeature
import com.cobblemon.mod.common.pokemon.feature.SlowpokeTailRegrowthSpeciesFeatureProvider import com.cobblemon.mod.common.pokemon.feature.SlowpokeTailRegrowthSpeciesFeatureProvider
import com.cobblemon.mod.common.pokemon.feature.TagSeasonResolver import com.cobblemon.mod.common.pokemon.feature.TagSeasonResolver
@@ -115,6 +115,7 @@ import com.cobblemon.mod.common.pokemon.properties.NoAIProperty
import com.cobblemon.mod.common.pokemon.properties.UnaspectPropertyType import com.cobblemon.mod.common.pokemon.properties.UnaspectPropertyType
import com.cobblemon.mod.common.pokemon.properties.UncatchableProperty import com.cobblemon.mod.common.pokemon.properties.UncatchableProperty
import com.cobblemon.mod.common.pokemon.stat.CobblemonStatProvider import com.cobblemon.mod.common.pokemon.stat.CobblemonStatProvider
import com.cobblemon.mod.common.pokemon.transformation.triggers.BlockClickTrigger
import com.cobblemon.mod.common.starter.CobblemonStarterHandler import com.cobblemon.mod.common.starter.CobblemonStarterHandler
import com.cobblemon.mod.common.util.* import com.cobblemon.mod.common.util.*
import com.cobblemon.mod.common.world.feature.CobblemonPlacedFeatures import com.cobblemon.mod.common.world.feature.CobblemonPlacedFeatures
@@ -273,13 +274,8 @@ object Cobblemon {
PlatformEvents.RIGHT_CLICK_BLOCK.subscribe { event -> PlatformEvents.RIGHT_CLICK_BLOCK.subscribe { event ->
val player = event.player val player = event.player
val block = player.level().getBlockState(event.pos).block val block = player.level().getBlockState(event.pos).block
player.party().forEach { pokemon -> val context = BlockClickTrigger.Context(block, player.level())
pokemon.lockedEvolutions player.party().forEach { pokemon -> pokemon.triggerTransformations<BlockClickTrigger>(context) }
.filterIsInstance<BlockClickEvolution>()
.forEach { evolution ->
evolution.attemptEvolution(pokemon, BlockClickEvolution.BlockInteractionContext(block, player.level()))
}
}
} }
PlatformEvents.CHANGE_DIMENSION.subscribe { PlatformEvents.CHANGE_DIMENSION.subscribe {
@@ -323,6 +319,7 @@ object Cobblemon {
SHINY_ASPECT.register() SHINY_ASPECT.register()
GENDER_ASPECT.register() GENDER_ASPECT.register()
FORM_ASPECTS.register()
COSMETIC_SLOT_ASPECT.register() COSMETIC_SLOT_ASPECT.register()
CHARACTERISTIC_RAINBOW_ASPECT.register() CHARACTERISTIC_RAINBOW_ASPECT.register()
ALPHA_ASPECT.register() ALPHA_ASPECT.register()
@@ -9,6 +9,7 @@
package com.cobblemon.mod.common package com.cobblemon.mod.common
import com.bedrockk.molang.Expression import com.bedrockk.molang.Expression
import com.cobblemon.mod.common.CobblemonBehaviours.autoPokemonBehaviours
import com.cobblemon.mod.common.CobblemonNetwork.sendPacket import com.cobblemon.mod.common.CobblemonNetwork.sendPacket
import com.cobblemon.mod.common.api.ai.CobblemonBehaviour import com.cobblemon.mod.common.api.ai.CobblemonBehaviour
import com.cobblemon.mod.common.api.ai.config.BehaviourConfig import com.cobblemon.mod.common.api.ai.config.BehaviourConfig
@@ -19,16 +20,7 @@ import com.cobblemon.mod.common.api.molang.ExpressionLike
import com.cobblemon.mod.common.api.npc.configuration.MoLangConfigVariable import com.cobblemon.mod.common.api.npc.configuration.MoLangConfigVariable
import com.cobblemon.mod.common.api.reactive.SimpleObservable import com.cobblemon.mod.common.api.reactive.SimpleObservable
import com.cobblemon.mod.common.net.messages.client.data.BehaviourSyncPacket import com.cobblemon.mod.common.net.messages.client.data.BehaviourSyncPacket
import com.cobblemon.mod.common.util.adapters.ActivityAdapter import com.cobblemon.mod.common.util.adapters.*
import com.cobblemon.mod.common.util.adapters.BehaviourConfigAdapter
import com.cobblemon.mod.common.util.adapters.ExpressionAdapter
import com.cobblemon.mod.common.util.adapters.ExpressionLikeAdapter
import com.cobblemon.mod.common.util.adapters.ExpressionOrEntityVariableAdapter
import com.cobblemon.mod.common.util.adapters.IdentifierAdapter
import com.cobblemon.mod.common.util.adapters.MemoryModuleTypeAdapter
import com.cobblemon.mod.common.util.adapters.SensorTypeAdapter
import com.cobblemon.mod.common.util.adapters.TaskConfigAdapter
import com.cobblemon.mod.common.util.adapters.TranslatedTextAdapter
import com.cobblemon.mod.common.util.cobblemonResource import com.cobblemon.mod.common.util.cobblemonResource
import com.cobblemon.mod.common.util.endsWith import com.cobblemon.mod.common.util.endsWith
import com.google.gson.Gson import com.google.gson.Gson
@@ -41,6 +41,8 @@ object CobblemonCommands {
HeldItemCommand.register(dispatcher, registry) HeldItemCommand.register(dispatcher, registry)
PcCommand.register(dispatcher) PcCommand.register(dispatcher)
SpawnPokemonFromPool.register(dispatcher) SpawnPokemonFromPool.register(dispatcher)
SpawnMeteorCommand.register(dispatcher)
SetMegaBondCommand.register(dispatcher)
PokeboxCommand.register(dispatcher) PokeboxCommand.register(dispatcher)
PokedexCommand.register(dispatcher) PokedexCommand.register(dispatcher)
TestStoreCommand.register(dispatcher) TestStoreCommand.register(dispatcher)
@@ -16,6 +16,7 @@ import com.cobblemon.mod.common.entity.generic.GenericBedrockEntity
import com.cobblemon.mod.common.entity.npc.NPCEntity import com.cobblemon.mod.common.entity.npc.NPCEntity
import com.cobblemon.mod.common.entity.pokeball.EmptyPokeBallEntity import com.cobblemon.mod.common.entity.pokeball.EmptyPokeBallEntity
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import com.cobblemon.mod.common.entity.projectile.FallingStarEntity
import com.cobblemon.mod.common.platform.PlatformRegistry import com.cobblemon.mod.common.platform.PlatformRegistry
import com.cobblemon.mod.common.util.cobblemonResource import com.cobblemon.mod.common.util.cobblemonResource
import net.minecraft.core.Registry import net.minecraft.core.Registry
@@ -95,6 +96,15 @@ object CobblemonEntities : PlatformRegistry<Registry<EntityType<*>>, ResourceKey
EntityType.Builder.of({ _, world -> NPCEntity(world) }, MobCategory.CREATURE).build("$NPC_KEY") EntityType.Builder.of({ _, world -> NPCEntity(world) }, MobCategory.CREATURE).build("$NPC_KEY")
) )
@JvmField
val FALLING_STAR_KEY = cobblemonResource("falling_star")
@JvmField
val FALLING_STAR: EntityType<FallingStarEntity> = create(
FALLING_STAR_KEY.path,
EntityType.Builder.of(::FallingStarEntity, MobCategory.MISC).sized(0.5F, 0.5F).clientTrackingRange(8)
.build(FALLING_STAR_KEY.toString())
)
fun registerAttributes(consumer: (EntityType<out LivingEntity>, AttributeSupplier.Builder) -> Unit) { fun registerAttributes(consumer: (EntityType<out LivingEntity>, AttributeSupplier.Builder) -> Unit) {
consumer(POKEMON, PokemonEntity.createAttributes()) consumer(POKEMON, PokemonEntity.createAttributes())
consumer(NPC, NPCEntity.createAttributes()) consumer(NPC, NPCEntity.createAttributes())
@@ -19,7 +19,6 @@ import net.minecraft.server.level.ServerPlayer
import net.minecraft.server.packs.PackType import net.minecraft.server.packs.PackType
import net.minecraft.server.packs.resources.PreparableReloadListener import net.minecraft.server.packs.resources.PreparableReloadListener
import net.minecraft.tags.TagKey import net.minecraft.tags.TagKey
import net.minecraft.world.inventory.MenuType
import net.minecraft.world.level.GameRules import net.minecraft.world.level.GameRules
import net.minecraft.world.level.ItemLike import net.minecraft.world.level.ItemLike
import net.minecraft.world.level.biome.Biome import net.minecraft.world.level.biome.Biome
@@ -33,6 +33,12 @@ object CobblemonItemComponents : PlatformRegistry<Registry<DataComponentType<*>>
.networkSynchronized(HeldItemEffectComponent.PACKET_CODEC) .networkSynchronized(HeldItemEffectComponent.PACKET_CODEC)
.build()) .build())
@JvmField
val MEGA_BOND: DataComponentType<MegaBondComponent> = create("mega_bond", DataComponentType.builder<MegaBondComponent>()
.persistent(MegaBondComponent.CODEC)
.networkSynchronized(MegaBondComponent.PACKET_CODEC)
.build())
@JvmField @JvmField
val BAIT: DataComponentType<RodBaitComponent> = create("bait", DataComponentType.builder<RodBaitComponent>() val BAIT: DataComponentType<RodBaitComponent> = create("bait", DataComponentType.builder<RodBaitComponent>()
.persistent(RodBaitComponent.CODEC) .persistent(RodBaitComponent.CODEC)
@@ -914,6 +914,10 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
val THUNDER_STONE = noSettingsItem("thunder_stone") val THUNDER_STONE = noSettingsItem("thunder_stone")
@JvmField @JvmField
val WATER_STONE = noSettingsItem("water_stone") val WATER_STONE = noSettingsItem("water_stone")
@JvmField
val MEGA_SHARD = noSettingsItem("mega_shard")
@JvmField
val DORMANT_MEGA_STONE = heldItem("dormant_mega_stone")
val wearables = mutableListOf<WearableItem>() val wearables = mutableListOf<WearableItem>()
//Wearable items (these items should have a corresponding 3D model) //Wearable items (these items should have a corresponding 3D model)
@@ -932,14 +936,34 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
@JvmField @JvmField
val ABILITY_SHIELD = heldItem("ability_shield") val ABILITY_SHIELD = heldItem("ability_shield")
@JvmField @JvmField
val ABOMASITE = heldItem("abomasite")
@JvmField
val ABSOLITE = heldItem("absolite")
@JvmField
val ABSORB_BULB = heldItem("absorb_bulb") val ABSORB_BULB = heldItem("absorb_bulb")
@JvmField @JvmField
val AERODACTYLITE = heldItem("aerodactylite")
@JvmField
val AGGRONITE = heldItem("aggronite")
@JvmField
val AIR_BALLOON = heldItem("air_balloon") val AIR_BALLOON = heldItem("air_balloon")
@JvmField @JvmField
val ALAKAZITE = heldItem("alakazite")
@JvmField
val ALTARIANITE = heldItem("altarianite")
@JvmField
val AMPHAROSITE = heldItem("ampharosite")
@JvmField
val ASSAULT_VEST = heldItem("assault_vest") val ASSAULT_VEST = heldItem("assault_vest")
@JvmField @JvmField
val BIG_ROOT = compostableBlockItem("big_root", CobblemonBlocks.BIG_ROOT, 0.30f) val BIG_ROOT = compostableBlockItem("big_root", CobblemonBlocks.BIG_ROOT, 0.30f)
@JvmField @JvmField
val AUDINITE = heldItem("audinite")
@JvmField
val BANETTITE = heldItem("banettite")
@JvmField
val BEEDRILLITE = heldItem("beedrillite")
@JvmField
val BINDING_BAND = heldItem("binding_band") val BINDING_BAND = heldItem("binding_band")
@JvmField @JvmField
val BLACK_BELT = heldItem("black_belt") val BLACK_BELT = heldItem("black_belt")
@@ -948,10 +972,20 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
@JvmField @JvmField
val BLUNDER_POLICY = itemNameBlockItem("blunder_policy", CobblemonBlocks.BLUNDER_POLICY) val BLUNDER_POLICY = itemNameBlockItem("blunder_policy", CobblemonBlocks.BLUNDER_POLICY)
@JvmField @JvmField
val BLASTOISINITE = heldItem("blastoisinite")
@JvmField
val BLAZIKENITE = heldItem("blazikenite")
@JvmField
val CAMERUPTITE = heldItem("cameruptite")
@JvmField
val CELL_BATTERY = heldItem("cell_battery") val CELL_BATTERY = heldItem("cell_battery")
@JvmField @JvmField
val CHARCOAL = heldItem("charcoal_stick", remappedName = "charcoal") val CHARCOAL = heldItem("charcoal_stick", remappedName = "charcoal")
@JvmField @JvmField
val CHARIZARDITE_X = heldItem("charizardite_x")
@JvmField
val CHARIZARDITE_Y = heldItem("charizardite_y")
@JvmField
val CHOICE_SCARF = heldItem("choice_scarf") val CHOICE_SCARF = heldItem("choice_scarf")
@JvmField @JvmField
val CLEANSE_TAG = itemNameBlockItem("cleanse_tag", CobblemonBlocks.CLEANSE_TAG) val CLEANSE_TAG = itemNameBlockItem("cleanse_tag", CobblemonBlocks.CLEANSE_TAG)
@@ -962,6 +996,8 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
@JvmField @JvmField
val DESTINY_KNOT = heldItem("destiny_knot") val DESTINY_KNOT = heldItem("destiny_knot")
@JvmField @JvmField
val DIANCITE = heldItem("diancite")
@JvmField
val DRAGON_FANG = heldItem("dragon_fang") val DRAGON_FANG = heldItem("dragon_fang")
@JvmField @JvmField
val EJECT_BUTTON = heldItem("eject_button") val EJECT_BUTTON = heldItem("eject_button")
@@ -984,20 +1020,42 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
@JvmField @JvmField
val FOCUS_SASH = heldItem("focus_sash") val FOCUS_SASH = heldItem("focus_sash")
@JvmField @JvmField
val GALLADITE = heldItem("galladite")
@JvmField
val GARCHOMPITE = heldItem("garchompite")
@JvmField
val GARDEVOIRITE = heldItem("gardevoirite")
@JvmField
val GENGARITE = heldItem("gengarite")
@JvmField
val GLALITITE = heldItem("glalitite")
@JvmField
val GRASSY_SEED = heldItem("grassy_seed") val GRASSY_SEED = heldItem("grassy_seed")
@JvmField @JvmField
val GRIP_CLAW = heldItem("grip_claw") val GRIP_CLAW = heldItem("grip_claw")
@JvmField @JvmField
val GYARADOSITE = heldItem("gyaradosite")
@JvmField
val HARD_STONE = heldItem("hard_stone") val HARD_STONE = heldItem("hard_stone")
@JvmField @JvmField
val HEAVY_DUTY_BOOTS = heldItem("heavy_duty_boots") val HEAVY_DUTY_BOOTS = heldItem("heavy_duty_boots")
@JvmField @JvmField
val HERACRONITE = heldItem("heracronite")
@JvmField
val HOUNDOOMINITE = heldItem("houndoominite")
@JvmField
val IRON_BALL = heldItem("iron_ball") val IRON_BALL = heldItem("iron_ball")
@JvmField @JvmField
val KANGASKHANITE = heldItem("kangaskhanite")
@JvmField
val LAGGING_TAIL = heldItem("lagging_tail") val LAGGING_TAIL = heldItem("lagging_tail")
@JvmField @JvmField
val LEFTOVERS = compostableHeldItem("leftovers", null, 0.50f) val LEFTOVERS = compostableHeldItem("leftovers", null, 0.50f)
@JvmField @JvmField
val LATIASITE = heldItem("latiasite")
@JvmField
val LATIOSITE = heldItem("latiosite")
@JvmField
val LIFE_ORB = heldItem("life_orb") val LIFE_ORB = heldItem("life_orb")
@JvmField @JvmField
val LIGHT_BALL = heldItem("light_ball") val LIGHT_BALL = heldItem("light_ball")
@@ -1006,20 +1064,40 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
@JvmField @JvmField
val LOADED_DICE = heldItem("loaded_dice") val LOADED_DICE = heldItem("loaded_dice")
@JvmField @JvmField
val LOPUNNITE = heldItem("lopunnite")
@JvmField
val LUCARIONITE = heldItem("lucarionite")
@JvmField
val LUCKY_EGG = heldItem("lucky_egg") val LUCKY_EGG = heldItem("lucky_egg")
@JvmField @JvmField
val LUMINOUS_MOSS = heldItem("luminous_moss") val LUMINOUS_MOSS = heldItem("luminous_moss")
@JvmField @JvmField
val MAGNET = heldItem("magnet") val MAGNET = heldItem("magnet")
@JvmField @JvmField
val MANECTITE = heldItem("manectite")
@JvmField
val MAWILITE = heldItem("mawilite")
@JvmField
val MEDICHAMITE = heldItem("medichamite")
@JvmField
val METAGROSSITE = heldItem("metagrossite")
@JvmField
val METRONOME = heldItem("metronome") val METRONOME = heldItem("metronome")
@JvmField @JvmField
val MEWTWONITE_X = heldItem("mewtwonite_x")
@JvmField
val MEWTWONITE_Y = heldItem("mewtwonite_y")
@JvmField
val MIRACLE_SEED = heldItem("miracle_seed") val MIRACLE_SEED = heldItem("miracle_seed")
@JvmField @JvmField
val MYSTIC_WATER = heldItem("mystic_water") val MYSTIC_WATER = heldItem("mystic_water")
@JvmField @JvmField
val NEVER_MELT_ICE = heldItem("never_melt_ice") val NEVER_MELT_ICE = heldItem("never_melt_ice")
@JvmField @JvmField
val PIDGEOTITE = heldItem("pidgeotite")
@JvmField
val PINSIRITE = heldItem("pinsirite")
@JvmField
val POISON_BARB = heldItem("poison_barb") val POISON_BARB = heldItem("poison_barb")
@JvmField @JvmField
val POWER_ANKLET = heldItem("power_anklet") val POWER_ANKLET = heldItem("power_anklet")
@@ -1048,10 +1126,20 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
@JvmField @JvmField
val ROOM_SERVICE = heldItem("room_service") val ROOM_SERVICE = heldItem("room_service")
@JvmField @JvmField
val SABLENITE = heldItem("sablenite")
@JvmField
val SALAMENCITE = heldItem("salamencite")
@JvmField
val SCEPTILITE = heldItem("sceptilite")
@JvmField
val SCIZORITE = heldItem("scizorite")
@JvmField
val SCOPE_LENS = heldItem("scope_lens") val SCOPE_LENS = heldItem("scope_lens")
@JvmField @JvmField
val SHARP_BEAK = heldItem("sharp_beak") val SHARP_BEAK = heldItem("sharp_beak")
@JvmField @JvmField
val SHARPEDONITE = heldItem("sharpedonite")
@JvmField
val SHED_SHELL = heldItem("shed_shell") val SHED_SHELL = heldItem("shed_shell")
@JvmField @JvmField
val SHELL_BELL = heldItem("shell_bell") val SHELL_BELL = heldItem("shell_bell")
@@ -1060,6 +1148,8 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
@JvmField @JvmField
val SILVER_POWDER = heldItem("silver_powder") val SILVER_POWDER = heldItem("silver_powder")
@JvmField @JvmField
val SLOWBRONITE = heldItem("slowbronite")
@JvmField
val SOFT_SAND = heldItem("soft_sand") val SOFT_SAND = heldItem("soft_sand")
@JvmField @JvmField
val SPELL_TAG = itemNameBlockItem("spell_tag", CobblemonBlocks.SPELL_TAG) val SPELL_TAG = itemNameBlockItem("spell_tag", CobblemonBlocks.SPELL_TAG)
@@ -1068,8 +1158,12 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
@JvmField @JvmField
val SOOTHE_BELL = heldItem("soothe_bell") val SOOTHE_BELL = heldItem("soothe_bell")
@JvmField @JvmField
val STEELIXITE = heldItem("steelixite")
@JvmField
val STICKY_BARB = heldItem("sticky_barb") val STICKY_BARB = heldItem("sticky_barb")
@JvmField @JvmField
val SWAMPERTITE = heldItem("swampertite")
@JvmField
val TERRAIN_EXTENDER = heldItem("terrain_extender") val TERRAIN_EXTENDER = heldItem("terrain_extender")
@JvmField @JvmField
val THROAT_SPRAY = heldItem("throat_spray") val THROAT_SPRAY = heldItem("throat_spray")
@@ -1078,10 +1172,14 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
@JvmField @JvmField
val TWISTED_SPOON = heldItem("twisted_spoon") val TWISTED_SPOON = heldItem("twisted_spoon")
@JvmField @JvmField
val TYRANITARITE = heldItem("tyranitarite")
@JvmField
val UTILITY_UMBRELLA = heldItem("utility_umbrella") val UTILITY_UMBRELLA = heldItem("utility_umbrella")
@JvmField @JvmField
val WEAKNESS_POLICY = itemNameBlockItem("weakness_policy", CobblemonBlocks.WEAKNESS_POLICY) val WEAKNESS_POLICY = itemNameBlockItem("weakness_policy", CobblemonBlocks.WEAKNESS_POLICY)
@JvmField @JvmField
val VENUSAURITE = heldItem("venusaurite")
@JvmField
val WIDE_LENS = heldItem("wide_lens") val WIDE_LENS = heldItem("wide_lens")
@JvmField @JvmField
val ZOOM_LENS = heldItem("zoom_lens") val ZOOM_LENS = heldItem("zoom_lens")
@@ -15,12 +15,12 @@ import com.cobblemon.mod.common.api.moves.animations.ActionEffectContext
import com.mojang.serialization.Codec import com.mojang.serialization.Codec
import com.mojang.serialization.codecs.ListCodec import com.mojang.serialization.codecs.ListCodec
import com.mojang.serialization.codecs.PrimitiveCodec import com.mojang.serialization.codecs.PrimitiveCodec
import java.util.Optional
import java.util.UUID
import net.minecraft.core.BlockPos import net.minecraft.core.BlockPos
import net.minecraft.core.GlobalPos
import net.minecraft.core.UUIDUtil import net.minecraft.core.UUIDUtil
import net.minecraft.world.entity.LivingEntity import net.minecraft.world.entity.LivingEntity
import net.minecraft.world.entity.ai.memory.MemoryModuleType import net.minecraft.world.entity.ai.memory.MemoryModuleType
import java.util.*
object CobblemonMemories { object CobblemonMemories {
val memories = mutableMapOf<String, MemoryModuleType<*>>() val memories = mutableMapOf<String, MemoryModuleType<*>>()
@@ -107,10 +107,14 @@ import com.cobblemon.mod.common.net.messages.client.pokemon.update.evolution.Add
import com.cobblemon.mod.common.net.messages.client.pokemon.update.evolution.ClearEvolutionsPacket import com.cobblemon.mod.common.net.messages.client.pokemon.update.evolution.ClearEvolutionsPacket
import com.cobblemon.mod.common.net.messages.client.pokemon.update.evolution.ClientboundSeatAssignmentPacket import com.cobblemon.mod.common.net.messages.client.pokemon.update.evolution.ClientboundSeatAssignmentPacket
import com.cobblemon.mod.common.net.messages.client.pokemon.update.evolution.RemoveEvolutionPacket import com.cobblemon.mod.common.net.messages.client.pokemon.update.evolution.RemoveEvolutionPacket
import com.cobblemon.mod.common.net.messages.client.pokemon.update.form.AddFormPacket
import com.cobblemon.mod.common.net.messages.client.pokemon.update.form.ClearFormsPacket
import com.cobblemon.mod.common.net.messages.client.pokemon.update.form.RemoveFormPacket
import com.cobblemon.mod.common.net.messages.client.settings.OpenCobblemonConfigScreenPacket import com.cobblemon.mod.common.net.messages.client.settings.OpenCobblemonConfigScreenPacket
import com.cobblemon.mod.common.net.messages.client.settings.ServerSettingsPacket import com.cobblemon.mod.common.net.messages.client.settings.ServerSettingsPacket
import com.cobblemon.mod.common.net.messages.client.sound.UnvalidatedPlaySoundS2CPacket import com.cobblemon.mod.common.net.messages.client.sound.UnvalidatedPlaySoundS2CPacket
import com.cobblemon.mod.common.net.messages.client.spawn.SpawnGenericBedrockPacket import com.cobblemon.mod.common.net.messages.client.spawn.SpawnGenericBedrockPacket
import com.cobblemon.mod.common.net.messages.client.spawn.SpawnFallingStarPacket
import com.cobblemon.mod.common.net.messages.client.spawn.SpawnNPCPacket import com.cobblemon.mod.common.net.messages.client.spawn.SpawnNPCPacket
import com.cobblemon.mod.common.net.messages.client.spawn.SpawnPokeballPacket import com.cobblemon.mod.common.net.messages.client.spawn.SpawnPokeballPacket
import com.cobblemon.mod.common.net.messages.client.spawn.SpawnPokemonPacket import com.cobblemon.mod.common.net.messages.client.spawn.SpawnPokemonPacket
@@ -194,6 +198,8 @@ import com.cobblemon.mod.common.net.messages.server.pokemon.update.SetItemHidden
import com.cobblemon.mod.common.net.messages.server.pokemon.update.SetMarkingsPacket import com.cobblemon.mod.common.net.messages.server.pokemon.update.SetMarkingsPacket
import com.cobblemon.mod.common.net.messages.server.pokemon.update.SetNicknamePacket import com.cobblemon.mod.common.net.messages.server.pokemon.update.SetNicknamePacket
import com.cobblemon.mod.common.net.messages.server.pokemon.update.evolution.AcceptEvolutionPacket import com.cobblemon.mod.common.net.messages.server.pokemon.update.evolution.AcceptEvolutionPacket
import com.cobblemon.mod.common.net.messages.server.pokemon.update.form.AcceptFormPacket
import com.cobblemon.mod.common.net.messages.server.pokemon.update.form.RevertFormPacket
import com.cobblemon.mod.common.net.messages.server.riding.DismountPokemonPacket import com.cobblemon.mod.common.net.messages.server.riding.DismountPokemonPacket
import com.cobblemon.mod.common.net.messages.server.riding.ServerboundUpdateDriverInputPacket import com.cobblemon.mod.common.net.messages.server.riding.ServerboundUpdateDriverInputPacket
import com.cobblemon.mod.common.net.messages.server.riding.ServerboundUpdatePassengerPositionPacket import com.cobblemon.mod.common.net.messages.server.riding.ServerboundUpdatePassengerPositionPacket
@@ -211,9 +217,11 @@ import com.cobblemon.mod.common.net.messages.server.trade.ChangeTradeAcceptanceP
import com.cobblemon.mod.common.net.messages.server.trade.OfferTradePacket import com.cobblemon.mod.common.net.messages.server.trade.OfferTradePacket
import com.cobblemon.mod.common.net.messages.server.trade.PerformTradePacket import com.cobblemon.mod.common.net.messages.server.trade.PerformTradePacket
import com.cobblemon.mod.common.net.messages.server.trade.UpdateTradeOfferPacket import com.cobblemon.mod.common.net.messages.server.trade.UpdateTradeOfferPacket
import com.cobblemon.mod.common.net.serverhandling.AcceptFormHandler
import com.cobblemon.mod.common.net.serverhandling.ChallengeHandler import com.cobblemon.mod.common.net.serverhandling.ChallengeHandler
import com.cobblemon.mod.common.net.serverhandling.ChallengeResponseHandler import com.cobblemon.mod.common.net.serverhandling.ChallengeResponseHandler
import com.cobblemon.mod.common.net.serverhandling.RequestInteractionsHandler import com.cobblemon.mod.common.net.serverhandling.RequestInteractionsHandler
import com.cobblemon.mod.common.net.serverhandling.RevertFormHandler
import com.cobblemon.mod.common.net.serverhandling.battle.BattleSelectActionsHandler import com.cobblemon.mod.common.net.serverhandling.battle.BattleSelectActionsHandler
import com.cobblemon.mod.common.net.serverhandling.battle.RemoveSpectatorHandler import com.cobblemon.mod.common.net.serverhandling.battle.RemoveSpectatorHandler
import com.cobblemon.mod.common.net.serverhandling.battle.SpectateBattleHandler import com.cobblemon.mod.common.net.serverhandling.battle.SpectateBattleHandler
@@ -457,6 +465,7 @@ object CobblemonNetwork {
list.add(PacketRegisterInfo(SpawnPokemonPacket.ID, SpawnPokemonPacket::decode, SpawnExtraDataEntityHandler())) list.add(PacketRegisterInfo(SpawnPokemonPacket.ID, SpawnPokemonPacket::decode, SpawnExtraDataEntityHandler()))
list.add(PacketRegisterInfo(SpawnPokeballPacket.ID, SpawnPokeballPacket::decode, SpawnExtraDataEntityHandler())) list.add(PacketRegisterInfo(SpawnPokeballPacket.ID, SpawnPokeballPacket::decode, SpawnExtraDataEntityHandler()))
list.add(PacketRegisterInfo(SpawnGenericBedrockPacket.ID, SpawnGenericBedrockPacket::decode, SpawnExtraDataEntityHandler())) list.add(PacketRegisterInfo(SpawnGenericBedrockPacket.ID, SpawnGenericBedrockPacket::decode, SpawnExtraDataEntityHandler()))
list.add(PacketRegisterInfo(SpawnFallingStarPacket.ID, SpawnFallingStarPacket::decode, SpawnExtraDataEntityHandler()))
list.add(PacketRegisterInfo(SpawnNPCPacket.ID, SpawnNPCPacket::decode, SpawnExtraDataEntityHandler())) list.add(PacketRegisterInfo(SpawnNPCPacket.ID, SpawnNPCPacket::decode, SpawnExtraDataEntityHandler()))
list.add(PacketRegisterInfo(ToastPacket.ID, ToastPacket::decode, ToastPacketHandler)) list.add(PacketRegisterInfo(ToastPacket.ID, ToastPacket::decode, ToastPacketHandler))
@@ -506,6 +515,11 @@ object CobblemonNetwork {
// Pokédex scanning // Pokédex scanning
list.add(PacketRegisterInfo(ServerConfirmedRegisterPacket.ID, ServerConfirmedRegisterPacket::decode, ServerConfirmedRegisterHandler)) list.add(PacketRegisterInfo(ServerConfirmedRegisterPacket.ID, ServerConfirmedRegisterPacket::decode, ServerConfirmedRegisterHandler))
// Form packets
list.add(PacketRegisterInfo(AddFormPacket.ID, AddFormPacket::decode, PokemonUpdatePacketHandler()))
list.add(PacketRegisterInfo(ClearFormsPacket.ID, ClearFormsPacket::decode, PokemonUpdatePacketHandler()))
list.add(PacketRegisterInfo(RemoveFormPacket.ID, RemoveFormPacket::decode, PokemonUpdatePacketHandler()))
// Riding // Riding
list.add(PacketRegisterInfo(ClientboundUpdateRidingStatePacket.ID, ClientboundUpdateRidingStatePacket::decode, ClientboundUpdateRidingStateHandler)) list.add(PacketRegisterInfo(ClientboundUpdateRidingStatePacket.ID, ClientboundUpdateRidingStatePacket::decode, ClientboundUpdateRidingStateHandler))
list.add(PacketRegisterInfo(ClientboundUpdateDriverInputPacket.ID, ClientboundUpdateDriverInputPacket::decode, ClientboundUpdateDriverInputHandler)) list.add(PacketRegisterInfo(ClientboundUpdateDriverInputPacket.ID, ClientboundUpdateDriverInputPacket::decode, ClientboundUpdateDriverInputHandler))
@@ -621,6 +635,10 @@ object CobblemonNetwork {
// NPC packets // NPC packets
list.add(PacketRegisterInfo(SaveNPCPacket.ID, SaveNPCPacket::decode, SaveNPCHandler)) list.add(PacketRegisterInfo(SaveNPCPacket.ID, SaveNPCPacket::decode, SaveNPCHandler))
// Form Packets
list.add(PacketRegisterInfo(AcceptFormPacket.ID, AcceptFormPacket::decode, AcceptFormHandler))
list.add(PacketRegisterInfo(RevertFormPacket.ID, RevertFormPacket::decode, RevertFormHandler))
// Riding packet(s) // Riding packet(s)
list.add(PacketRegisterInfo(ServerboundUpdateOrientationPacket.ID, ServerboundUpdateOrientationPacket::decode, ServerboundUpdateOrientationHandler)) list.add(PacketRegisterInfo(ServerboundUpdateOrientationPacket.ID, ServerboundUpdateOrientationPacket::decode, ServerboundUpdateOrientationHandler))
list.add(PacketRegisterInfo(ServerboundUpdateRidingStatePacket.ID, ServerboundUpdateRidingStatePacket::decode, ServerboundUpdateRidingStateHandler)) list.add(PacketRegisterInfo(ServerboundUpdateRidingStatePacket.ID, ServerboundUpdateRidingStatePacket::decode, ServerboundUpdateRidingStateHandler))
@@ -9,9 +9,9 @@
package com.cobblemon.mod.common package com.cobblemon.mod.common
import com.cobblemon.mod.common.entity.pokemon.ai.sensors.* import com.cobblemon.mod.common.entity.pokemon.ai.sensors.*
import com.cobblemon.mod.common.pokemon.ai.PokemonDisturbancesSensor
import com.cobblemon.mod.common.entity.sensor.BattlingPokemonSensor import com.cobblemon.mod.common.entity.sensor.BattlingPokemonSensor
import com.cobblemon.mod.common.entity.sensor.NPCBattlingSensor import com.cobblemon.mod.common.entity.sensor.NPCBattlingSensor
import com.cobblemon.mod.common.pokemon.ai.PokemonDisturbancesSensor
import java.util.function.Supplier import java.util.function.Supplier
import net.minecraft.world.entity.Entity import net.minecraft.world.entity.Entity
import net.minecraft.world.entity.ai.sensing.Sensor import net.minecraft.world.entity.ai.sensing.Sensor
@@ -8,6 +8,7 @@
package com.cobblemon.mod.common package com.cobblemon.mod.common
import java.util.Optional
import net.minecraft.core.registries.BuiltInRegistries import net.minecraft.core.registries.BuiltInRegistries
import net.minecraft.util.RandomSource import net.minecraft.util.RandomSource
import net.minecraft.world.entity.Entity import net.minecraft.world.entity.Entity
@@ -18,7 +19,6 @@ import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.Items import net.minecraft.world.item.Items
import net.minecraft.world.item.trading.ItemCost import net.minecraft.world.item.trading.ItemCost
import net.minecraft.world.item.trading.MerchantOffer import net.minecraft.world.item.trading.MerchantOffer
import java.util.Optional
/** /**
* A generator for various trade offers in the mod. * A generator for various trade offers in the mod.
@@ -11,10 +11,10 @@ package com.cobblemon.mod.common.advancement.criterion
import com.cobblemon.mod.common.util.cobblemonResource import com.cobblemon.mod.common.util.cobblemonResource
import com.mojang.serialization.Codec import com.mojang.serialization.Codec
import com.mojang.serialization.codecs.RecordCodecBuilder import com.mojang.serialization.codecs.RecordCodecBuilder
import java.util.Optional
import net.minecraft.advancements.critereon.ContextAwarePredicate import net.minecraft.advancements.critereon.ContextAwarePredicate
import net.minecraft.resources.ResourceLocation import net.minecraft.resources.ResourceLocation
import net.minecraft.server.level.ServerPlayer import net.minecraft.server.level.ServerPlayer
import java.util.Optional
class AspectCriterion( class AspectCriterion(
playerCtx: Optional<ContextAwarePredicate>, playerCtx: Optional<ContextAwarePredicate>,
@@ -14,8 +14,8 @@ import com.mojang.serialization.codecs.RecordCodecBuilder
import java.util.Optional import java.util.Optional
import net.minecraft.advancements.critereon.ContextAwarePredicate import net.minecraft.advancements.critereon.ContextAwarePredicate
import net.minecraft.advancements.critereon.EntityPredicate import net.minecraft.advancements.critereon.EntityPredicate
import net.minecraft.server.level.ServerPlayer
import net.minecraft.resources.ResourceLocation import net.minecraft.resources.ResourceLocation
import net.minecraft.server.level.ServerPlayer
class CastPokeRodContext(val baitId: ResourceLocation) class CastPokeRodContext(val baitId: ResourceLocation)
@@ -10,10 +10,10 @@ package com.cobblemon.mod.common.advancement.criterion
import com.mojang.serialization.Codec import com.mojang.serialization.Codec
import com.mojang.serialization.codecs.RecordCodecBuilder import com.mojang.serialization.codecs.RecordCodecBuilder
import java.util.Optional
import net.minecraft.advancements.critereon.ContextAwarePredicate import net.minecraft.advancements.critereon.ContextAwarePredicate
import net.minecraft.advancements.critereon.EntityPredicate import net.minecraft.advancements.critereon.EntityPredicate
import net.minecraft.server.level.ServerPlayer import net.minecraft.server.level.ServerPlayer
import java.util.Optional
/** /**
* A context that is used when you require a [CountableContext] along with some type string. * A context that is used when you require a [CountableContext] along with some type string.
@@ -14,8 +14,8 @@ import com.mojang.serialization.codecs.RecordCodecBuilder
import java.util.Optional import java.util.Optional
import net.minecraft.advancements.critereon.ContextAwarePredicate import net.minecraft.advancements.critereon.ContextAwarePredicate
import net.minecraft.advancements.critereon.EntityPredicate import net.minecraft.advancements.critereon.EntityPredicate
import net.minecraft.server.level.ServerPlayer
import net.minecraft.resources.ResourceLocation import net.minecraft.resources.ResourceLocation
import net.minecraft.server.level.ServerPlayer
class ReelInPokemonContext(val species : ResourceLocation, val baitId: ResourceLocation) class ReelInPokemonContext(val species : ResourceLocation, val baitId: ResourceLocation)
@@ -9,6 +9,7 @@
package com.cobblemon.mod.common.api.abilities package com.cobblemon.mod.common.api.abilities
import com.cobblemon.mod.common.api.Priority import com.cobblemon.mod.common.api.Priority
import com.cobblemon.mod.common.api.data.ShowdownIdentifiable
import com.cobblemon.mod.common.util.codec.CodecUtils import com.cobblemon.mod.common.util.codec.CodecUtils
import com.google.gson.JsonObject import com.google.gson.JsonObject
import com.mojang.serialization.Codec import com.mojang.serialization.Codec
@@ -25,7 +26,7 @@ class AbilityTemplate(
var builder: (AbilityTemplate, forced: Boolean, priority: Priority) -> Ability = { template, forced, priority -> Ability(template, forced, priority) }, var builder: (AbilityTemplate, forced: Boolean, priority: Priority) -> Ability = { template, forced, priority -> Ability(template, forced, priority) },
val displayName: String = "cobblemon.ability.$name", val displayName: String = "cobblemon.ability.$name",
val description: String = "cobblemon.ability.$name.desc" val description: String = "cobblemon.ability.$name.desc"
) { ) : ShowdownIdentifiable {
/** /**
* Returns the Ability or if applicable the extension connected to this template * Returns the Ability or if applicable the extension connected to this template
*/ */
@@ -45,6 +46,8 @@ class AbilityTemplate(
*/ */
fun create(json: JsonObject) = create().loadFromJSON(json) fun create(json: JsonObject) = create().loadFromJSON(json)
override fun showdownId(): String = ShowdownIdentifiable.REGEX.replace(this.name.lowercase(), "")
companion object { companion object {
@JvmStatic @JvmStatic
@@ -18,7 +18,6 @@ import com.cobblemon.mod.common.api.molang.MoLangFunctions.addStandardFunctions
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMostSpecificMoLangValue import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMostSpecificMoLangValue
import com.cobblemon.mod.common.api.molang.MoLangFunctions.setup import com.cobblemon.mod.common.api.molang.MoLangFunctions.setup
import com.cobblemon.mod.common.api.molang.ObjectValue import com.cobblemon.mod.common.api.molang.ObjectValue
import com.cobblemon.mod.common.api.scripting.CobblemonScripts
import com.cobblemon.mod.common.entity.MoLangScriptingEntity import com.cobblemon.mod.common.entity.MoLangScriptingEntity
import com.cobblemon.mod.common.util.activityRegistry import com.cobblemon.mod.common.util.activityRegistry
import com.cobblemon.mod.common.util.asIdentifierDefaultingNamespace import com.cobblemon.mod.common.util.asIdentifierDefaultingNamespace
@@ -13,7 +13,6 @@ import com.cobblemon.mod.common.api.ai.config.BehaviourConfig
import com.cobblemon.mod.common.api.molang.ExpressionLike import com.cobblemon.mod.common.api.molang.ExpressionLike
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMostSpecificMoLangValue import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMostSpecificMoLangValue
import com.cobblemon.mod.common.api.molang.MoLangFunctions.setup import com.cobblemon.mod.common.api.molang.MoLangFunctions.setup
import com.cobblemon.mod.common.api.scripting.CobblemonScripts
import com.cobblemon.mod.common.util.asTranslated import com.cobblemon.mod.common.util.asTranslated
import com.cobblemon.mod.common.util.resolve import com.cobblemon.mod.common.util.resolve
import com.cobblemon.mod.common.util.withQueryValue import com.cobblemon.mod.common.util.withQueryValue
@@ -13,7 +13,6 @@ import com.cobblemon.mod.common.util.getBooleanOrNull
import com.cobblemon.mod.common.util.getDoubleOrNull import com.cobblemon.mod.common.util.getDoubleOrNull
import kotlin.math.sqrt import kotlin.math.sqrt
import net.minecraft.core.BlockPos import net.minecraft.core.BlockPos
import net.minecraft.world.entity.PathfinderMob
/** /**
* Used to maintain some settings around how the entity should wander this tick. The idea is you * Used to maintain some settings around how the entity should wander this tick. The idea is you
@@ -8,16 +8,12 @@
package com.cobblemon.mod.common.api.ai.config package com.cobblemon.mod.common.api.ai.config
import com.bedrockk.molang.runtime.MoLangRuntime
import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
import com.cobblemon.mod.common.api.ai.ExpressionOrEntityVariable import com.cobblemon.mod.common.api.ai.ExpressionOrEntityVariable
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMostSpecificMoLangValue
import com.cobblemon.mod.common.api.molang.MoLangFunctions.setup
import com.cobblemon.mod.common.api.npc.configuration.MoLangConfigVariable import com.cobblemon.mod.common.api.npc.configuration.MoLangConfigVariable
import com.cobblemon.mod.common.util.asExpression import com.cobblemon.mod.common.util.asExpression
import com.cobblemon.mod.common.util.cobblemonResource import com.cobblemon.mod.common.util.cobblemonResource
import com.cobblemon.mod.common.util.resolveBoolean import com.cobblemon.mod.common.util.resolveBoolean
import com.cobblemon.mod.common.util.withQueryValue
import net.minecraft.resources.ResourceLocation import net.minecraft.resources.ResourceLocation
import net.minecraft.world.entity.LivingEntity import net.minecraft.world.entity.LivingEntity
@@ -11,13 +11,8 @@ package com.cobblemon.mod.common.api.ai.config.task
import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
import com.cobblemon.mod.common.api.ai.ExpressionOrEntityVariable import com.cobblemon.mod.common.api.ai.ExpressionOrEntityVariable
import com.cobblemon.mod.common.api.ai.asVariables import com.cobblemon.mod.common.api.ai.asVariables
import com.cobblemon.mod.common.api.molang.ExpressionLike
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMostSpecificMoLangValue
import com.cobblemon.mod.common.util.asExpression import com.cobblemon.mod.common.util.asExpression
import com.cobblemon.mod.common.util.asExpressionLike
import com.cobblemon.mod.common.util.resolveBoolean
import com.cobblemon.mod.common.util.weightedSelection import com.cobblemon.mod.common.util.weightedSelection
import com.cobblemon.mod.common.util.withQueryValue
import com.mojang.datafixers.util.Either import com.mojang.datafixers.util.Either
import net.minecraft.world.entity.LivingEntity import net.minecraft.world.entity.LivingEntity
import net.minecraft.world.entity.ai.behavior.BehaviorControl import net.minecraft.world.entity.ai.behavior.BehaviorControl
@@ -8,12 +8,10 @@
package com.cobblemon.mod.common.api.ai.config.task package com.cobblemon.mod.common.api.ai.config.task
import com.bedrockk.molang.runtime.MoLangRuntime
import com.cobblemon.mod.common.CobblemonMemories import com.cobblemon.mod.common.CobblemonMemories
import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
import com.cobblemon.mod.common.api.ai.WrapperLivingEntityTask.Companion.wrapped import com.cobblemon.mod.common.api.ai.WrapperLivingEntityTask.Companion.wrapped
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMostSpecificMoLangValue import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMostSpecificMoLangValue
import com.cobblemon.mod.common.api.molang.MoLangFunctions.setup
import com.cobblemon.mod.common.api.npc.configuration.MoLangConfigVariable import com.cobblemon.mod.common.api.npc.configuration.MoLangConfigVariable
import com.cobblemon.mod.common.util.mainThreadRuntime import com.cobblemon.mod.common.util.mainThreadRuntime
import com.cobblemon.mod.common.util.resolveBoolean import com.cobblemon.mod.common.util.resolveBoolean
@@ -10,8 +10,6 @@ package com.cobblemon.mod.common.api.ai.config.task
import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
import com.cobblemon.mod.common.api.ai.asVariables import com.cobblemon.mod.common.api.ai.asVariables
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMostSpecificMoLangValue
import com.cobblemon.mod.common.util.withQueryValue
import net.minecraft.world.entity.LivingEntity import net.minecraft.world.entity.LivingEntity
import net.minecraft.world.entity.ai.behavior.BehaviorControl import net.minecraft.world.entity.ai.behavior.BehaviorControl
import net.minecraft.world.entity.ai.behavior.StopBeingAngryIfTargetDead import net.minecraft.world.entity.ai.behavior.StopBeingAngryIfTargetDead
@@ -9,9 +9,7 @@
package com.cobblemon.mod.common.api.ai.config.task package com.cobblemon.mod.common.api.ai.config.task
import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMostSpecificMoLangValue
import com.cobblemon.mod.common.api.npc.configuration.MoLangConfigVariable import com.cobblemon.mod.common.api.npc.configuration.MoLangConfigVariable
import com.cobblemon.mod.common.util.withQueryValue
import net.minecraft.world.Difficulty import net.minecraft.world.Difficulty
import net.minecraft.world.entity.LivingEntity import net.minecraft.world.entity.LivingEntity
import net.minecraft.world.entity.ai.behavior.declarative.BehaviorBuilder import net.minecraft.world.entity.ai.behavior.declarative.BehaviorBuilder
@@ -15,7 +15,6 @@ import com.cobblemon.mod.common.api.npc.configuration.MoLangConfigVariable
import com.cobblemon.mod.common.entity.npc.ai.SwitchToBattleTask import com.cobblemon.mod.common.entity.npc.ai.SwitchToBattleTask
import net.minecraft.world.entity.LivingEntity import net.minecraft.world.entity.LivingEntity
import net.minecraft.world.entity.ai.behavior.BehaviorControl import net.minecraft.world.entity.ai.behavior.BehaviorControl
import net.minecraft.world.entity.ai.memory.MemoryModuleType
class SwitchToNPCBattleTaskConfig : SingleTaskConfig { class SwitchToNPCBattleTaskConfig : SingleTaskConfig {
override fun getVariables(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext) = emptyList<MoLangConfigVariable>() override fun getVariables(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext) = emptyList<MoLangConfigVariable>()
@@ -10,8 +10,6 @@ package com.cobblemon.mod.common.api.ai.config.task
import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
import com.cobblemon.mod.common.api.ai.asVariables import com.cobblemon.mod.common.api.ai.asVariables
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMostSpecificMoLangValue
import com.cobblemon.mod.common.util.withQueryValue
import net.minecraft.world.entity.LivingEntity import net.minecraft.world.entity.LivingEntity
import net.minecraft.world.entity.PathfinderMob import net.minecraft.world.entity.PathfinderMob
import net.minecraft.world.entity.ai.behavior.BehaviorControl import net.minecraft.world.entity.ai.behavior.BehaviorControl
@@ -10,8 +10,6 @@ package com.cobblemon.mod.common.api.ai.config.task
import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
import com.cobblemon.mod.common.api.ai.asVariables import com.cobblemon.mod.common.api.ai.asVariables
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMostSpecificMoLangValue
import com.cobblemon.mod.common.util.withQueryValue
import net.minecraft.world.entity.LivingEntity import net.minecraft.world.entity.LivingEntity
import net.minecraft.world.entity.PathfinderMob import net.minecraft.world.entity.PathfinderMob
import net.minecraft.world.entity.ai.behavior.BehaviorControl import net.minecraft.world.entity.ai.behavior.BehaviorControl
@@ -25,7 +25,6 @@ import net.minecraft.world.entity.ai.behavior.BehaviorControl
import net.minecraft.world.entity.ai.behavior.declarative.BehaviorBuilder import net.minecraft.world.entity.ai.behavior.declarative.BehaviorBuilder
import net.minecraft.world.entity.ai.behavior.declarative.Trigger import net.minecraft.world.entity.ai.behavior.declarative.Trigger
import net.minecraft.world.entity.ai.memory.MemoryModuleType import net.minecraft.world.entity.ai.memory.MemoryModuleType
import net.minecraft.world.entity.ai.memory.MemoryStatus
import net.minecraft.world.entity.ai.sensing.SensorType import net.minecraft.world.entity.ai.sensing.SensorType
/** /**
@@ -22,6 +22,7 @@ import com.cobblemon.mod.common.util.mainThreadRuntime
import com.cobblemon.mod.common.util.resolveFloat import com.cobblemon.mod.common.util.resolveFloat
import com.cobblemon.mod.common.util.withQueryValue import com.cobblemon.mod.common.util.withQueryValue
import com.mojang.datafixers.util.Either import com.mojang.datafixers.util.Either
import kotlin.math.ceil
import net.minecraft.core.BlockPos import net.minecraft.core.BlockPos
import net.minecraft.world.entity.LivingEntity import net.minecraft.world.entity.LivingEntity
import net.minecraft.world.entity.PathfinderMob import net.minecraft.world.entity.PathfinderMob
@@ -34,7 +35,6 @@ import net.minecraft.world.entity.ai.memory.MemoryModuleType
import net.minecraft.world.level.material.Fluids import net.minecraft.world.level.material.Fluids
import net.minecraft.world.level.pathfinder.PathType import net.minecraft.world.level.pathfinder.PathType
import net.minecraft.world.phys.Vec3 import net.minecraft.world.phys.Vec3
import kotlin.math.ceil
class WaterWanderTaskConfig : SingleTaskConfig { class WaterWanderTaskConfig : SingleTaskConfig {
val condition = booleanVariable(WANDER, "water_wanders", true).asExpressible() val condition = booleanVariable(WANDER, "water_wanders", true).asExpressible()
@@ -54,9 +54,9 @@ import com.cobblemon.mod.common.net.messages.client.battle.BattleEndPacket
import com.cobblemon.mod.common.net.messages.client.battle.BattleMakeChoicePacket import com.cobblemon.mod.common.net.messages.client.battle.BattleMakeChoicePacket
import com.cobblemon.mod.common.net.messages.client.battle.BattleMessagePacket import com.cobblemon.mod.common.net.messages.client.battle.BattleMessagePacket
import com.cobblemon.mod.common.net.messages.client.battle.BattleQueueRequestPacket import com.cobblemon.mod.common.net.messages.client.battle.BattleQueueRequestPacket
import com.cobblemon.mod.common.pokemon.evolution.progress.DefeatEvolutionProgress import com.cobblemon.mod.common.pokemon.transformation.progress.DefeatTransformationProgress
import com.cobblemon.mod.common.pokemon.evolution.progress.LastBattleCriticalHitsEvolutionProgress import com.cobblemon.mod.common.pokemon.transformation.progress.LastBattleCriticalHitsTransformationProgress
import com.cobblemon.mod.common.pokemon.requirements.DefeatRequirement import com.cobblemon.mod.common.pokemon.transformation.requirements.DefeatRequirement
import com.cobblemon.mod.common.util.battleLang import com.cobblemon.mod.common.util.battleLang
import com.cobblemon.mod.common.util.getPlayer import com.cobblemon.mod.common.util.getPlayer
import com.cobblemon.mod.common.util.giveOrDropItemStack import com.cobblemon.mod.common.util.giveOrDropItemStack
@@ -97,8 +97,8 @@ open class PokemonBattle(
this.actors.forEach { actor -> this.actors.forEach { actor ->
actor.battle = this actor.battle = this
actor.pokemonList.forEach { battlePokemon -> actor.pokemonList.forEach { battlePokemon ->
battlePokemon.effectedPokemon.evolutionProxy.current().progress() battlePokemon.effectedPokemon.requirementProgress
.filterIsInstance<LastBattleCriticalHitsEvolutionProgress>() .filterIsInstance<LastBattleCriticalHitsTransformationProgress>()
.forEach { it.reset() } .forEach { it.reset() }
} }
} }
@@ -271,12 +271,13 @@ open class PokemonBattle(
val facedFainted = opponentPokemon.facedOpponents.contains(faintedPokemon) val facedFainted = opponentPokemon.facedOpponents.contains(faintedPokemon)
val pokemon = opponentPokemon.effectedPokemon val pokemon = opponentPokemon.effectedPokemon
if (facedFainted) { if (facedFainted) {
pokemon.lockedEvolutions.forEach { evolution -> if (pokemon.hasMatchingRequirement<DefeatRequirement>({ it.target.matches(faintedPokemon.effectedPokemon) })) {
evolution.requirements.filterIsInstance<DefeatRequirement>().forEach { defeatRequirement -> val requiredPokemonProperties = pokemon.getRelevantRequirements<DefeatRequirement> { it.target.matches(faintedPokemon.effectedPokemon) }
if (defeatRequirement.target.matches(faintedPokemon.effectedPokemon)) { .map { it.target }
val progress = pokemon.evolutionProxy.current().progressFirstOrCreate({ it is DefeatEvolutionProgress && it.currentProgress().target == defeatRequirement.target }) { DefeatEvolutionProgress() } .distinctBy { it.asString() }
progress.updateProgress(DefeatEvolutionProgress.Progress(defeatRequirement.target, progress.currentProgress().amount + 1)) for (props in requiredPokemonProperties) {
} val progress = pokemon.progressFirstOrCreate({ it is DefeatTransformationProgress && it.currentProgress().target.asString().equals(props.asString(), ignoreCase = true) }, ::DefeatTransformationProgress)
progress.updateProgress(DefeatTransformationProgress.Progress(props.copy(), progress.currentProgress().amount + 1))
} }
} }
} }
@@ -22,9 +22,9 @@ import com.cobblemon.mod.common.item.battle.BagItem
import com.cobblemon.mod.common.net.messages.client.battle.BattleApplyPassResponsePacket import com.cobblemon.mod.common.net.messages.client.battle.BattleApplyPassResponsePacket
import com.cobblemon.mod.common.net.messages.client.battle.BattleMakeChoicePacket import com.cobblemon.mod.common.net.messages.client.battle.BattleMakeChoicePacket
import com.cobblemon.mod.common.net.messages.client.battle.BattleMessagePacket import com.cobblemon.mod.common.net.messages.client.battle.BattleMessagePacket
import java.util.UUID
import net.minecraft.network.chat.Component import net.minecraft.network.chat.Component
import net.minecraft.network.chat.MutableComponent import net.minecraft.network.chat.MutableComponent
import java.util.UUID
import net.minecraft.server.level.ServerPlayer import net.minecraft.server.level.ServerPlayer
abstract class BattleActor( abstract class BattleActor(
@@ -21,6 +21,7 @@ import com.cobblemon.mod.common.util.adapters.*
import com.cobblemon.mod.common.util.cobblemonResource import com.cobblemon.mod.common.util.cobblemonResource
import com.google.gson.GsonBuilder import com.google.gson.GsonBuilder
import com.google.gson.reflect.TypeToken import com.google.gson.reflect.TypeToken
import java.awt.Color
import net.minecraft.advancements.critereon.MinMaxBounds import net.minecraft.advancements.critereon.MinMaxBounds
import net.minecraft.core.registries.Registries import net.minecraft.core.registries.Registries
import net.minecraft.resources.ResourceLocation import net.minecraft.resources.ResourceLocation
@@ -30,7 +31,6 @@ import net.minecraft.tags.TagKey
import net.minecraft.world.level.biome.Biome import net.minecraft.world.level.biome.Biome
import net.minecraft.world.phys.AABB import net.minecraft.world.phys.AABB
import net.minecraft.world.phys.Vec3 import net.minecraft.world.phys.Vec3
import java.awt.Color
/** /**
* The data registry for [Berry]. * The data registry for [Berry].
@@ -26,10 +26,10 @@ import com.cobblemon.mod.common.util.writeBox
import com.cobblemon.mod.common.util.writeEnumConstant import com.cobblemon.mod.common.util.writeEnumConstant
import com.cobblemon.mod.common.util.writeIdentifier import com.cobblemon.mod.common.util.writeIdentifier
import com.google.gson.annotations.SerializedName import com.google.gson.annotations.SerializedName
import net.minecraft.core.BlockPos
import net.minecraft.network.RegistryFriendlyByteBuf
import java.awt.Color import java.awt.Color
import java.util.EnumSet import java.util.EnumSet
import net.minecraft.core.BlockPos
import net.minecraft.network.RegistryFriendlyByteBuf
import net.minecraft.resources.ResourceLocation import net.minecraft.resources.ResourceLocation
import net.minecraft.tags.TagKey import net.minecraft.tags.TagKey
import net.minecraft.world.entity.LivingEntity import net.minecraft.world.entity.LivingEntity
@@ -8,11 +8,11 @@
package com.cobblemon.mod.common.api.drop package com.cobblemon.mod.common.api.drop
import com.cobblemon.mod.common.api.pokemon.requirement.Requirement import com.cobblemon.mod.common.api.pokemon.transformation.requirement.TransformationRequirement
import com.cobblemon.mod.common.pokemon.Pokemon import com.cobblemon.mod.common.pokemon.Pokemon
class EvolutionItemDropEntry : ItemDropEntry() { class EvolutionItemDropEntry : ItemDropEntry() {
val requirements: MutableSet<Requirement> = mutableSetOf() val requirements: MutableSet<TransformationRequirement> = mutableSetOf()
override fun canDrop(pokemon: Pokemon?): Boolean = pokemon != null && requirements.all { it.check(pokemon) } override fun canDrop(pokemon: Pokemon?): Boolean = pokemon != null && requirements.all { it.check(pokemon) }
} }
@@ -48,6 +48,10 @@ import com.cobblemon.mod.common.api.events.pokemon.evolution.EvolutionAcceptedEv
import com.cobblemon.mod.common.api.events.pokemon.evolution.EvolutionCompleteEvent import com.cobblemon.mod.common.api.events.pokemon.evolution.EvolutionCompleteEvent
import com.cobblemon.mod.common.api.events.pokemon.evolution.EvolutionDisplayEvent import com.cobblemon.mod.common.api.events.pokemon.evolution.EvolutionDisplayEvent
import com.cobblemon.mod.common.api.events.pokemon.evolution.EvolutionTestedEvent import com.cobblemon.mod.common.api.events.pokemon.evolution.EvolutionTestedEvent
import com.cobblemon.mod.common.api.events.pokemon.form.FormAcceptedEvent
import com.cobblemon.mod.common.api.events.pokemon.form.FormCompleteEvent
import com.cobblemon.mod.common.api.events.pokemon.form.FormDisplayEvent
import com.cobblemon.mod.common.api.events.pokemon.form.FormTestedEvent
import com.cobblemon.mod.common.api.events.pokemon.healing.PokemonHealedEvent import com.cobblemon.mod.common.api.events.pokemon.healing.PokemonHealedEvent
import com.cobblemon.mod.common.api.events.pokemon.interaction.ExperienceCandyUseEvent import com.cobblemon.mod.common.api.events.pokemon.interaction.ExperienceCandyUseEvent
import com.cobblemon.mod.common.api.events.pokemon.interaction.PokemonInteractionGUICreationEvent import com.cobblemon.mod.common.api.events.pokemon.interaction.PokemonInteractionGUICreationEvent
@@ -103,6 +107,18 @@ object CobblemonEvents {
@JvmField @JvmField
val EVOLUTION_COMPLETE = EventObservable<EvolutionCompleteEvent>() val EVOLUTION_COMPLETE = EventObservable<EvolutionCompleteEvent>()
@JvmField
val FORM_ACCEPTED = CancelableObservable<FormAcceptedEvent>()
@JvmField
val FORM_DISPLAY = EventObservable<FormDisplayEvent>()
@JvmField
val FORM_TESTED = EventObservable<FormTestedEvent>()
@JvmField
val FORM_COMPLETE = EventObservable<FormCompleteEvent>()
@JvmField @JvmField
val POKEMON_NICKNAMED = CancelableObservable<PokemonNicknamedEvent>() val POKEMON_NICKNAMED = CancelableObservable<PokemonNicknamedEvent>()
@@ -15,9 +15,7 @@ import com.cobblemon.mod.common.api.battles.model.actor.ActorType
import com.cobblemon.mod.common.api.battles.model.actor.BattleActor import com.cobblemon.mod.common.api.battles.model.actor.BattleActor
import com.cobblemon.mod.common.api.battles.model.actor.EntityBackedBattleActor import com.cobblemon.mod.common.api.battles.model.actor.EntityBackedBattleActor
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMostSpecificMoLangValue import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMostSpecificMoLangValue
import com.cobblemon.mod.common.battles.actor.PlayerBattleActor
import com.cobblemon.mod.common.entity.MoLangScriptingEntity import com.cobblemon.mod.common.entity.MoLangScriptingEntity
import com.cobblemon.mod.common.entity.npc.NPCBattleActor
import com.cobblemon.mod.common.util.asArrayValue import com.cobblemon.mod.common.util.asArrayValue
import net.minecraft.world.entity.LivingEntity import net.minecraft.world.entity.LivingEntity
@@ -12,7 +12,6 @@ import com.bedrockk.molang.runtime.value.DoubleValue
import com.cobblemon.mod.common.api.events.Cancelable import com.cobblemon.mod.common.api.events.Cancelable
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMoLangValue import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMoLangValue
import com.cobblemon.mod.common.api.molang.MoLangFunctions.moLangFunctionMap import com.cobblemon.mod.common.api.molang.MoLangFunctions.moLangFunctionMap
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import com.cobblemon.mod.common.pokemon.Pokemon import com.cobblemon.mod.common.pokemon.Pokemon
import com.cobblemon.mod.common.trade.TradeParticipant import com.cobblemon.mod.common.trade.TradeParticipant
import com.cobblemon.mod.common.util.getPlayer import com.cobblemon.mod.common.util.getPlayer
@@ -12,8 +12,8 @@ import com.bedrockk.molang.runtime.value.MoValue
import com.cobblemon.mod.common.api.events.Cancelable import com.cobblemon.mod.common.api.events.Cancelable
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMoLangValue import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMoLangValue
import com.cobblemon.mod.common.api.molang.MoLangFunctions.moLangFunctionMap import com.cobblemon.mod.common.api.molang.MoLangFunctions.moLangFunctionMap
import com.cobblemon.mod.common.api.pokemon.evolution.Evolution
import com.cobblemon.mod.common.pokemon.Pokemon import com.cobblemon.mod.common.pokemon.Pokemon
import com.cobblemon.mod.common.pokemon.transformation.evolution.Evolution
/** /**
* Fired when an evolution is accepted. * Fired when an evolution is accepted.
@@ -10,8 +10,8 @@ package com.cobblemon.mod.common.api.events.pokemon.evolution
import com.bedrockk.molang.runtime.value.MoValue import com.bedrockk.molang.runtime.value.MoValue
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMoLangValue import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMoLangValue
import com.cobblemon.mod.common.api.pokemon.evolution.Evolution
import com.cobblemon.mod.common.pokemon.Pokemon import com.cobblemon.mod.common.pokemon.Pokemon
import com.cobblemon.mod.common.pokemon.transformation.evolution.Evolution
/** /**
* Fired after an evolution finishes. * Fired after an evolution finishes.
@@ -8,9 +8,9 @@
package com.cobblemon.mod.common.api.events.pokemon.evolution package com.cobblemon.mod.common.api.events.pokemon.evolution
import com.cobblemon.mod.common.api.pokemon.evolution.Evolution import com.cobblemon.mod.common.pokemon.transformation.evolution.Evolution
import com.cobblemon.mod.common.api.pokemon.evolution.EvolutionDisplay
import com.cobblemon.mod.common.pokemon.Pokemon import com.cobblemon.mod.common.pokemon.Pokemon
import com.cobblemon.mod.common.pokemon.transformation.evolution.EvolutionDisplay
/** /**
* Fired before an evolution is sent to clients. * Fired before an evolution is sent to clients.
@@ -8,7 +8,7 @@
package com.cobblemon.mod.common.api.events.pokemon.evolution package com.cobblemon.mod.common.api.events.pokemon.evolution
import com.cobblemon.mod.common.api.pokemon.evolution.Evolution import com.cobblemon.mod.common.pokemon.transformation.evolution.Evolution
import com.cobblemon.mod.common.pokemon.Pokemon import com.cobblemon.mod.common.pokemon.Pokemon
/** /**
@@ -12,8 +12,8 @@ import com.bedrockk.molang.runtime.value.DoubleValue
import com.bedrockk.molang.runtime.value.MoValue import com.bedrockk.molang.runtime.value.MoValue
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMoLangValue import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMoLangValue
import com.cobblemon.mod.common.api.molang.MoLangFunctions.moLangFunctionMap import com.cobblemon.mod.common.api.molang.MoLangFunctions.moLangFunctionMap
import com.cobblemon.mod.common.api.pokemon.evolution.Evolution
import com.cobblemon.mod.common.pokemon.Pokemon import com.cobblemon.mod.common.pokemon.Pokemon
import com.cobblemon.mod.common.pokemon.transformation.evolution.Evolution
import com.cobblemon.mod.common.util.getBoolean import com.cobblemon.mod.common.util.getBoolean
/** /**
@@ -0,0 +1,37 @@
/*
* 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.api.events.pokemon.form
import com.bedrockk.molang.runtime.value.StringValue
import com.cobblemon.mod.common.api.events.Cancelable
import com.cobblemon.mod.common.api.molang.MoLangFunctions.moLangFunctionMap
import com.cobblemon.mod.common.pokemon.Pokemon
import com.cobblemon.mod.common.pokemon.transformation.form.TemporaryForm
/**
* Fired when a temporary form change is accepted.
* Cancelling will not notify users nor remove the form from the pending list.
*
* @param pokemon The [Pokemon] about to change form.
* @param form The [TemporaryForm] being used.
*
* @author Hiroku
* @since June 3rd, 2026
*/
data class FormAcceptedEvent(
override val pokemon: Pokemon,
override val form: TemporaryForm
) : Cancelable(), FormEvent {
val context = mutableMapOf(
"pokemon" to pokemon.struct,
"form" to StringValue(form.formOnlyShowdownId())
)
val functions = moLangFunctionMap(cancelFunc)
}
@@ -0,0 +1,34 @@
/*
* 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.api.events.pokemon.form
import com.bedrockk.molang.runtime.value.StringValue
import com.cobblemon.mod.common.pokemon.Pokemon
import com.cobblemon.mod.common.pokemon.transformation.form.TemporaryForm
/**
* Fired after a temporary form change finishes.
*
* @param pokemon The [Pokemon] resulting from the form change.
* @param form The [TemporaryForm] that was used.
*
* @author Hiroku
* @since June 3rd, 2026
*/
data class FormCompleteEvent(
/** The [Pokemon] that did the form change. */
override val pokemon: Pokemon,
/** The [TemporaryForm] that was used. */
override val form: TemporaryForm
) : FormEvent {
val context = mutableMapOf(
"pokemon" to pokemon.struct,
"form" to StringValue(form.formOnlyShowdownId())
)
}
@@ -0,0 +1,37 @@
/*
* 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.api.events.pokemon.form
import com.bedrockk.molang.runtime.value.StringValue
import com.cobblemon.mod.common.pokemon.Pokemon
import com.cobblemon.mod.common.pokemon.transformation.form.FormDisplay
import com.cobblemon.mod.common.pokemon.transformation.form.TemporaryForm
/**
* Fired before a form is sent to clients. For modifications on the actual output when they accept it modify
* the [display] directly.
*
* @param pokemon The [Pokemon] that will change form if this proposition is accepted.
* @param display The current [FormDisplay] the client will see.
* @param form The [TemporaryForm] being used.
*
* @author Hiroku
* @since June 3rd, 2026
*/
data class FormDisplayEvent(
override val pokemon: Pokemon,
var display: FormDisplay,
override val form: TemporaryForm
) : FormEvent {
val context = mutableMapOf(
"pokemon" to pokemon.struct,
"display" to display.struct,
"form" to StringValue(form.formOnlyShowdownId())
)
}
@@ -0,0 +1,22 @@
/*
* 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.api.events.pokemon.form
import com.cobblemon.mod.common.pokemon.Pokemon
import com.cobblemon.mod.common.pokemon.transformation.form.TemporaryForm
/**
* The root of the various [TemporaryForm]-related events.
*/
interface FormEvent {
/** The Pokémon impacted in this event.*/
val pokemon: Pokemon
/*** The form triggering this event.*/
val form: TemporaryForm
}
@@ -0,0 +1,47 @@
/*
* 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.api.events.pokemon.form
import com.bedrockk.molang.runtime.value.DoubleValue
import com.bedrockk.molang.runtime.value.StringValue
import com.cobblemon.mod.common.api.molang.MoLangFunctions.moLangFunctionMap
import com.cobblemon.mod.common.pokemon.Pokemon
import com.cobblemon.mod.common.pokemon.transformation.form.TemporaryForm
import com.cobblemon.mod.common.util.getBoolean
/**
* An event fired when [TemporaryForm.test] has been performed.
* The final state [result] will be the return value of the test function.
*
* @property pokemon The [Pokemon] being tested against.
* @property form The [TemporaryForm] instance performing the test.
* @property originalResult The base result from the Cobblemon implementation.
* @property result The final value returned by [TemporaryForm.test].
*/
data class FormTestedEvent(
override val pokemon: Pokemon,
override val form: TemporaryForm,
val originalResult: Boolean,
) : FormEvent {
var result: Boolean = originalResult
val context = mutableMapOf(
"pokemon" to pokemon.struct,
"form" to StringValue(form.formOnlyShowdownId()),
"original_result" to DoubleValue(originalResult),
)
val functions = moLangFunctionMap(
"result" to { DoubleValue(result) },
"set_result" to {
result = it.getBoolean(0)
DoubleValue.ONE
}
)
}
@@ -15,7 +15,6 @@ import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMoLangValue
import com.cobblemon.mod.common.api.molang.MoLangFunctions.moLangFunctionMap import com.cobblemon.mod.common.api.molang.MoLangFunctions.moLangFunctionMap
import com.cobblemon.mod.common.api.pokemon.PokemonProperties import com.cobblemon.mod.common.api.pokemon.PokemonProperties
import com.cobblemon.mod.common.pokemon.Pokemon import com.cobblemon.mod.common.pokemon.Pokemon
import com.cobblemon.mod.common.util.getPlayer
import net.minecraft.server.level.ServerPlayer import net.minecraft.server.level.ServerPlayer
/** /**
@@ -8,7 +8,6 @@
package com.cobblemon.mod.common.api.events.storage package com.cobblemon.mod.common.api.events.storage
import com.bedrockk.molang.runtime.value.DoubleValue
import com.bedrockk.molang.runtime.value.StringValue import com.bedrockk.molang.runtime.value.StringValue
import com.cobblemon.mod.common.api.events.Cancelable import com.cobblemon.mod.common.api.events.Cancelable
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMoLangValue import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMoLangValue
@@ -16,9 +16,7 @@ import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMoLangValue
import com.cobblemon.mod.common.api.molang.MoLangFunctions.moLangFunctionMap import com.cobblemon.mod.common.api.molang.MoLangFunctions.moLangFunctionMap
import com.cobblemon.mod.common.api.storage.PokemonStore import com.cobblemon.mod.common.api.storage.PokemonStore
import com.cobblemon.mod.common.pokemon.Pokemon import com.cobblemon.mod.common.pokemon.Pokemon
import com.cobblemon.mod.common.util.getPlayer
import net.minecraft.server.level.ServerPlayer import net.minecraft.server.level.ServerPlayer
import java.util.UUID
/** /**
* The base of the events around the release of Pokémon from pc or party. * The base of the events around the release of Pokémon from pc or party.
@@ -14,7 +14,7 @@ import com.cobblemon.mod.common.api.data.JsonDataRegistry
import com.cobblemon.mod.common.api.pokemon.PokemonProperties import com.cobblemon.mod.common.api.pokemon.PokemonProperties
import com.cobblemon.mod.common.api.reactive.SimpleObservable import com.cobblemon.mod.common.api.reactive.SimpleObservable
import com.cobblemon.mod.common.net.messages.client.data.FossilRegistrySyncPacket import com.cobblemon.mod.common.net.messages.client.data.FossilRegistrySyncPacket
import com.cobblemon.mod.common.pokemon.evolution.adapters.LegacyItemConditionWrapperAdapter import com.cobblemon.mod.common.pokemon.transformation.adapters.LegacyItemConditionWrapperAdapter
import com.cobblemon.mod.common.util.adapters.IdentifierAdapter import com.cobblemon.mod.common.util.adapters.IdentifierAdapter
import com.cobblemon.mod.common.util.adapters.ItemLikeConditionAdapter import com.cobblemon.mod.common.util.adapters.ItemLikeConditionAdapter
import com.cobblemon.mod.common.util.adapters.pokemonPropertiesShortAdapter import com.cobblemon.mod.common.util.adapters.pokemonPropertiesShortAdapter
@@ -13,13 +13,13 @@ import com.cobblemon.mod.common.api.conditional.RegistryLikeCondition
import com.cobblemon.mod.common.api.data.JsonDataRegistry import com.cobblemon.mod.common.api.data.JsonDataRegistry
import com.cobblemon.mod.common.api.molang.ExpressionLike import com.cobblemon.mod.common.api.molang.ExpressionLike
import com.cobblemon.mod.common.api.pokemon.PokemonProperties import com.cobblemon.mod.common.api.pokemon.PokemonProperties
import com.cobblemon.mod.common.api.pokemon.requirement.Requirement import com.cobblemon.mod.common.api.pokemon.transformation.requirement.TransformationRequirement
import com.cobblemon.mod.common.api.reactive.SimpleObservable import com.cobblemon.mod.common.api.reactive.SimpleObservable
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import com.cobblemon.mod.common.net.messages.client.data.PokemonInteractionsSyncPacket import com.cobblemon.mod.common.net.messages.client.data.PokemonInteractionsSyncPacket
import com.cobblemon.mod.common.pokemon.adapters.CobblemonRequirementAdapter import com.cobblemon.mod.common.pokemon.transformation.adapters.CobblemonRequirementAdapter
import com.cobblemon.mod.common.pokemon.evolution.adapters.LegacyItemConditionWrapperAdapter import com.cobblemon.mod.common.pokemon.transformation.adapters.LegacyItemConditionWrapperAdapter
import com.cobblemon.mod.common.pokemon.requirements.PokemonPropertiesRequirement import com.cobblemon.mod.common.pokemon.transformation.requirements.PokemonPropertiesRequirement
import com.cobblemon.mod.common.util.adapters.* import com.cobblemon.mod.common.util.adapters.*
import com.cobblemon.mod.common.util.cobblemonResource import com.cobblemon.mod.common.util.cobblemonResource
import com.google.gson.Gson import com.google.gson.Gson
@@ -46,7 +46,7 @@ object PokemonInteractions : JsonDataRegistry<PokemonInteractionSet> {
.registerTypeAdapter(ResourceLocation::class.java, IdentifierAdapter) .registerTypeAdapter(ResourceLocation::class.java, IdentifierAdapter)
.registerTypeAdapter(PokemonProperties::class.java, pokemonPropertiesShortAdapter) .registerTypeAdapter(PokemonProperties::class.java, pokemonPropertiesShortAdapter)
.registerTypeAdapter(ItemPredicate::class.java, LegacyItemConditionWrapperAdapter) .registerTypeAdapter(ItemPredicate::class.java, LegacyItemConditionWrapperAdapter)
.registerTypeAdapter(Requirement::class.java, CobblemonRequirementAdapter) .registerTypeAdapter(TransformationRequirement::class.java, CobblemonRequirementAdapter)
.registerTypeAdapter(InteractionEffect::class.java, InteractionEffectAdapter) .registerTypeAdapter(InteractionEffect::class.java, InteractionEffectAdapter)
.registerTypeAdapter(ExpressionLike::class.java, ExpressionLikeAdapter) .registerTypeAdapter(ExpressionLike::class.java, ExpressionLikeAdapter)
.registerTypeAdapter(TypeToken.getParameterized(RegistryLikeCondition::class.java, Biome::class.java).type, BiomeLikeConditionAdapter) .registerTypeAdapter(TypeToken.getParameterized(RegistryLikeCondition::class.java, Biome::class.java).type, BiomeLikeConditionAdapter)
@@ -12,11 +12,16 @@ import com.bedrockk.molang.runtime.MoLangRuntime
import com.cobblemon.mod.common.api.molang.ExpressionLike import com.cobblemon.mod.common.api.molang.ExpressionLike
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMoLangValue import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMoLangValue
import com.cobblemon.mod.common.api.molang.MoLangFunctions.setup import com.cobblemon.mod.common.api.molang.MoLangFunctions.setup
import com.cobblemon.mod.common.api.pokemon.requirement.Requirement import com.cobblemon.mod.common.api.pokemon.transformation.requirement.TransformationRequirement
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import com.cobblemon.mod.common.net.messages.client.sound.UnvalidatedPlaySoundS2CPacket import com.cobblemon.mod.common.net.messages.client.sound.UnvalidatedPlaySoundS2CPacket
import com.cobblemon.mod.common.pokemon.adapters.CobblemonRequirementAdapter import com.cobblemon.mod.common.pokemon.transformation.adapters.CobblemonRequirementAdapter
import com.cobblemon.mod.common.util.* import com.cobblemon.mod.common.util.asExpressionLike
import com.cobblemon.mod.common.util.giveOrDropItemStack
import com.cobblemon.mod.common.util.readExpressionLike
import com.cobblemon.mod.common.util.withPlayerValue
import com.cobblemon.mod.common.util.withQueryValue
import com.cobblemon.mod.common.util.writeExpressionLike
import com.google.gson.annotations.SerializedName import com.google.gson.annotations.SerializedName
import net.minecraft.core.registries.Registries import net.minecraft.core.registries.Registries
import net.minecraft.network.FriendlyByteBuf import net.minecraft.network.FriendlyByteBuf
@@ -29,7 +34,7 @@ import net.minecraft.world.entity.item.ItemEntity
import net.minecraft.world.item.ItemStack import net.minecraft.world.item.ItemStack
data class PokemonInteractionSet( data class PokemonInteractionSet(
val requirements: List<Requirement> = listOf(), val requirements: List<TransformationRequirement> = listOf(),
val interactions: List<PokemonInteraction> = listOf(), val interactions: List<PokemonInteraction> = listOf(),
) { ) {
fun encode(buffer: FriendlyByteBuf) { fun encode(buffer: FriendlyByteBuf) {
@@ -51,7 +56,7 @@ data class PokemonInteractionSet(
} }
data class PokemonInteraction( data class PokemonInteraction(
val requirements: List<Requirement> = listOf(), val requirements: List<TransformationRequirement> = listOf(),
val effects: List<InteractionEffect> = listOf(), val effects: List<InteractionEffect> = listOf(),
val cooldown: ExpressionLike = "0".asExpressionLike() val cooldown: ExpressionLike = "0".asExpressionLike()
) { ) {
@@ -74,7 +74,7 @@ abstract class RequestManager<T : ServerPlayerActionRequest> {
?: this.getInboundRequest(receiver.uuid, requestID) ?: this.getInboundRequest(receiver.uuid, requestID)
/** Determines whether [player] can receive a [T]. */ /** Determines whether [player] can receive a [T]. */
open fun isBusy(player: ServerPlayer): Boolean = player.isInBattle() || player.isTrading() || player.party().find { it.entity?.isBusy == true } != null open fun isBusy(player: ServerPlayer): Boolean = player.isBusy() || player.isPartyBusy()
/** Determines if the [target] is a valid interaction request target. */ /** Determines if the [target] is a valid interaction request target. */
abstract fun isValidInteraction(player: ServerPlayer, target: ServerPlayer): Boolean abstract fun isValidInteraction(player: ServerPlayer, target: ServerPlayer): Boolean
@@ -9,6 +9,7 @@
package com.cobblemon.mod.common.api.item package com.cobblemon.mod.common.api.item
import com.cobblemon.mod.common.api.data.DataRegistry import com.cobblemon.mod.common.api.data.DataRegistry
import com.cobblemon.mod.common.api.data.ShowdownIdentifiable
import com.cobblemon.mod.common.api.reactive.SimpleObservable import com.cobblemon.mod.common.api.reactive.SimpleObservable
import com.cobblemon.mod.common.battles.runner.ShowdownService import com.cobblemon.mod.common.battles.runner.ShowdownService
import com.cobblemon.mod.common.pokemon.helditem.CobblemonHeldItemManager import com.cobblemon.mod.common.pokemon.helditem.CobblemonHeldItemManager
@@ -29,9 +30,11 @@ object HeldItems : DataRegistry {
// val heldItems = PrioritizedList<BagItemLike>() // val heldItems = PrioritizedList<BagItemLike>()
internal val heldItemsScripts = mutableMapOf<String, String>() // showdown item ID to JavaScript internal val heldItemsScripts = mutableMapOf<String, String>() // showdown item ID to JavaScript
val showdownItems = hashSetOf<String>() val showdownItems = hashSetOf<String>()
val megaStones = hashMapOf<String, String>()
override fun reload(manager: ResourceManager) { override fun reload(manager: ResourceManager) {
heldItemsScripts.clear() heldItemsScripts.clear()
megaStones.clear()
ShowdownService.service.resetRegistryData("heldItem") ShowdownService.service.resetRegistryData("heldItem")
manager.listResources("held_items") { it.path.endsWith(".js") }.forEach { (identifier, resource) -> manager.listResources("held_items") { it.path.endsWith(".js") }.forEach { (identifier, resource) ->
resource.open().use { stream -> resource.open().use { stream ->
@@ -48,6 +51,9 @@ object HeldItems : DataRegistry {
for (i in 0 until itemsJson.size()) { for (i in 0 until itemsJson.size()) {
val jsItem = itemsJson[i].asJsonObject val jsItem = itemsJson[i].asJsonObject
showdownItems += jsItem.get("id").asString showdownItems += jsItem.get("id").asString
if (jsItem.has("megaEvolves")) {
megaStones[jsItem.get("id").asString] = ShowdownIdentifiable.REGEX.replace(jsItem.get("megaEvolves").asString.lowercase(), "")
}
} }
CobblemonHeldItemManager.load() CobblemonHeldItemManager.load()
@@ -21,34 +21,9 @@ import com.cobblemon.mod.common.api.battles.interpreter.BattleMessage
import com.cobblemon.mod.common.api.battles.model.PokemonBattle import com.cobblemon.mod.common.api.battles.model.PokemonBattle
import com.cobblemon.mod.common.api.battles.model.actor.BattleActor import com.cobblemon.mod.common.api.battles.model.actor.BattleActor
import com.cobblemon.mod.common.api.drop.DropEntry import com.cobblemon.mod.common.api.drop.DropEntry
import com.cobblemon.mod.common.api.molang.function.BattleActorMoLangFunctions import com.cobblemon.mod.common.api.molang.function.*
import com.cobblemon.mod.common.api.molang.function.BattleMessageMoLangFunctions
import com.cobblemon.mod.common.api.molang.function.BattleMoLangFunctions
import com.cobblemon.mod.common.api.molang.function.BiomeMoLangFunctions
import com.cobblemon.mod.common.api.molang.function.BlockMoLangFunctions
import com.cobblemon.mod.common.api.molang.function.DimensionTypeMoLangFunctions
import com.cobblemon.mod.common.api.molang.function.DropEntryMoLangFunctions
import com.cobblemon.mod.common.api.molang.function.EntityMoLangFunctions
import com.cobblemon.mod.common.api.molang.function.EvolutionMoLangFunctions
import com.cobblemon.mod.common.api.molang.function.GeneralMoLangFunctions
import com.cobblemon.mod.common.api.molang.function.ItemStackMoLangFunctions
import com.cobblemon.mod.common.api.molang.function.LivingEntityMoLangFunctions
import com.cobblemon.mod.common.api.molang.function.NPCMoLangFunctions
import com.cobblemon.mod.common.api.molang.function.PCMoLangFunctions
import com.cobblemon.mod.common.api.molang.function.PartyMoLangFunctions
import com.cobblemon.mod.common.api.molang.function.PlayerMoLangFunctions
import com.cobblemon.mod.common.api.molang.function.PokedexMoLangFunctions
import com.cobblemon.mod.common.api.molang.function.PokemonEntityMoLangFunctions
import com.cobblemon.mod.common.api.molang.function.PokemonMoLangFunctions
import com.cobblemon.mod.common.api.molang.function.PokemonPropertiesMoLangFunctions
import com.cobblemon.mod.common.api.molang.function.PokemonStoreMoLangFunctions
import com.cobblemon.mod.common.api.molang.function.ServerMoLangFunctions
import com.cobblemon.mod.common.api.molang.function.SpawnablePositionMoLangFunctions
import com.cobblemon.mod.common.api.molang.function.SpeciesMoLangFunctions
import com.cobblemon.mod.common.api.molang.function.WorldMoLangFunctions
import com.cobblemon.mod.common.api.pokedex.AbstractPokedexManager import com.cobblemon.mod.common.api.pokedex.AbstractPokedexManager
import com.cobblemon.mod.common.api.pokemon.PokemonProperties import com.cobblemon.mod.common.api.pokemon.PokemonProperties
import com.cobblemon.mod.common.api.pokemon.evolution.Evolution
import com.cobblemon.mod.common.api.scripting.CobblemonScripts import com.cobblemon.mod.common.api.scripting.CobblemonScripts
import com.cobblemon.mod.common.api.spawning.position.SpawnablePosition import com.cobblemon.mod.common.api.spawning.position.SpawnablePosition
import com.cobblemon.mod.common.api.storage.PokemonStore import com.cobblemon.mod.common.api.storage.PokemonStore
@@ -58,8 +33,10 @@ import com.cobblemon.mod.common.entity.npc.NPCEntity
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import com.cobblemon.mod.common.pokemon.Pokemon import com.cobblemon.mod.common.pokemon.Pokemon
import com.cobblemon.mod.common.pokemon.Species import com.cobblemon.mod.common.pokemon.Species
import com.cobblemon.mod.common.pokemon.transformation.evolution.Evolution
import com.cobblemon.mod.common.util.effectiveName import com.cobblemon.mod.common.util.effectiveName
import com.mojang.datafixers.util.Either import com.mojang.datafixers.util.Either
import java.util.function.Function
import net.minecraft.core.Holder import net.minecraft.core.Holder
import net.minecraft.core.Registry import net.minecraft.core.Registry
import net.minecraft.core.RegistryAccess import net.minecraft.core.RegistryAccess
@@ -84,7 +61,6 @@ import net.minecraft.world.level.biome.Biome
import net.minecraft.world.level.block.Block import net.minecraft.world.level.block.Block
import net.minecraft.world.level.dimension.DimensionType import net.minecraft.world.level.dimension.DimensionType
import net.minecraft.world.phys.Vec3 import net.minecraft.world.phys.Vec3
import java.util.function.Function
/** /**
* Holds a bunch of useful MoLang trickery that can be used or extended in API * Holds a bunch of useful MoLang trickery that can be used or extended in API
@@ -13,7 +13,7 @@ import com.bedrockk.molang.runtime.value.DoubleValue
import com.bedrockk.molang.runtime.value.StringValue import com.bedrockk.molang.runtime.value.StringValue
import com.cobblemon.mod.common.api.battles.model.PokemonBattle import com.cobblemon.mod.common.api.battles.model.PokemonBattle
import com.cobblemon.mod.common.util.asArrayValue import com.cobblemon.mod.common.util.asArrayValue
import java.util.* import java.util.UUID
object BattleMoLangFunctions : AbstractMoLangFunctionHolder<PokemonBattle>() { object BattleMoLangFunctions : AbstractMoLangFunctionHolder<PokemonBattle>() {
override fun PokemonBattle.moLangFunctions(): MutableMap<String, (MoParams) -> Any> { override fun PokemonBattle.moLangFunctions(): MutableMap<String, (MoParams) -> Any> {
@@ -11,31 +11,34 @@ package com.cobblemon.mod.common.api.molang.function
import com.bedrockk.molang.runtime.MoParams import com.bedrockk.molang.runtime.MoParams
import com.bedrockk.molang.runtime.value.DoubleValue import com.bedrockk.molang.runtime.value.DoubleValue
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMoLangValue import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMoLangValue
import com.cobblemon.mod.common.api.pokemon.evolution.Evolution import com.cobblemon.mod.common.api.pokemon.transformation.Transformation
import com.cobblemon.mod.common.pokemon.evolution.variants.ItemInteractionEvolution import com.cobblemon.mod.common.pokemon.transformation.evolution.Evolution
import com.cobblemon.mod.common.pokemon.evolution.variants.LevelUpEvolution import com.cobblemon.mod.common.pokemon.transformation.triggers.ItemInteractionTrigger
import com.cobblemon.mod.common.pokemon.evolution.variants.TradeEvolution import com.cobblemon.mod.common.pokemon.transformation.triggers.LevelUpTrigger
import com.cobblemon.mod.common.pokemon.transformation.triggers.TradeTrigger
object EvolutionMoLangFunctions : AbstractMoLangFunctionHolder<Evolution>() { object EvolutionMoLangFunctions : AbstractMoLangFunctionHolder<Transformation>() {
override fun Evolution.moLangFunctions(): MutableMap<String, (MoParams) -> Any> { override fun Transformation.moLangFunctions(): MutableMap<String, (MoParams) -> Any> {
val evolution = this val evolution = this
val functions = hashMapOf<String, (MoParams) -> Any>() val functions = hashMapOf<String, (MoParams) -> Any>()
functions["result"] = { evolution.result.asMoLangValue() } functions["reevaluate"] = { DoubleValue(evolution.reevaluate) }
functions["is_optional"] = { DoubleValue(evolution.optional) } functions["is_optional"] = { DoubleValue(evolution.optional) }
functions["consumes_held_item"] = { DoubleValue(evolution.consumeHeldItem) }
when (evolution) { if (evolution is Evolution) {
is LevelUpEvolution -> { functions["result"] = { evolution.result.asMoLangValue() }
functions["is_level_up"] = { DoubleValue.ONE } when (evolution.trigger) {
} is LevelUpTrigger -> {
functions["is_level_up"] = { DoubleValue.ONE }
}
is TradeEvolution -> { is TradeTrigger -> {
functions["is_trade"] = { DoubleValue.ONE } functions["is_trade"] = { DoubleValue.ONE }
} }
is ItemInteractionEvolution -> { is ItemInteractionTrigger -> {
functions["is_item"] = { DoubleValue.ONE } functions["is_item"] = { DoubleValue.ONE }
}
} }
} }
@@ -445,7 +445,7 @@ object PokemonMoLangFunctions : AbstractMoLangFunctionHolder<Pokemon>() {
val idx = params.getInt(0) val idx = params.getInt(0)
val evolution = val evolution =
if (idx >= 0) pokemon.evolutions.elementAtOrNull(idx) else return@forceEvolve DoubleValue.ZERO if (idx >= 0) pokemon.evolutions.elementAtOrNull(idx) else return@forceEvolve DoubleValue.ZERO
evolution?.forceEvolve(pokemon) evolution?.perform(pokemon)
StringValue(evolution.toString()) StringValue(evolution.toString())
} }
@@ -12,6 +12,8 @@ import com.bedrockk.molang.runtime.struct.MoStruct
import com.bedrockk.molang.runtime.struct.QueryStruct import com.bedrockk.molang.runtime.struct.QueryStruct
import com.bedrockk.molang.runtime.value.DoubleValue import com.bedrockk.molang.runtime.value.DoubleValue
import com.bedrockk.molang.runtime.value.StringValue import com.bedrockk.molang.runtime.value.StringValue
import com.cobblemon.mod.common.api.data.ShowdownIdentifiable
import com.cobblemon.mod.common.api.moves.animations.ActionEffectTimeline
import com.cobblemon.mod.common.api.moves.categories.DamageCategories import com.cobblemon.mod.common.api.moves.categories.DamageCategories
import com.cobblemon.mod.common.api.moves.categories.DamageCategory import com.cobblemon.mod.common.api.moves.categories.DamageCategory
import com.cobblemon.mod.common.api.types.ElementalType import com.cobblemon.mod.common.api.types.ElementalType
@@ -55,7 +57,7 @@ open class MoveTemplate(
val critRatio: Double, val critRatio: Double,
val effectChances: Array<Double>, val effectChances: Array<Double>,
val weight: Float val weight: Float
) { ) : ShowdownIdentifiable {
val struct: MoStruct by lazy { val struct: MoStruct by lazy {
QueryStruct(hashMapOf()) QueryStruct(hashMapOf())
.addFunction("name") { StringValue(name) } .addFunction("name") { StringValue(name) }
@@ -163,6 +165,8 @@ open class MoveTemplate(
return this.elementalType return this.elementalType
} }
override fun showdownId() = ShowdownIdentifiable.REGEX.replace(this.name.lowercase(), "")
fun getSelectionWeight(form: FormData): Float { fun getSelectionWeight(form: FormData): Float {
return if (this in form.signatureMoves) { return if (this in form.signatureMoves) {
weight * MovesetBuilder.signatureMoveWeightMultiplier weight * MovesetBuilder.signatureMoveWeightMultiplier
@@ -10,13 +10,17 @@ package com.cobblemon.mod.common.api.moves.animations
import com.bedrockk.molang.runtime.MoLangRuntime import com.bedrockk.molang.runtime.MoLangRuntime
import com.cobblemon.mod.common.api.molang.ExpressionLike import com.cobblemon.mod.common.api.molang.ExpressionLike
import com.cobblemon.mod.common.api.molang.MoLangFunctions.addStandardFunctions
import com.cobblemon.mod.common.api.moves.animations.keyframes.ActionEffectKeyframe import com.cobblemon.mod.common.api.moves.animations.keyframes.ActionEffectKeyframe
import com.cobblemon.mod.common.api.scheduling.Schedulable
import com.cobblemon.mod.common.api.scheduling.ServerTaskTracker
import com.cobblemon.mod.common.entity.npc.NPCEntity import com.cobblemon.mod.common.entity.npc.NPCEntity
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import com.cobblemon.mod.common.util.asExpressionLike import com.cobblemon.mod.common.util.asExpressionLike
import com.cobblemon.mod.common.util.resolveBoolean import com.cobblemon.mod.common.util.resolveBoolean
import java.util.concurrent.CompletableFuture
import net.minecraft.world.entity.Entity import net.minecraft.world.entity.Entity
import net.minecraft.world.level.Level import net.minecraft.world.level.Level
import java.util.concurrent.CompletableFuture
/** /**
* An action effect will run and execute a series of 'keyframes', with each running once * An action effect will run and execute a series of 'keyframes', with each running once
@@ -36,7 +40,7 @@ class ActionEffectTimeline(
} }
fun run(context: ActionEffectContext): CompletableFuture<Unit> { fun run(context: ActionEffectContext): CompletableFuture<Unit> {
return if (timeline.isEmpty() || !context.runtime.resolveBoolean(condition)) { val future = if (timeline.isEmpty() || !context.runtime.resolveBoolean(condition)) {
CompletableFuture.completedFuture(Unit) CompletableFuture.completedFuture(Unit)
} else { } else {
val finalFuture = CompletableFuture<Unit>() val finalFuture = CompletableFuture<Unit>()
@@ -47,6 +51,10 @@ class ActionEffectTimeline(
it.printStackTrace() it.printStackTrace()
CompletableFuture.completedFuture(Unit) CompletableFuture.completedFuture(Unit)
} }
context.future = future
future.thenRun { context.getHolds().forEach(context::removeHold) }
return future
} }
fun chainKeyframes(context: ActionEffectContext, iterator: Iterator<ActionEffectKeyframe>, finalFuture: CompletableFuture<Unit>) { fun chainKeyframes(context: ActionEffectContext, iterator: Iterator<ActionEffectKeyframe>, finalFuture: CompletableFuture<Unit>) {
@@ -65,15 +73,45 @@ class ActionEffectTimeline(
class ActionEffectContext( class ActionEffectContext(
val actionEffect: ActionEffectTimeline, val actionEffect: ActionEffectTimeline,
val holds: MutableSet<String> = mutableSetOf(), private val holds: MutableSet<String> = mutableSetOf(),
val providers: MutableList<Any> = mutableListOf(), val providers: MutableList<Any> = mutableListOf(),
val runtime: MoLangRuntime, val runtime: MoLangRuntime,
var canBeInterrupted: Boolean = false, var canBeInterrupted: Boolean = false,
var interrupted: Boolean = false, var interrupted: Boolean = false,
var currentKeyframes: MutableList<ActionEffectKeyframe> = mutableListOf(), var currentKeyframes: MutableList<ActionEffectKeyframe> = mutableListOf(),
var level: Level? = null var level: Level? = null,
var holdRemovalCallbacks: MutableMap<String, () -> Unit> = mutableMapOf(),
var tracker: Schedulable = ServerTaskTracker
) { ) {
companion object {
fun fromPokemonEntity(
actionEffect: ActionEffectTimeline,
pokemonEntity: PokemonEntity,
runtime: MoLangRuntime = MoLangRuntime().also { it.environment.query.addStandardFunctions() },
holds: Collection<String> = emptySet(),
holdRemovalCallbacks: Map<String, () -> Unit> = emptyMap()
): ActionEffectContext {
return ActionEffectContext(
actionEffect = actionEffect,
providers = mutableListOf(UsersProvider(listOf(pokemonEntity))),
holdRemovalCallbacks = holdRemovalCallbacks.toMutableMap(),
holds = holds.toMutableSet(),
runtime = runtime,
level = pokemonEntity.level()
)
}
}
lateinit var future: CompletableFuture<Unit>
inline fun <reified T> findOneProvider() = providers.filterIsInstance<T>().firstOrNull() inline fun <reified T> findOneProvider() = providers.filterIsInstance<T>().firstOrNull()
/** Returns a reference to the internal holds set so you can keep an eye on it. */
fun getHolds(): Set<String> = holds
fun addHold(hold: String) = holds.add(hold)
fun removeHold(hold: String) {
holds.remove(hold)
holdRemovalCallbacks.remove(hold)?.invoke()
}
} }
class UsersProvider(users: List<Entity>): EntityProvider { class UsersProvider(users: List<Entity>): EntityProvider {
@@ -21,7 +21,7 @@ import java.util.concurrent.CompletableFuture
class AddHoldsActionEffectKeyframe : ActionEffectKeyframe { class AddHoldsActionEffectKeyframe : ActionEffectKeyframe {
val holds = mutableSetOf<String>() val holds = mutableSetOf<String>()
override fun play(context: ActionEffectContext): CompletableFuture<Unit> { override fun play(context: ActionEffectContext): CompletableFuture<Unit> {
context.holds.addAll(holds) holds.forEach(context::addHold)
return CompletableFuture.completedFuture(Unit) return CompletableFuture.completedFuture(Unit)
} }
} }
@@ -49,6 +49,6 @@ class AnimationActionEffectKeyframe : ConditionalActionEffectKeyframe(), EntityC
players.forEach { it.sendPacket(pkt) } players.forEach { it.sendPacket(pkt) }
} }
return delayedFuture(seconds = delay.resolveFloat(context.runtime)) return delayedFuture(seconds = delay.resolveFloat(context.runtime), tracker = context.tracker)
} }
} }
@@ -46,6 +46,6 @@ class EntityMoLangActionEffectKeyframe : ConditionalActionEffectKeyframe(), Enti
players.forEach { it.sendPacket(pkt) } players.forEach { it.sendPacket(pkt) }
} }
return delayedFuture(seconds = delay.resolveFloat(context.runtime)) return delayedFuture(seconds = delay.resolveFloat(context.runtime), context.tracker)
} }
} }
@@ -18,7 +18,6 @@ import com.cobblemon.mod.common.entity.PosableEntity
import com.cobblemon.mod.common.net.messages.client.effect.SpawnSnowstormEntityParticlePacket import com.cobblemon.mod.common.net.messages.client.effect.SpawnSnowstormEntityParticlePacket
import com.cobblemon.mod.common.util.asExpressionLike import com.cobblemon.mod.common.util.asExpressionLike
import com.cobblemon.mod.common.util.asIdentifierDefaultingNamespace import com.cobblemon.mod.common.util.asIdentifierDefaultingNamespace
import net.minecraft.commands.arguments.EntityArgument.getPlayers
import java.util.concurrent.CompletableFuture import java.util.concurrent.CompletableFuture
import net.minecraft.server.level.ServerLevel import net.minecraft.server.level.ServerLevel
@@ -79,6 +78,6 @@ class EntityParticlesActionEffectKeyframe : ConditionalActionEffectKeyframe(), E
} }
} }
return delayedFuture(seconds = delay.resolveFloat(context.runtime)) return delayedFuture(seconds = delay.resolveFloat(context.runtime), context.tracker)
} }
} }
@@ -15,8 +15,8 @@ import com.cobblemon.mod.common.api.moves.animations.UsersProvider
import com.cobblemon.mod.common.api.scheduling.delayedFuture import com.cobblemon.mod.common.api.scheduling.delayedFuture
import com.cobblemon.mod.common.util.asExpressionLike import com.cobblemon.mod.common.util.asExpressionLike
import com.cobblemon.mod.common.util.asIdentifierDefaultingNamespace import com.cobblemon.mod.common.util.asIdentifierDefaultingNamespace
import net.minecraft.core.registries.Registries
import java.util.concurrent.CompletableFuture import java.util.concurrent.CompletableFuture
import net.minecraft.core.registries.Registries
/** /**
* An action effect keyframe that plays a positioned sound for all matching entities. * An action effect keyframe that plays a positioned sound for all matching entities.
@@ -45,6 +45,6 @@ class EntitySoundActionEffectKeyframe : ConditionalActionEffectKeyframe(), Entit
entity.playSound(soundEvent, 1f, 1f) entity.playSound(soundEvent, 1f, 1f)
} }
return delayedFuture(seconds = delay.resolveFloat(context.runtime)) return delayedFuture(seconds = delay.resolveFloat(context.runtime), context.tracker)
} }
} }
@@ -8,8 +8,6 @@
package com.cobblemon.mod.common.api.moves.animations.keyframes package com.cobblemon.mod.common.api.moves.animations.keyframes
import com.bedrockk.molang.runtime.struct.QueryStruct
import com.cobblemon.mod.common.Cobblemon
import com.cobblemon.mod.common.api.molang.ExpressionLike import com.cobblemon.mod.common.api.molang.ExpressionLike
import com.cobblemon.mod.common.api.moves.animations.ActionEffectContext import com.cobblemon.mod.common.api.moves.animations.ActionEffectContext
import com.cobblemon.mod.common.api.scheduling.delayedFuture import com.cobblemon.mod.common.api.scheduling.delayedFuture
@@ -27,6 +25,6 @@ class MoLangActionEffectKeyframe : ActionEffectKeyframe {
val delay: ExpressionLike = "0".asExpressionLike() val delay: ExpressionLike = "0".asExpressionLike()
override fun play(context: ActionEffectContext): CompletableFuture<Unit> { override fun play(context: ActionEffectContext): CompletableFuture<Unit> {
expressions.resolve(context.runtime) expressions.resolve(context.runtime)
return delayedFuture(seconds = delay.resolveFloat(context.runtime)) return delayedFuture(seconds = delay.resolveFloat(context.runtime), context.tracker)
} }
} }
@@ -13,7 +13,6 @@ import com.cobblemon.mod.common.api.moves.animations.ActionEffectTimeline
import com.cobblemon.mod.common.api.moves.animations.ActionEffects import com.cobblemon.mod.common.api.moves.animations.ActionEffects
import com.cobblemon.mod.common.api.moves.animations.TargetsProvider import com.cobblemon.mod.common.api.moves.animations.TargetsProvider
import com.cobblemon.mod.common.api.moves.animations.UsersProvider import com.cobblemon.mod.common.api.moves.animations.UsersProvider
import com.cobblemon.mod.common.api.scheduling.afterOnServer
import com.cobblemon.mod.common.entity.ai.OmniPathNavigation.NavigationContext import com.cobblemon.mod.common.entity.ai.OmniPathNavigation.NavigationContext
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import com.cobblemon.mod.common.util.asExpressionLike import com.cobblemon.mod.common.util.asExpressionLike
@@ -61,7 +60,7 @@ class MoveToTargetActionEffectKeyframe : ActionEffectKeyframe {
} }
) )
afterOnServer(seconds = timeout.resolveFloat(context.runtime)) { context.tracker.after(seconds = timeout.resolveFloat(context.runtime)) {
if (!future.isDone && !timedOut) { if (!future.isDone && !timedOut) {
timedOut = true timedOut = true
timeoutEffect.run(context).thenApply { future.complete(Unit) } timeoutEffect.run(context).thenApply { future.complete(Unit) }
@@ -14,5 +14,5 @@ import com.cobblemon.mod.common.util.asExpressionLike
class PauseActionEffectKeyframe : ConditionalActionEffectKeyframe() { class PauseActionEffectKeyframe : ConditionalActionEffectKeyframe() {
val pause = "1".asExpressionLike() val pause = "1".asExpressionLike()
override fun playWhenTrue(context: ActionEffectContext) = delayedFuture(seconds = pause.resolveFloat(context.runtime)) override fun playWhenTrue(context: ActionEffectContext) = delayedFuture(seconds = pause.resolveFloat(context.runtime), context.tracker)
} }
@@ -25,11 +25,8 @@ class RemoveHoldsActionEffectKeyframe : ActionEffectKeyframe {
val holds = mutableSetOf<String>() val holds = mutableSetOf<String>()
override fun play(context: ActionEffectContext): CompletableFuture<Unit> { override fun play(context: ActionEffectContext): CompletableFuture<Unit> {
return delayedFuture(seconds = delay).thenApply { return delayedFuture(seconds = delay).thenApply {
if (holds.isEmpty()) { val holdsToRemove = if (holds.isEmpty()) context.getHolds() else holds
context.holds.clear() holdsToRemove.forEach(context::removeHold)
} else {
context.holds.removeAll(holds)
}
} }
} }
} }
@@ -13,13 +13,12 @@ import com.cobblemon.mod.common.api.moves.animations.ActionEffectContext
import com.cobblemon.mod.common.api.moves.animations.ActionEffectTimeline import com.cobblemon.mod.common.api.moves.animations.ActionEffectTimeline
import com.cobblemon.mod.common.api.moves.animations.ActionEffects import com.cobblemon.mod.common.api.moves.animations.ActionEffects
import com.cobblemon.mod.common.api.moves.animations.UsersProvider import com.cobblemon.mod.common.api.moves.animations.UsersProvider
import com.cobblemon.mod.common.api.scheduling.after
import com.cobblemon.mod.common.entity.ai.OmniPathNavigation.NavigationContext import com.cobblemon.mod.common.entity.ai.OmniPathNavigation.NavigationContext
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import com.cobblemon.mod.common.util.asExpressionLike import com.cobblemon.mod.common.util.asExpressionLike
import java.util.concurrent.CompletableFuture
import net.minecraft.resources.ResourceLocation import net.minecraft.resources.ResourceLocation
import net.minecraft.world.phys.Vec3 import net.minecraft.world.phys.Vec3
import java.util.concurrent.CompletableFuture
class ReturnToPositionActionEffectKeyframe : ActionEffectKeyframe { class ReturnToPositionActionEffectKeyframe : ActionEffectKeyframe {
val speed = 1F val speed = 1F
@@ -56,7 +55,7 @@ class ReturnToPositionActionEffectKeyframe : ActionEffectKeyframe {
} }
) )
after(seconds = timeout.resolveFloat(context.runtime)) { context.tracker.after(seconds = timeout.resolveFloat(context.runtime)) {
if (!future.isDone && !timedOut) { if (!future.isDone && !timedOut) {
timedOut = true timedOut = true
timeoutEffect.run(context).thenApply { future.complete(Unit) } timeoutEffect.run(context).thenApply { future.complete(Unit) }
@@ -29,7 +29,6 @@ import com.cobblemon.mod.common.util.withQueryValue
import com.google.gson.JsonElement import com.google.gson.JsonElement
import com.google.gson.JsonObject import com.google.gson.JsonObject
import kotlin.random.Random import kotlin.random.Random
import kotlin.ranges.random
import net.minecraft.server.level.ServerPlayer import net.minecraft.server.level.ServerPlayer
/** /**
@@ -17,21 +17,18 @@ import com.cobblemon.mod.common.api.npc.NPCPartyProvider
import com.cobblemon.mod.common.api.pokemon.PokemonProperties import com.cobblemon.mod.common.api.pokemon.PokemonProperties
import com.cobblemon.mod.common.api.storage.party.NPCPartyStore import com.cobblemon.mod.common.api.storage.party.NPCPartyStore
import com.cobblemon.mod.common.entity.npc.NPCEntity import com.cobblemon.mod.common.entity.npc.NPCEntity
import com.cobblemon.mod.common.util.* import com.cobblemon.mod.common.util.asArrayValue
import com.cobblemon.mod.common.util.asExpression
import com.cobblemon.mod.common.util.cobblemonResource
import com.cobblemon.mod.common.util.resolveFloat
import com.cobblemon.mod.common.util.resolveInt
import com.cobblemon.mod.common.util.weightedSelection
import com.cobblemon.mod.common.util.withQueryValue
import com.google.gson.JsonElement import com.google.gson.JsonElement
import com.google.gson.JsonObject import com.google.gson.JsonObject
import com.google.gson.JsonPrimitive import com.google.gson.JsonPrimitive
import net.minecraft.server.level.ServerPlayer
import kotlin.collections.List
import kotlin.collections.any
import kotlin.collections.filter
import kotlin.collections.first
import kotlin.collections.mutableListOf
import kotlin.collections.mutableMapOf
import kotlin.collections.randomOrNull
import kotlin.collections.set
import kotlin.collections.toMutableList
import kotlin.random.Random import kotlin.random.Random
import net.minecraft.server.level.ServerPlayer
/** /**
* A provider of a party for battling the NPC. It generates a party using a more complex process * A provider of a party for battling the NPC. It generates a party using a more complex process
@@ -67,6 +67,10 @@ object CobblemonPermissions {
val SPAWN_POKEMON = this.create("${COMMAND_PREFIX}spawnpokemon", PermissionLevel.CHEAT_COMMANDS_AND_COMMAND_BLOCKS) val SPAWN_POKEMON = this.create("${COMMAND_PREFIX}spawnpokemon", PermissionLevel.CHEAT_COMMANDS_AND_COMMAND_BLOCKS)
@JvmStatic @JvmStatic
val SPAWN_NPC = this.create("${COMMAND_PREFIX}spawnnpc", PermissionLevel.CHEAT_COMMANDS_AND_COMMAND_BLOCKS) val SPAWN_NPC = this.create("${COMMAND_PREFIX}spawnnpc", PermissionLevel.CHEAT_COMMANDS_AND_COMMAND_BLOCKS)
@JvmStatic
val SPAWN_METEOR = this.create("${COMMAND_PREFIX}spawnmeteor", PermissionLevel.CHEAT_COMMANDS_AND_COMMAND_BLOCKS)
@JvmStatic
val SET_MEGA_BOND = this.create("${COMMAND_PREFIX}setmegabond", PermissionLevel.CHEAT_COMMANDS_AND_COMMAND_BLOCKS)
@JvmStatic @JvmStatic
@@ -12,10 +12,10 @@ import com.cobblemon.mod.common.api.pokedex.AbstractPokedexManager
import com.cobblemon.mod.common.api.pokedex.PokedexEntryProgress import com.cobblemon.mod.common.api.pokedex.PokedexEntryProgress
import com.cobblemon.mod.common.api.pokedex.entry.PokedexEntry import com.cobblemon.mod.common.api.pokedex.entry.PokedexEntry
import com.cobblemon.mod.common.api.pokemon.PokemonSpecies import com.cobblemon.mod.common.api.pokemon.PokemonSpecies
import com.cobblemon.mod.common.api.pokemon.evolution.Evolution
import com.cobblemon.mod.common.api.tms.TechnicalMachines import com.cobblemon.mod.common.api.tms.TechnicalMachines
import com.cobblemon.mod.common.client.CobblemonClient import com.cobblemon.mod.common.client.CobblemonClient
import com.cobblemon.mod.common.pokemon.FormData import com.cobblemon.mod.common.pokemon.FormData
import com.cobblemon.mod.common.pokemon.transformation.evolution.Evolution
import com.cobblemon.mod.common.util.asIdentifierDefaultingNamespace import com.cobblemon.mod.common.util.asIdentifierDefaultingNamespace
enum class PokedexCategoryFilterType { enum class PokedexCategoryFilterType {
@@ -14,11 +14,11 @@ import com.cobblemon.mod.common.api.pokedex.AbstractPokedexManager
import com.cobblemon.mod.common.api.pokedex.PokedexEntryProgress import com.cobblemon.mod.common.api.pokedex.PokedexEntryProgress
import com.cobblemon.mod.common.api.pokedex.entry.PokedexEntry import com.cobblemon.mod.common.api.pokedex.entry.PokedexEntry
import com.cobblemon.mod.common.api.pokemon.PokemonSpecies import com.cobblemon.mod.common.api.pokemon.PokemonSpecies
import com.cobblemon.mod.common.api.pokemon.evolution.Evolution
import com.cobblemon.mod.common.api.tms.TechnicalMachines import com.cobblemon.mod.common.api.tms.TechnicalMachines
import com.cobblemon.mod.common.client.CobblemonClient import com.cobblemon.mod.common.client.CobblemonClient
import com.cobblemon.mod.common.pokemon.abilities.HiddenAbility
import com.cobblemon.mod.common.pokemon.FormData import com.cobblemon.mod.common.pokemon.FormData
import com.cobblemon.mod.common.pokemon.abilities.HiddenAbility
import com.cobblemon.mod.common.pokemon.transformation.evolution.Evolution
import com.cobblemon.mod.common.util.asIdentifierDefaultingNamespace import com.cobblemon.mod.common.util.asIdentifierDefaultingNamespace
import com.cobblemon.mod.common.util.asTranslated import com.cobblemon.mod.common.util.asTranslated
import com.cobblemon.mod.common.util.itemRegistry import com.cobblemon.mod.common.util.itemRegistry
@@ -49,6 +49,7 @@ import com.mojang.brigadier.StringReader
import com.mojang.serialization.Codec import com.mojang.serialization.Codec
import com.mojang.serialization.JsonOps import com.mojang.serialization.JsonOps
import java.util.UUID import java.util.UUID
import kotlin.jvm.optionals.getOrNull
import kotlin.math.min import kotlin.math.min
import kotlin.random.Random import kotlin.random.Random
import net.minecraft.ResourceLocationException import net.minecraft.ResourceLocationException
@@ -65,7 +66,6 @@ import net.minecraft.resources.ResourceLocation
import net.minecraft.server.level.ServerPlayer import net.minecraft.server.level.ServerPlayer
import net.minecraft.world.item.ItemStack import net.minecraft.world.item.ItemStack
import net.minecraft.world.level.Level import net.minecraft.world.level.Level
import kotlin.jvm.optionals.getOrNull
/** /**
* A grouping of typical, selectable properties for a Pokémon. This is serializable * A grouping of typical, selectable properties for a Pokémon. This is serializable
@@ -168,8 +168,8 @@ open class PokemonProperties {
parseIntProperty(keyPairs, listOf("${statName}_iv"))?.coerceIn(0, IVs.MAX_VALUE)?.let { maybeIVs[stat] = it } parseIntProperty(keyPairs, listOf("${statName}_iv"))?.coerceIn(0, IVs.MAX_VALUE)?.let { maybeIVs[stat] = it }
parseIntProperty(keyPairs, listOf("${statName}_ev"))?.coerceIn(0, EVs.MAX_STAT_VALUE)?.let { maybeEVs[stat] = it } parseIntProperty(keyPairs, listOf("${statName}_ev"))?.coerceIn(0, EVs.MAX_STAT_VALUE)?.let { maybeEVs[stat] = it }
} }
props.ivs = maybeIVs props.evs = maybeEVs.takeIf { it.total() > 0 }
props.evs = maybeEVs props.ivs = maybeIVs.takeIf { it.total() > 0 }
props.updateAspects() props.updateAspects()
return props return props
@@ -519,29 +519,18 @@ open class PokemonProperties {
} }
fun matches(properties: PokemonProperties): Boolean { fun matches(properties: PokemonProperties): Boolean {
return properties.asString() == this.asString() // Custom properties check could be duplicated but can't assume 3rd party hasn't done anything type specific
return this.commonMatches(properties) && this.customProperties.containsAll(properties.customProperties)
} }
// Undefined properties will match whatever they're compared with
private fun commonMatches(pokemon: Pokemon): Boolean { private fun commonMatches(pokemon: Pokemon): Boolean {
level?.takeIf { it != pokemon.level }?.let { return false } level?.takeIf { it != pokemon.level }?.let { return false }
shiny?.takeIf { it != pokemon.shiny }?.let { return false } shiny?.takeIf { it != pokemon.shiny }?.let { return false }
gender?.takeIf { it != pokemon.gender }?.let { return false } gender?.takeIf { it != pokemon.gender }?.let { return false }
species?.run { species?.takeIf { it.asSpecies() != pokemon.species }?.let { return false }
try {
val species = if (this == "random") {
PokemonSpecies.species.random()
} else {
PokemonSpecies.getByIdentifier(this.asIdentifierDefaultingNamespace()) ?: return@run
}
if (pokemon.species != species) {
return false
}
} catch (e: ResourceLocationException) {
return false
}
}
nickname?.takeIf { it.string != pokemon.nickname?.string }?.let { return false } nickname?.takeIf { it.string != pokemon.nickname?.string }?.let { return false }
form?.takeIf { !it.equals(pokemon.form.name, true) }?.let { return false } form?.takeIf { !it.equals(pokemon.form.formOnlyShowdownId(), true) }?.let { return false }
friendship?.takeIf { it != pokemon.friendship }?.let { return false } friendship?.takeIf { it != pokemon.friendship }?.let { return false }
fullness?.takeIf { it != pokemon.currentFullness }?.let { return false } fullness?.takeIf { it != pokemon.currentFullness }?.let { return false }
pokeball?.takeIf { it != pokemon.caughtBall.name.toString() }?.let { return false } pokeball?.takeIf { it != pokemon.caughtBall.name.toString() }?.let { return false }
@@ -584,6 +573,36 @@ open class PokemonProperties {
return true return true
} }
// Undefined properties will match whatever they're compared with
private fun commonMatches(properties: PokemonProperties): Boolean {
level?.takeIf { it != properties.level }?.let { return false }
shiny?.takeIf { it != properties.shiny }?.let { return false }
gender?.takeIf { it != properties.gender }?.let { return false }
species?.takeIf { it.asSpecies() != properties.species?.asSpecies() }?.let { return false }
nickname?.takeIf { it.string != properties.nickname?.string }?.let { return false }
form?.takeIf { it != properties.form }?.let { return false }
friendship?.takeIf { it != properties.friendship }?.let { return false }
pokeball?.takeIf { it != properties.pokeball }?.let { return false }
nature?.takeIf { it != properties.nature }?.let { return false }
ability?.takeIf { it != properties.ability }?.let { return false }
status?.takeIf { it != properties.status }?.let { return false }
ivs?.forEach{ stat ->
if (stat.value != properties.ivs?.get(stat.key)) { return false }
}
evs?.forEach{ stat ->
if (stat.value != properties.evs?.get(stat.key)) { return false }
}
type?.takeIf { it != properties.type }?.let { return false }
teraType?.takeIf { it != properties.teraType }?.let { return false }
dmaxLevel?.takeIf { it != properties.dmaxLevel }?.let { return false }
gmaxFactor?.takeIf { it != properties.gmaxFactor }?.let { return false }
tradeable?.takeIf { it != properties.tradeable }?.let { return false }
originalTrainer?.takeIf { it != properties.originalTrainer }?.let{ return false }
originalTrainerType?.takeIf { it != properties.originalTrainerType }?.let{ return false }
moves?.takeIf { it.any { move -> properties.moves?.none { it == move } == true } }?.let { return false }
return true
}
// TODO Review the need for this, usage for us is in commands that deviate from the behavior established by multiple Pokémon query equivalent // TODO Review the need for this, usage for us is in commands that deviate from the behavior established by multiple Pokémon query equivalent
fun isSubSetOf(properties: PokemonProperties): Boolean { fun isSubSetOf(properties: PokemonProperties): Boolean {
level?.takeIf { it != properties.level }?.let { return false } level?.takeIf { it != properties.level }?.let { return false }
@@ -904,4 +923,15 @@ open class PokemonProperties {
} }
fun hasSpecies() = species?.let { PokemonSpecies.getByIdentifier(it.asIdentifierDefaultingNamespace()) } != null fun hasSpecies() = species?.let { PokemonSpecies.getByIdentifier(it.asIdentifierDefaultingNamespace()) } != null
private fun String.asSpecies() =
try {
if (this == "random") {
PokemonSpecies.species.random()
} else {
PokemonSpecies.getByIdentifier(this.asIdentifierDefaultingNamespace())
}
}
catch (e: ResourceLocationException) {
null
}
} }
@@ -12,6 +12,8 @@ import com.bedrockk.molang.Expression
import com.cobblemon.mod.common.Cobblemon import com.cobblemon.mod.common.Cobblemon
import com.cobblemon.mod.common.api.abilities.AbilityPool import com.cobblemon.mod.common.api.abilities.AbilityPool
import com.cobblemon.mod.common.api.abilities.AbilityTemplate import com.cobblemon.mod.common.api.abilities.AbilityTemplate
import com.cobblemon.mod.common.api.abilities.CommonAbility
import com.cobblemon.mod.common.api.abilities.PotentialAbility
import com.cobblemon.mod.common.api.ai.SleepDepth import com.cobblemon.mod.common.api.ai.SleepDepth
import com.cobblemon.mod.common.api.ai.config.BehaviourConfig import com.cobblemon.mod.common.api.ai.config.BehaviourConfig
import com.cobblemon.mod.common.api.ai.config.task.TaskConfig import com.cobblemon.mod.common.api.ai.config.task.TaskConfig
@@ -30,14 +32,14 @@ import com.cobblemon.mod.common.api.pokemon.PokemonSpecies.getByIdentifier
import com.cobblemon.mod.common.api.pokemon.effect.ShoulderEffect import com.cobblemon.mod.common.api.pokemon.effect.ShoulderEffect
import com.cobblemon.mod.common.api.pokemon.effect.adapter.ShoulderEffectAdapter import com.cobblemon.mod.common.api.pokemon.effect.adapter.ShoulderEffectAdapter
import com.cobblemon.mod.common.api.pokemon.egg.EggGroup import com.cobblemon.mod.common.api.pokemon.egg.EggGroup
import com.cobblemon.mod.common.api.pokemon.evolution.Evolution
import com.cobblemon.mod.common.api.pokemon.evolution.PreEvolution
import com.cobblemon.mod.common.api.pokemon.experience.ExperienceGroup import com.cobblemon.mod.common.api.pokemon.experience.ExperienceGroup
import com.cobblemon.mod.common.api.pokemon.experience.ExperienceGroupAdapter import com.cobblemon.mod.common.api.pokemon.experience.ExperienceGroupAdapter
import com.cobblemon.mod.common.api.pokemon.moves.Learnset import com.cobblemon.mod.common.api.pokemon.moves.Learnset
import com.cobblemon.mod.common.api.pokemon.requirement.Requirement
import com.cobblemon.mod.common.api.pokemon.stats.Stat import com.cobblemon.mod.common.api.pokemon.stats.Stat
import com.cobblemon.mod.common.api.pokemon.stats.Stats import com.cobblemon.mod.common.api.pokemon.stats.Stats
import com.cobblemon.mod.common.api.pokemon.transformation.evolution.PreEvolution
import com.cobblemon.mod.common.api.pokemon.transformation.requirement.TransformationRequirement
import com.cobblemon.mod.common.api.pokemon.transformation.trigger.TransformationTrigger
import com.cobblemon.mod.common.api.reactive.SimpleObservable import com.cobblemon.mod.common.api.reactive.SimpleObservable
import com.cobblemon.mod.common.api.riding.behaviour.RidingBehaviourSettings import com.cobblemon.mod.common.api.riding.behaviour.RidingBehaviourSettings
import com.cobblemon.mod.common.api.riding.sound.RideSoundSettingsList import com.cobblemon.mod.common.api.riding.sound.RideSoundSettingsList
@@ -48,12 +50,21 @@ import com.cobblemon.mod.common.net.messages.client.data.SpeciesRegistrySyncPack
import com.cobblemon.mod.common.pokemon.FormData import com.cobblemon.mod.common.pokemon.FormData
import com.cobblemon.mod.common.pokemon.Species import com.cobblemon.mod.common.pokemon.Species
import com.cobblemon.mod.common.pokemon.SpeciesAdditions import com.cobblemon.mod.common.pokemon.SpeciesAdditions
import com.cobblemon.mod.common.pokemon.adapters.CobblemonRequirementAdapter import com.cobblemon.mod.common.pokemon.abilities.HiddenAbility
import com.cobblemon.mod.common.pokemon.abilities.SpecialAbility
import com.cobblemon.mod.common.pokemon.ai.ObtainableItemCondition import com.cobblemon.mod.common.pokemon.ai.ObtainableItemCondition
import com.cobblemon.mod.common.pokemon.ai.ObtainableItemConditionAdapter import com.cobblemon.mod.common.pokemon.ai.ObtainableItemConditionAdapter
import com.cobblemon.mod.common.pokemon.evolution.adapters.CobblemonEvolutionAdapter import com.cobblemon.mod.common.pokemon.transformation.adapters.CobblemonPreEvolutionAdapter
import com.cobblemon.mod.common.pokemon.evolution.adapters.CobblemonPreEvolutionAdapter import com.cobblemon.mod.common.pokemon.transformation.adapters.CobblemonRequirementAdapter
import com.cobblemon.mod.common.pokemon.evolution.adapters.LegacyItemConditionWrapperAdapter import com.cobblemon.mod.common.pokemon.transformation.adapters.CobblemonTriggerAdapter
import com.cobblemon.mod.common.pokemon.transformation.adapters.LegacyItemConditionWrapperAdapter
import com.cobblemon.mod.common.pokemon.transformation.evolution.Evolution
import com.cobblemon.mod.common.pokemon.transformation.form.GigantamaxForm
import com.cobblemon.mod.common.pokemon.transformation.form.PermanentForm
import com.cobblemon.mod.common.pokemon.transformation.form.StandardForm
import com.cobblemon.mod.common.pokemon.transformation.form.TemporaryForm
import com.cobblemon.mod.common.pokemon.transformation.requirements.HeldItemRequirement
import com.cobblemon.mod.common.pokemon.transformation.requirements.MoveSetRequirement
import com.cobblemon.mod.common.util.adapters.* import com.cobblemon.mod.common.util.adapters.*
import com.cobblemon.mod.common.util.cobblemonResource import com.cobblemon.mod.common.util.cobblemonResource
import com.google.common.collect.HashBasedTable import com.google.common.collect.HashBasedTable
@@ -104,10 +115,8 @@ object PokemonSpecies : JsonDataRegistry<Species> {
.registerTypeAdapter(ExperienceGroup::class.java, ExperienceGroupAdapter) .registerTypeAdapter(ExperienceGroup::class.java, ExperienceGroupAdapter)
.registerTypeAdapter(EntityDimensions::class.java, EntityDimensionsAdapter) .registerTypeAdapter(EntityDimensions::class.java, EntityDimensionsAdapter)
.registerTypeAdapter(Learnset::class.java, LearnsetAdapter) .registerTypeAdapter(Learnset::class.java, LearnsetAdapter)
.registerTypeAdapter(Evolution::class.java, CobblemonEvolutionAdapter)
.registerTypeAdapter(AABB::class.java, BoxAdapter) .registerTypeAdapter(AABB::class.java, BoxAdapter)
.registerTypeAdapter(AbilityPool::class.java, AbilityPoolAdapter) .registerTypeAdapter(AbilityPool::class.java, AbilityPoolAdapter)
.registerTypeAdapter(Requirement::class.java, CobblemonRequirementAdapter)
.registerTypeAdapter(PreEvolution::class.java, CobblemonPreEvolutionAdapter) .registerTypeAdapter(PreEvolution::class.java, CobblemonPreEvolutionAdapter)
.registerTypeAdapter(TypeToken.getParameterized(Set::class.java, Evolution::class.java).type, LazySetAdapter(Evolution::class)) .registerTypeAdapter(TypeToken.getParameterized(Set::class.java, Evolution::class.java).type, LazySetAdapter(Evolution::class))
.registerTypeAdapter(IntRange::class.java, IntRangeAdapter) .registerTypeAdapter(IntRange::class.java, IntRangeAdapter)
@@ -128,7 +137,10 @@ object PokemonSpecies : JsonDataRegistry<Species> {
.registerTypeAdapter(TypeToken.getParameterized(RegistryLikeCondition::class.java, Fluid::class.java).type, FluidLikeConditionAdapter) .registerTypeAdapter(TypeToken.getParameterized(RegistryLikeCondition::class.java, Fluid::class.java).type, FluidLikeConditionAdapter)
.registerTypeAdapter(EggGroup::class.java, EggGroupAdapter) .registerTypeAdapter(EggGroup::class.java, EggGroupAdapter)
.registerTypeAdapter(MobEffect::class.java, RegistryElementAdapter<MobEffect>(BuiltInRegistries::MOB_EFFECT)) .registerTypeAdapter(MobEffect::class.java, RegistryElementAdapter<MobEffect>(BuiltInRegistries::MOB_EFFECT))
.registerTypeAdapter(TransformationTrigger::class.java, CobblemonTriggerAdapter)
.registerTypeAdapter(TransformationRequirement::class.java, CobblemonRequirementAdapter)
.registerTypeAdapter(ItemPredicate::class.java, LegacyItemConditionWrapperAdapter) .registerTypeAdapter(ItemPredicate::class.java, LegacyItemConditionWrapperAdapter)
.registerTypeAdapter(FormData::class.java, FormAdapter)
.registerTypeAdapter(RidingBehaviourSettings::class.java, RidingBehaviourSettingsAdapter) .registerTypeAdapter(RidingBehaviourSettings::class.java, RidingBehaviourSettingsAdapter)
.registerTypeAdapter(RideSoundSettingsList::class.java, RideSoundSettingsListAdapter) .registerTypeAdapter(RideSoundSettingsList::class.java, RideSoundSettingsListAdapter)
.registerTypeAdapter(ObtainableItemCondition::class.java, ObtainableItemConditionAdapter) .registerTypeAdapter(ObtainableItemCondition::class.java, ObtainableItemConditionAdapter)
@@ -152,6 +164,9 @@ object PokemonSpecies : JsonDataRegistry<Species> {
val implemented: List<Species> val implemented: List<Species>
get() = this.species.filter { it.implemented } get() = this.species.filter { it.implemented }
val forms: Collection<FormData>
get() = this.species.flatMap { it.allForms }
init { init {
SpeciesAdditions.observable.subscribe { SpeciesAdditions.observable.subscribe {
this.species.forEach(Species::initialize) this.species.forEach(Species::initialize)
@@ -246,34 +261,18 @@ object PokemonSpecies : JsonDataRegistry<Species> {
} }
/** /**
* The representation of a [Species] and/or [FormData] in the context of showdown. * The representation of [FormData] in the context of Showdown.
* This is intended as a sort of DTO that can be easily converted between JSON and Java/JS objects. * This is intended as a sort of DTO that can be easily converted between JSON and Java/JS objects.
* *
* @param species The [Species] being converted or the base species if the form is not null. * @param form The [FormData] being converted into a species (Showdown considers them species).
* @param form The [FormData] being converted int o species (Showdown considers them species) will be null when dealing with the base form.
*/ */
@Suppress("unused") @Suppress("unused")
internal class ShowdownSpecies(species: Species, form: FormData?) { internal open class ShowdownSpecies(form: FormData) {
val num = species.nationalPokedexNumber val num = form.species.nationalPokedexNumber
val name = if (form != null) "${createShowdownName(species)}-${form.name}" else createShowdownName(species) val name = form.showdownName()
val baseSpecies = if (form != null) createShowdownName(species) else this.name val types = form.types.map { it.name }
val forme = form?.name val eggGroups = form.eggGroups.map { it.showdownID }
// ToDo baseForme val gender: String? = when (form.maleRatio) {
val otherFormes = if (form == null && species.forms.isNotEmpty()) species.forms.map { "${this.name}-${it.name}" } else emptyList()
val formeOrder = if (form == null && this.otherFormes.isNotEmpty()) arrayListOf(this.name, *this.otherFormes.toTypedArray()) else emptyList()
val abilities: Map<String, String> = mapOf(
"0" to "No Ability",
"1" to "No Ability",
"H" to "No Ability",
"S" to "No Ability"
)
val types = (form?.types ?: species.types).map { it.name }
val preevo: String? = (form?.preEvolution ?: species.preEvolution)?.let { if (it.form == it.species.standardForm) createShowdownName(it.species) else "${createShowdownName(it.species)}-${it.form.name}" }
// For the context of battles the content here doesn't matter whatsoever and due to how PokemonProperties work we can't guarantee an actual specific species is defined.
val evos = if ((form?.evolutions ?: species.evolutions).isEmpty()) emptyList() else arrayListOf("")
val nfe = this.evos.isNotEmpty()
val eggGroups = (form?.eggGroups ?: species.eggGroups).map { it.showdownID }
val gender: String? = when (form?.maleRatio ?: species.maleRatio) {
0F -> "F" 0F -> "F"
1F -> "M" 1F -> "M"
-1F, 1.125F -> "N" -1F, 1.125F -> "N"
@@ -281,47 +280,145 @@ object PokemonSpecies : JsonDataRegistry<Species> {
} }
val genderRatio = if (this.gender == null) val genderRatio = if (this.gender == null)
mapOf( mapOf(
"maleRatio" to (form?.maleRatio ?: species.maleRatio), "M" to (form.maleRatio),
"femaleRation" to (1F - (form?.maleRatio ?: species.maleRatio)) "F" to (1F - (form.maleRatio))
) else null ) else null
val baseStats = mapOf( val baseStats = Stats.PERMANENT.associateBy({ it.showdownId }, { form.baseStats[it] ?: 1 })
"hp" to (form?.baseStats?.get(Stats.HP) ?: species.baseStats[Stats.HP] ?: 1), val heightm = form.height / 10
"atk" to (form?.baseStats?.get(Stats.ATTACK) ?: species.baseStats[Stats.ATTACK] ?: 1), val weightkg = form.weight / 10
"def" to (form?.baseStats?.get(Stats.DEFENCE) ?: species.baseStats[Stats.DEFENCE] ?: 1),
"spa" to (form?.baseStats?.get(Stats.SPECIAL_ATTACK) ?: species.baseStats[Stats.SPECIAL_ATTACK] ?: 1),
"spd" to (form?.baseStats?.get(Stats.SPECIAL_DEFENCE) ?: species.baseStats[Stats.SPECIAL_DEFENCE] ?: 1),
"spe" to (form?.baseStats?.get(Stats.SPEED) ?: species.baseStats[Stats.SPEED] ?: 1)
)
val heightm = (form?.height ?: species.height) / 10
val weightkg = (form?.weight ?: species.weight) / 10
// This is ugly, but we already have it hardcoded in the mod anyway // This is ugly, but we already have it hardcoded in the mod anyway
val maxHP = if (species.showdownId() == "shedinja") 1 else null val maxHP = if (this.num == 292) 1 else null
val canGigantamax: String? = if (form?.gigantamaxMove != null) form.gigantamaxMove.name else null val cannotDynamax = form.dynamaxBlocked
val cannotDynamax = form?.dynamaxBlocked ?: species.dynamaxBlocked val abilities = form.showdownAbilityMapping()
// ToDo battleOnly // Common fields exempt from standard forms
// ToDo changesFrom val baseSpecies = if (form !is StandardForm) form.species.standardForm.showdownName() else null
val requiredMove = form?.requiredMove val forme = if (form !is StandardForm) form.name else null
val requiredItem = form?.requiredItem
val requiredItems = form?.requiredItems /**
* The following fields are optional and currently omitted
*
* cosmeticFormes (not needed, we have species features)
* addedType (tertiary type [by name or showdownid] added by moves or abilities)
* tier (smogon tryhard bs)
* doublesTier (smogon tryhard bs)
* natDexTier (smogon tryhard bs)
* evoType (the evolution method used to evolve from 'prevo'; trade', 'useItem', 'levelMove', 'levelExtra', 'levelFriendship', 'levelHold', 'other')
* evoMove (the move [by name or showdownid] used to evolve from 'prevo')
* evoLevel (the minimum level required to evolve from 'prevo')
* canHatch (flag for baby pokemon)
* color (color, value is arbitrary)
* tags (flags for filtering pokemon; 'Mega', 'Mythical', 'Sub-Legendary', 'Restricted Legendary', 'Paradox')
* unreleasedHidden (whether this pokemon has an unreleased hidden ability)
* maleOnlyHidden (whether it is only possible to get the hidden ability on a male pokemon)
* gmaxUnreleased (whether this pokemon has an unreleased gmax form)
* pokemonGoData (no one cares)
*/
} }
private fun createShowdownName(species: Species): String { /**
if (species.resourceIdentifier.namespace == Cobblemon.MODID) { * The representation of a [PermanentForm] in the context of Showdown.
return species.name *
* @param form The [PermanentForm] being converted into a species.
*/
internal open class ShowdownPermanentForm(form: PermanentForm) : ShowdownSpecies(form) {
// species this form evolves from
val prevo = form.preEvolution?.form?.showdownName()
// For the context of battles the content here doesn't matter whatsoever and due to how PokemonProperties work we can't guarantee an actual specific species is defined.
val evos = form.evolutions.map { "" }
// not fully evolved
val nfe = this.evos.isNotEmpty()
// whether there is a gmax form to change to
val canGigantamax: String? = form.changeableForms.filterIsInstance<GigantamaxForm>().firstOrNull()?.name // TODO id better
}
/**
* The representation of a [StandardForm] in the context of Showdown.
*
* @param form The [StandardForm] being converted into a species.
*/
internal class ShowdownStandardForm(form: StandardForm) : ShowdownPermanentForm(form) {
// list of all forms descending from this base species
val otherFormes = form.flattenForms().map { it.showdownName() }
// list of forms [by name or showdownid] in the order they appear in game [union of baseSpecies, otherFormes, and cosmeticFormes] with the exception of ending with 'Gmax' forms
val formeOrder = if (this.otherFormes.isNotEmpty()) arrayListOf(this.name, *this.otherFormes.toTypedArray()) else null
// TODO we don't enforce any form order with our Species registration - right now this looks like only a problem with Mega Rayquaza, but investigate changes needed on Showdown's end to enable these lists to be more dynamic
}
/**
* The representation of a [TemporaryForm] in the context of Showdown.
*
* @param form The [TemporaryForm] being converted into a species.
*/
internal class ShowdownTemporaryForm(form: TemporaryForm) : ShowdownSpecies(form) {
// form change can occur during a battle
val battleOnly = if (form.battleOnly) form.parentForm.showdownName() else null
// form change can occur outside of battle (mutually exclusive with battleOnly)
val changesFrom = if (!form.battleOnly) form.parentForm.showdownName() else null
// pokemon must know this move to be in this form
val requiredMove = form.requirements.filterIsInstance<MoveSetRequirement>().firstOrNull()?.move?.showdownId() // TODO update showdown to support 'requiredMoves'
// pokemon must hold one of these item(s) to be in this form
val requiredItems = form.requirements.filterIsInstance<HeldItemRequirement>().firstOrNull()?.let { requirement ->
try {
requirement.itemCondition.items.get().map { BuiltInRegistries.ITEM.getKey(it.value()).path } // TODO held items on showdown are ignorant of namespace
}
catch (e: NoSuchElementException)
{
Cobblemon.LOGGER.error("Failed to resolve required held item for ${form.showdownId()}}") // TODO this needs to be done after tags are loaded...
null
}
} }
return "${species.resourceIdentifier.namespace}:${species.name}" }
/** Accommodate for Showdown bullshit. */
/*
private fun TemporaryForm.showdownParentForm(): Any {
if (this.parentOverrides.isNotEmpty())
return this.species.standardForm.flattenForms().filter {
parentOverrides.contains(it.showdownId())
}.map {
it.showdownName()
}
else
return parentForm.showdownName()
}
*/
/**
* Constructs a mapping of the [PotentialAbility]s belonging to a [FormData] in Showdown identifiable format.
*
* @return A map of type (numeric for [CommonAbility]s, H for [HiddenAbility], S for [SpecialAbility]) to showdownid.
*/
private fun FormData.showdownAbilityMapping(): Map<String, String>? {
// potential abilities
val commonAbilities = this.abilities.filterIsInstance<CommonAbility>()
val hiddenAbility = this.abilities.find { it is HiddenAbility }
val specialAbility = this.abilities.find { it is SpecialAbility }
// can have multiple common abilities
val abilities = mutableMapOf<String, String>()
val mapping: (String, PotentialAbility) -> Unit = { key, ability ->
abilities.put(key, ability.template.showdownId())
}
// can only have one hidden and one special ability
commonAbilities.forEachIndexed { index, ability -> mapping(index.toString(), ability) }
hiddenAbility?.let { ability -> mapping("H", ability) }
specialAbility?.let { ability -> mapping("S", ability) }
return if (abilities.isEmpty()) null else abilities
} }
internal fun allShowdownSpecies(): Map<String, String> { internal fun allShowdownSpecies(): Map<String, String> {
val result = mutableMapOf<String, String>() val result = mutableMapOf<String, String>()
this.species.forEach {species -> this.species.forEach { species ->
val baseSpecies = ShowdownSpecies(species, null) species.permanentForms.forEach { form ->
result[ShowdownIdentifiable.REGEX.replace(baseSpecies.name.lowercase(), "")] = this.gson.toJson(baseSpecies) val formSpecies = ShowdownSpecies(form)
species.forms.forEach { form -> result[ShowdownIdentifiable.REGEX.replace(formSpecies.name.lowercase(), "")] = this.gson.toJson(formSpecies)
if (form != species.standardForm) { }
val formSpecies = ShowdownSpecies(species, form) species.temporaryForms.forEach { form ->
result[ShowdownIdentifiable.REGEX.replace(formSpecies.name.lowercase(), "")] = this.gson.toJson(formSpecies) val formSpecies = ShowdownSpecies(form)
} result[ShowdownIdentifiable.REGEX.replace(formSpecies.name.lowercase(), "")] = this.gson.toJson(formSpecies)
} }
} }
return result return result
@@ -1,34 +0,0 @@
/*
* 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.api.pokemon.adapters
import com.cobblemon.mod.common.api.pokemon.requirement.Requirement
import com.google.gson.JsonDeserializer
import com.google.gson.JsonSerializer
import kotlin.reflect.KClass
/**
* Saves and loads [Requirement]s with JSON.
* For the default implementation see [com.cobblemon.mod.common.pokemon.adapters.CobblemonRequirementAdapter].
*
* @author Licious
* @since March 21st, 2022
*/
interface RequirementAdapter : JsonDeserializer<Requirement>, JsonSerializer<Requirement> {
/**
* Registers the given type of [Requirement] to it's associated ID for deserialization.
*
* @param T The type of [Requirement].
* @param id The id of the evolution event.
* @param type The [KClass] of the type.
*/
fun <T : Requirement> registerType(id: String, type: KClass<T>)
}
@@ -0,0 +1,32 @@
/*
* 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.api.pokemon.aspect
import com.cobblemon.mod.common.api.pokemon.feature.SpeciesFeature
import com.cobblemon.mod.common.pokemon.Pokemon
/**
* A provider of aspects for a [SpeciesFeature].
*
* @author Segfault Guy
* @since Feb 12th, 2024
*/
interface FeatureAspectProvider: AspectProvider {
var default: String?
var isAspect: Boolean
/** Returns true if this [aspect] is provided by this provider. */
fun matches(aspect: String): Boolean
/** Creates a [SpeciesFeature] that provides the respective [aspect]. */
fun from(aspect: String): SpeciesFeature<*>?
/** Sets the [aspect] that's provided. */
fun set(pokemon: Pokemon, aspect: String)
}
@@ -24,11 +24,11 @@ interface SingleConditionalAspectProvider : AspectProvider {
fun getForFeature(name: String): SingleConditionalAspectProvider { fun getForFeature(name: String): SingleConditionalAspectProvider {
return object : SingleConditionalAspectProvider { return object : SingleConditionalAspectProvider {
override val aspect: String = name override val aspect: String = name
override fun meetsCondition(pokemon: Pokemon) = pokemon.getFeature<FlagSpeciesFeature>(name)?.enabled == true override fun meetsCondition(pokemon: Pokemon) = pokemon.getFeature<FlagSpeciesFeature>(name)?.value == true
override fun meetsCondition(pokemonProperties: PokemonProperties) = pokemonProperties override fun meetsCondition(pokemonProperties: PokemonProperties) = pokemonProperties
.customProperties .customProperties
.filterIsInstance<FlagSpeciesFeature>() .filterIsInstance<FlagSpeciesFeature>()
.any { it.name == name && it.enabled } .any { it.name == name && it.value }
} }
} }
@@ -1,54 +0,0 @@
/*
* 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.api.pokemon.evolution
import com.cobblemon.mod.common.pokemon.Pokemon
import com.cobblemon.mod.common.pokemon.evolution.variants.ItemInteractionEvolution
import com.cobblemon.mod.common.pokemon.evolution.variants.TradeEvolution
/**
* Represents an evolution of a [Pokemon] that can only occur during specific actions and with added context.
* For the default implementations see [ItemInteractionEvolution] & [TradeEvolution].
*
* @param RC The context given at runtime when querying the [Evolution].
* @param TC The context that is serialized from JSON during species loading, this is what the [RC] is expected to match against.
* @author Licious
* @since March 19th, 2022
*/
interface ContextEvolution<RC, TC> : Evolution {
/**
* The target context for this [Evolution] to even be tested.
*/
val requiredContext: TC
/**
* Attempts to evolve the given [Pokemon] under the given context of type [RC].
*
* @param pokemon The [Pokemon] attempting to evolve.
* @param context The context of this query.
* @return If the evolution was successful.
*/
fun attemptEvolution(pokemon: Pokemon, context: RC): Boolean {
if (this.testContext(pokemon, context) && super.test(pokemon)) {
return super.evolve(pokemon)
}
return false
}
/**
* Checks if the given context is valid for the [requiredContext].
*
* @param pokemon The [Pokemon] attempting to evolve.
* @param context The context of this query.
* @return If the context matched the [requiredContext].
*/
fun testContext(pokemon: Pokemon, context: RC): Boolean
}
@@ -1,69 +0,0 @@
/*
* 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.api.pokemon.evolution
import com.cobblemon.mod.common.api.pokemon.evolution.progress.EvolutionProgress
import com.cobblemon.mod.common.pokemon.Pokemon
import com.cobblemon.mod.common.pokemon.evolution.controller.ClientEvolutionController
import com.cobblemon.mod.common.pokemon.evolution.controller.ServerEvolutionController
/**
* Responsible for holding all available [EvolutionLike]s in the [Pokemon].
* Also handles all the networking behind them.
* For the Cobblemon default implementations see [ClientEvolutionController] & [ServerEvolutionController].
*
* @author Licious
* @since April 28th, 2022
*/
interface EvolutionController<T : EvolutionLike, out I : PreProcessor> : MutableSet<T> {
/**
* Resolves the [Pokemon] attached to this controller.
*
* @return The [Pokemon] this controller is attached to.
*/
fun pokemon(): Pokemon
/**
* Starts the given evolution on this controller.
* All the necessary networking will be handled.
*
* @param evolution The [EvolutionLike] starting.
*/
fun start(evolution: T)
/**
* Returns an immutable collection of [EvolutionProgress]es attached to this controller.
*
* @return The currently tracked [EvolutionProgress]es.
*/
fun progress(): Collection<EvolutionProgress<*>>
/**
* Attaches a [EvolutionProgress] to this controller.
*
* @param P The type of [EvolutionProgress].
* @param progress The [EvolutionProgress] being attached for tracking.
* @return The instance being tracked.
*/
fun <P : EvolutionProgress<*>> trackProgress(progress: P): P
/**
* Attempts to find an [EvolutionProgress] in [progress] or creates and tracks using [trackProgress].
*
* @param P The type of [EvolutionProgress].
* @param predicate The lambda attempting to find specific progress. This needs to ensure the [EvolutionProgress] is of type [P] or the cast will fail.
* @param progressFactory The lambda creating a new instance of type [P] if [predicate] can't find an element.
* @return The found match in [progress] or the created and now tracked with [trackProgress].
*/
fun <P : EvolutionProgress<*>> progressFirstOrCreate(predicate: (progress: EvolutionProgress<*>) -> Boolean, progressFactory: () -> P): P
fun asIntermediate(): I
}
@@ -1,48 +0,0 @@
/*
* 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.api.pokemon.evolution
import com.cobblemon.mod.common.pokemon.Pokemon
import com.cobblemon.mod.common.pokemon.Species
import com.cobblemon.mod.common.pokemon.evolution.CobblemonEvolutionDisplay
import com.mojang.serialization.Codec
import com.mojang.serialization.codecs.RecordCodecBuilder
/**
* Represents an evolution of a [Pokemon], this is the client side counterpart of [Evolution].
* This has no attachments to any data regarding the evolution itself and only serves for display purposes and basic communication.
*
* @author Licious
* @since April 28th, 2022
*/
interface EvolutionDisplay : EvolutionLike {
/**
* The [Species] of the evolution result.
*/
val species: Species
/**
* The aspects of the evolution result.
* These are used by the client to resolve the entity it needs to display.
*/
val aspects: Set<String>
companion object {
@JvmStatic
val CODEC: Codec<EvolutionDisplay> = RecordCodecBuilder.create { instance ->
instance.group(
Codec.STRING.fieldOf("id").forGetter(EvolutionDisplay::id),
Species.BY_IDENTIFIER_CODEC.fieldOf("species").forGetter(EvolutionDisplay::species),
Codec.list(Codec.STRING).fieldOf("aspects").forGetter { it.aspects.toList() }
).apply(instance) { id, species, aspects -> CobblemonEvolutionDisplay(id, species, aspects.toSet()) }
}
}
}
@@ -1,59 +0,0 @@
/*
* 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.api.pokemon.evolution
/**
* Responsible for holding the different [EvolutionController] implementations based on the logical side.
* If you haven't already checked your side previously you can use [isClient].
*
* @param C The type of [EvolutionLike] on the client side.
* @param S The type of [EvolutionLike] on the server side.
* @param CI The type of [PreProcessor] on the client side.
* @param SI The type of [PreProcessor] on the server side.
*
* @author Licious
* @since June 18th, 2022
*/
interface EvolutionProxy<C : EvolutionLike, S : EvolutionLike, CI : PreProcessor, SI : PreProcessor> {
/**
* Checks if the current logical side is the client.
*
* @return True if the current logical side is the client.
*/
fun isClient(): Boolean
/**
* Returns the current [EvolutionController].
* Keep in mind this will have type erasure and as such most operations will not be possible.
* It's recommended to work with [client] or [server] when possible.
*
* @return The current [EvolutionController].
*/
fun current(): EvolutionController<out EvolutionLike, *>
/**
* The client side implementation of the [EvolutionController].
*
* @throws [ClassCastException] if called from the server side.
*
* @return The client side implementation of the [EvolutionController] if possible.
*/
fun client(): EvolutionController<C, CI>
/**
* The server side implementation of the [EvolutionController].
*
* @throws [ClassCastException] if called from the client side.
*
* @return The server side implementation of the [EvolutionController] if possible.
*/
fun server(): EvolutionController<S, SI>
}
@@ -1,43 +0,0 @@
/*
* 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.api.pokemon.evolution
import com.cobblemon.mod.common.pokemon.Pokemon
import com.cobblemon.mod.common.pokemon.evolution.variants.LevelUpEvolution
/**
* Represents an evolution of a [Pokemon] that can occur without any additional context or actions.
* For the default implementation see [LevelUpEvolution].
*
* @author Licious
* @since March 19th, 2022
*/
interface PassiveEvolution : Evolution {
/**
* Checks if the given [Pokemon] satisfies the requirements.
* If yes the evolution will attempt to start.
*
* @param pokemon The [Pokemon] being tested.
* @return If the [Pokemon] will evolve.
*/
fun attemptEvolution(pokemon: Pokemon): Boolean {
if (super.test(pokemon)) {
return super.evolve(pokemon)
}
return false
}
/**
* If the evolution will disappear once the conditions are no longer met.
*/
val permanent: Boolean
}
@@ -1,35 +0,0 @@
/*
* 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.api.pokemon.evolution.adapters
import com.cobblemon.mod.common.api.pokemon.evolution.Evolution
import com.cobblemon.mod.common.pokemon.evolution.adapters.CobblemonEvolutionAdapter
import com.google.gson.JsonDeserializer
import com.google.gson.JsonSerializer
import kotlin.reflect.KClass
/**
* Saves and loads [Evolution]s with JSON.
* For the default implementation see [CobblemonEvolutionAdapter].
*
* @author Licious
* @since March 20th, 2022
*/
interface EvolutionAdapter : JsonDeserializer<Evolution>, JsonSerializer<Evolution> {
/**
* Registers the given type of [Evolution] to it's associated ID for deserialization.
*
* @param T The type of [Evolution].
* @param id The id of the evolution event.
* @param type The [KClass] of the type.
*/
fun <T : Evolution> registerType(id: String, type: KClass<T>)
}
@@ -1,66 +0,0 @@
/*
* 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.api.pokemon.evolution.progress
import com.cobblemon.mod.common.pokemon.evolution.controller.ServerEvolutionController
import com.cobblemon.mod.common.pokemon.evolution.progress.*
import com.cobblemon.mod.common.util.cobblemonResource
import com.mojang.serialization.Codec
import com.mojang.serialization.Lifecycle
import net.minecraft.core.MappedRegistry
import net.minecraft.core.Registry
import net.minecraft.resources.ResourceKey
import net.minecraft.resources.ResourceLocation
import kotlin.jvm.Throws
object EvolutionProgressTypes {
private val REGISTRY: Registry<EvolutionProgressType<*>> = MappedRegistry(
ResourceKey.createRegistryKey(cobblemonResource("evolution_progress")), Lifecycle.stable()
)
@JvmStatic
val DAMAGE_TAKEN = this.registerType(DamageTakenEvolutionProgress.ID, EvolutionProgressType(DamageTakenEvolutionProgress.CODEC))
@JvmStatic
val DEFEAT = this.registerType(DefeatEvolutionProgress.ID, EvolutionProgressType(DefeatEvolutionProgress.CODEC))
@JvmStatic
val LAST_BATTLE_CRITICAL_HITS = this.registerType(LastBattleCriticalHitsEvolutionProgress.ID, EvolutionProgressType(LastBattleCriticalHitsEvolutionProgress.CODEC))
@JvmStatic
val RECOIL = this.registerType(RecoilEvolutionProgress.ID, EvolutionProgressType(RecoilEvolutionProgress.CODEC))
@JvmStatic
val USE_MOVE = this.registerType(UseMoveEvolutionProgress.ID, EvolutionProgressType(UseMoveEvolutionProgress.CODEC))
/**
* Registers an evolution progress.
*
* @param T The type of the [EvolutionProgress].
* @param id The [Identifier].
* @param type The [EvolutionProgressType] record.
* @return The registered [EvolutionProgressType] of type [T].
*
* @throws [IllegalStateException] if [Registry.register] fails.
*/
@Throws(IllegalStateException::class)
@JvmStatic
fun <T : EvolutionProgress<*>> registerType(id: ResourceLocation, type: EvolutionProgressType<T>): EvolutionProgressType<T> {
return Registry.register(REGISTRY, id, type)
}
/**
* Creates a codec instance of this registry.
*
* @return The generated [Codec] of [EvolutionProgress].
*/
fun codec(): Codec<EvolutionProgress<*>> = REGISTRY.byNameCodec().dispatch(
ServerEvolutionController.ID_KEY,
{ it.type() },
{ it.codec }
)
}
@@ -12,7 +12,7 @@ import com.cobblemon.mod.common.Cobblemon
import com.cobblemon.mod.common.api.tags.CobblemonItemTags import com.cobblemon.mod.common.api.tags.CobblemonItemTags
import com.cobblemon.mod.common.battles.pokemon.BattlePokemon import com.cobblemon.mod.common.battles.pokemon.BattlePokemon
import com.cobblemon.mod.common.pokemon.OriginalTrainerType import com.cobblemon.mod.common.pokemon.OriginalTrainerType
import com.cobblemon.mod.common.pokemon.requirements.LevelRequirement import com.cobblemon.mod.common.pokemon.transformation.requirements.LevelRequirement
import kotlin.math.pow import kotlin.math.pow
import kotlin.math.roundToInt import kotlin.math.roundToInt
@@ -8,6 +8,7 @@
package com.cobblemon.mod.common.api.pokemon.feature package com.cobblemon.mod.common.api.pokemon.feature
import com.cobblemon.mod.common.api.pokemon.PokemonProperties
import com.cobblemon.mod.common.pokemon.Pokemon import com.cobblemon.mod.common.pokemon.Pokemon
import com.cobblemon.mod.common.util.readString import com.cobblemon.mod.common.util.readString
import com.cobblemon.mod.common.util.substitute import com.cobblemon.mod.common.util.substitute
@@ -80,4 +81,29 @@ class ChoiceSpeciesFeatureProvider : AbstractChoiceSpeciesFeatureProvider<List<S
} }
return aspects return aspects
} }
override fun provide(pokemon: Pokemon): Set<String> {
return if (isAspect) {
get(pokemon)?.let {
setOf(getAspect(it))
} ?: emptySet()
} else {
emptySet()
}
}
override fun get(pokemon: Pokemon) = pokemon.getFeature<StringSpeciesFeature>(keys.first())
override fun provide(properties: PokemonProperties): Set<String> {
return if (isAspect) {
val feature = properties.customProperties.filterIsInstance<StringSpeciesFeature>().find { it.name == keys.first() }
if (feature != null) {
setOf(getAspect(feature))
} else {
emptySet()
}
} else {
emptySet()
}
}
} }
@@ -9,7 +9,7 @@
package com.cobblemon.mod.common.api.pokemon.feature package com.cobblemon.mod.common.api.pokemon.feature
import com.cobblemon.mod.common.api.pokemon.PokemonProperties import com.cobblemon.mod.common.api.pokemon.PokemonProperties
import com.cobblemon.mod.common.api.pokemon.aspect.AspectProvider import com.cobblemon.mod.common.api.pokemon.aspect.FeatureAspectProvider
import com.cobblemon.mod.common.api.properties.CustomPokemonProperty import com.cobblemon.mod.common.api.properties.CustomPokemonProperty
import com.cobblemon.mod.common.api.properties.CustomPokemonPropertyType import com.cobblemon.mod.common.api.properties.CustomPokemonPropertyType
import com.cobblemon.mod.common.client.gui.summary.featurerenderers.SummarySpeciesFeatureRenderer import com.cobblemon.mod.common.client.gui.summary.featurerenderers.SummarySpeciesFeatureRenderer
@@ -17,9 +17,9 @@ import com.cobblemon.mod.common.pokemon.Pokemon
import com.cobblemon.mod.common.util.readString import com.cobblemon.mod.common.util.readString
import com.cobblemon.mod.common.util.writeString import com.cobblemon.mod.common.util.writeString
import com.google.gson.JsonObject import com.google.gson.JsonObject
import kotlin.random.Random
import net.minecraft.nbt.CompoundTag import net.minecraft.nbt.CompoundTag
import net.minecraft.network.RegistryFriendlyByteBuf import net.minecraft.network.RegistryFriendlyByteBuf
import kotlin.random.Random
/** /**
* A simple [SpeciesFeature] that is a true/false flag value. It implements [CustomPokemonProperty] for use in * A simple [SpeciesFeature] that is a true/false flag value. It implements [CustomPokemonProperty] for use in
@@ -30,65 +30,74 @@ import kotlin.random.Random
* @author Hiroku * @author Hiroku
* @since May 13th, 2022 * @since May 13th, 2022
*/ */
open class FlagSpeciesFeature(override val name: String) : SynchronizedSpeciesFeature, CustomPokemonProperty { open class FlagSpeciesFeature(override val name: String) : SynchronizedSpeciesFeature<Boolean>, CustomPokemonProperty {
constructor(name: String, enabled: Boolean): this(name) { constructor(name: String, enabled: Boolean): this(name) {
this.enabled = enabled this.value = enabled
} }
var enabled = false override var value: Boolean = false
override fun saveToNBT(pokemonNBT: CompoundTag): CompoundTag { override fun saveToNBT(pokemonNBT: CompoundTag): CompoundTag {
pokemonNBT.putBoolean(name, enabled) pokemonNBT.putBoolean(name, value)
return pokemonNBT return pokemonNBT
} }
override fun loadFromNBT(pokemonNBT: CompoundTag): SpeciesFeature { override fun loadFromNBT(pokemonNBT: CompoundTag): SpeciesFeature<Boolean> {
enabled = if (pokemonNBT.contains(name)) pokemonNBT.getBoolean(name) else enabled value = if (pokemonNBT.contains(name)) pokemonNBT.getBoolean(name) else value
return this return this
} }
override fun saveToJSON(pokemonJSON: JsonObject): JsonObject { override fun saveToJSON(pokemonJSON: JsonObject): JsonObject {
pokemonJSON.addProperty(name, enabled) pokemonJSON.addProperty(name, value)
return pokemonJSON return pokemonJSON
} }
override fun loadFromJSON(pokemonJSON: JsonObject): SpeciesFeature { override fun loadFromJSON(pokemonJSON: JsonObject): SpeciesFeature<Boolean> {
val isEnabled = pokemonJSON.get(name)?.asBoolean val isEnabled = pokemonJSON.get(name)?.asBoolean
enabled = isEnabled ?: this.enabled value = isEnabled ?: this.value
return this return this
} }
override fun saveToBuffer(buffer: RegistryFriendlyByteBuf, toClient: Boolean) { override fun saveToBuffer(buffer: RegistryFriendlyByteBuf, toClient: Boolean) {
buffer.writeBoolean(enabled) buffer.writeBoolean(value)
} }
override fun loadFromBuffer(buffer: RegistryFriendlyByteBuf) { override fun loadFromBuffer(buffer: RegistryFriendlyByteBuf) {
enabled = buffer.readBoolean() value = buffer.readBoolean()
} }
override fun asString() = "$name=$enabled" override fun asString() = "$name=$value"
override fun apply(pokemon: Pokemon) { override fun apply(pokemon: Pokemon) {
val featureProvider = SpeciesFeatures.getFeature(name) ?: return val featureProvider = SpeciesFeatures.getFeature(name) ?: return
if (featureProvider in SpeciesFeatures.getFeaturesFor(pokemon.species)) { if (featureProvider in SpeciesFeatures.getFeaturesFor(pokemon.species)) {
val existingFeature = pokemon.getFeature<FlagSpeciesFeature>(name) val existingFeature = pokemon.getFeature<FlagSpeciesFeature>(name)
if (existingFeature != null) { if (existingFeature != null) {
existingFeature.enabled = enabled existingFeature.value = value
} else { } else {
pokemon.features.add(FlagSpeciesFeature(name, enabled)) pokemon.features.add(FlagSpeciesFeature(name, value))
} }
pokemon.updateAspects() pokemon.updateAspects()
} }
} }
override fun matches(pokemon: Pokemon) = pokemon.getFeature<FlagSpeciesFeature>(name)?.enabled == enabled override fun matches(pokemon: Pokemon) = pokemon.getFeature<FlagSpeciesFeature>(name)?.value == value
} }
class FlagSpeciesFeatureProvider : SynchronizedSpeciesFeatureProvider<FlagSpeciesFeature>, CustomPokemonPropertyType<FlagSpeciesFeature>, AspectProvider { class FlagSpeciesFeatureProvider : SynchronizedSpeciesFeatureProvider<FlagSpeciesFeature>, CustomPokemonPropertyType<FlagSpeciesFeature>, FeatureAspectProvider {
override var keys: List<String> = emptyList() override var keys: List<String> = emptyList()
// Uses get() = true because that way there's no backing field. It MUST be true, this way no JSON trickery will overwrite it // Uses get() = true because that way there's no backing field. It MUST be true, this way no JSON trickery will overwrite it
override val needsKey get() = true override val needsKey get() = true
var default: String? = null override var default: String? = null
var isAspect = true override var isAspect = true
override fun matches(aspect: String): Boolean = this.isAspect && this.keys.first() == aspect
override fun from(aspect: String): SpeciesFeature<*>? = if (matches(aspect)) fromString(null) else null
override fun set(pokemon: Pokemon, aspect: String) {
this.get(pokemon)?.value = true
}
override var visible: Boolean = false override var visible: Boolean = false
override fun invoke(buffer: RegistryFriendlyByteBuf, name: String): FlagSpeciesFeature? { override fun invoke(buffer: RegistryFriendlyByteBuf, name: String): FlagSpeciesFeature? {
@@ -174,7 +183,7 @@ class FlagSpeciesFeatureProvider : SynchronizedSpeciesFeatureProvider<FlagSpecie
override fun provide(pokemon: Pokemon): Set<String> { override fun provide(pokemon: Pokemon): Set<String> {
return if (isAspect) { return if (isAspect) {
val feature = pokemon.features.filterIsInstance<FlagSpeciesFeature>().find { it.name in keys } val feature = pokemon.features.filterIsInstance<FlagSpeciesFeature>().find { it.name in keys }
if (feature != null && feature.enabled) { if (feature != null && feature.value) {
setOf(keys.first()) setOf(keys.first())
} else { } else {
emptySet() emptySet()
@@ -187,7 +196,7 @@ class FlagSpeciesFeatureProvider : SynchronizedSpeciesFeatureProvider<FlagSpecie
override fun provide(properties: PokemonProperties): Set<String> { override fun provide(properties: PokemonProperties): Set<String> {
return if (isAspect) { return if (isAspect) {
val feature = properties.customProperties.filterIsInstance<FlagSpeciesFeature>().find { it.name in keys } val feature = properties.customProperties.filterIsInstance<FlagSpeciesFeature>().find { it.name in keys }
if (feature != null && feature.enabled) { if (feature != null && feature.value) {
setOf(keys.first()) setOf(keys.first())
} else { } else {
emptySet() emptySet()

Some files were not shown because too many files have changed in this diff Show More