Compare commits

...
Author SHA1 Message Date
Paul a7e6e638fe Added run_command molang function to general query structs and player structs 2024-05-20 09:10:04 +10:00
Paul 9ef3ea2932 Use context for flows because it's cooler, added more functions to pokemon related molang 2024-05-19 19:08:56 +10:00
Paul 38dcee3327 Merge remote-tracking branch 'origin/sega_bass_pro_fishing_2' into event-flows
# Conflicts:
#	common/src/main/kotlin/com/cobblemon/mod/common/CobblemonNetwork.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/entity/pokeball/EmptyPokeBallEntity.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/util/MoLangExtensions.kt
2024-05-19 11:27:18 +10:00
Paul 12b92d3f35 Added flow datapackable thing 2024-02-24 11:58:57 +10:00
Paul dacfb4f1ff Merge branch 'npcs' into event-flows
# Conflicts:
#	common/src/main/kotlin/com/cobblemon/mod/common/entity/pokeball/EmptyPokeBallEntity.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/util/MoLangExtensions.kt
2024-02-24 10:02:26 +10:00
Paul 4086ba73d3 Some structs for things 2024-02-24 09:59:27 +10:00
14 changed files with 318 additions and 17 deletions
@@ -93,6 +93,7 @@ import com.cobblemon.mod.common.config.constraint.IntConstraint
import com.cobblemon.mod.common.config.starter.StarterConfig
import com.cobblemon.mod.common.data.CobblemonDataProvider
import com.cobblemon.mod.common.events.AdvancementHandler
import com.cobblemon.mod.common.events.FlowHandler
import com.cobblemon.mod.common.events.ServerTickHandler
import com.cobblemon.mod.common.item.PokeBallItem
import com.cobblemon.mod.common.net.messages.client.settings.ServerSettingsPacket
@@ -299,6 +300,8 @@ object Cobblemon {
CustomPokemonProperty.register(AspectPropertyType)
CustomPokemonProperty.register(UnaspectPropertyType)
FlowHandler.setup()
ifDedicatedServer {
isDedicatedServer = true
}
@@ -0,0 +1,74 @@
/*
* 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
import com.bedrockk.molang.runtime.MoLangRuntime
import com.bedrockk.molang.runtime.value.MoValue
import com.cobblemon.mod.common.api.data.DataRegistry
import com.cobblemon.mod.common.api.molang.ExpressionLike
import com.cobblemon.mod.common.api.molang.MoLangFunctions.setup
import com.cobblemon.mod.common.api.reactive.SimpleObservable
import com.cobblemon.mod.common.api.scripting.CobblemonScripts
import com.cobblemon.mod.common.util.asExpressionLike
import com.cobblemon.mod.common.util.cobblemonResource
import com.cobblemon.mod.common.util.endsWith
import java.util.concurrent.ExecutionException
import net.minecraft.resource.ResourceManager
import net.minecraft.resource.ResourceType
import net.minecraft.server.network.ServerPlayerEntity
import net.minecraft.util.Identifier
/**
* Holds all the flows that are loaded from the server's data packs. A flow is foldered under the event identifier,
* which can be cobblemon's namespace but can also be minecraft or any other namespace someone has added hooks for.
* The value of the map is a list of MoLang scripts that will execute when that event occurs.
*
* @author Hiroku
* @since February 24th, 2024
*/
object CobblemonFlows : DataRegistry {
override val id = cobblemonResource("flows")
override val observable = SimpleObservable<CobblemonFlows>()
override val type = ResourceType.SERVER_DATA
override fun sync(player: ServerPlayerEntity) {}
val runtime by lazy { MoLangRuntime().setup() }
val clientFlows = hashMapOf<Identifier, MutableList<ExpressionLike>>()
val flows = hashMapOf<Identifier, MutableList<ExpressionLike>>()
override fun reload(manager: ResourceManager) {
val folderBeforeNameRegex = ".*\\/([^\\/]+)\\/[^\\/]+\$".toRegex()
manager.findResources("flows") { path -> path.endsWith(CobblemonScripts.MOLANG_EXTENSION) }.forEach { (identifier, resource) ->
resource.inputStream.use { stream ->
stream.bufferedReader().use { reader ->
try {
val expression = reader.readText().asExpressionLike()
val event = folderBeforeNameRegex.find(identifier.path)?.groupValues?.get(1)
?: throw IllegalArgumentException("Invalid flow path: $identifier. Should have a folder structure that includes the name of the event being flowed.")
if (identifier.path.startsWith("flows/client/")) {
clientFlows.getOrPut(Identifier(identifier.namespace, event)) { mutableListOf() }.add(expression)
} else {
flows.getOrPut(Identifier(identifier.namespace, event)) { mutableListOf() }.add(expression)
}
} catch (exception: Exception) {
throw ExecutionException("Error loading MoLang script for flow: $identifier", exception)
}
}
}
}
Cobblemon.LOGGER.info("Loaded ${CobblemonScripts.scripts.size} flows and ${CobblemonScripts.clientScripts.size} client flows")
observable.emit(this)
}
fun run(eventIdentifier: Identifier, context: Map<String, MoValue>) {
flows[eventIdentifier]?.forEach { it.resolve(runtime, context) }
}
}
@@ -66,6 +66,7 @@ import com.cobblemon.mod.common.net.messages.client.callback.OpenPartyCallbackPa
import com.cobblemon.mod.common.net.messages.client.callback.OpenPartyMoveCallbackPacket
import com.cobblemon.mod.common.net.messages.client.data.AbilityRegistrySyncPacket
import com.cobblemon.mod.common.net.messages.client.data.BerryRegistrySyncPacket
import com.cobblemon.mod.common.net.messages.client.data.FlowRegistrySyncPacket
import com.cobblemon.mod.common.net.messages.client.data.GlobalSpeciesFeatureSyncPacket
import com.cobblemon.mod.common.net.messages.client.data.MovesRegistrySyncPacket
import com.cobblemon.mod.common.net.messages.client.data.NPCRegistrySyncPacket
@@ -322,6 +323,7 @@ object CobblemonNetwork : NetworkManager {
this.createClientBound(NaturalMaterialRegistrySyncPacket.ID, NaturalMaterialRegistrySyncPacket::decode, DataRegistrySyncPacketHandler())
this.createClientBound(FossilRegistrySyncPacket.ID, FossilRegistrySyncPacket::decode, DataRegistrySyncPacketHandler())
this.createClientBound(PokeRodRegistrySyncPacket.ID, PokeRodRegistrySyncPacket::decode, DataRegistrySyncPacketHandler())
this.createClientBound(FlowRegistrySyncPacket.ID, FlowRegistrySyncPacket::decode, DataRegistrySyncPacketHandler())
// Effects
this.createClientBound(SpawnSnowstormParticlePacket.ID, SpawnSnowstormParticlePacket::decode, SpawnSnowstormParticleHandler)
@@ -8,12 +8,23 @@
package com.cobblemon.mod.common.api.events.pokemon
import com.bedrockk.molang.runtime.value.MoValue
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMoLangValue
import com.cobblemon.mod.common.entity.pokeball.EmptyPokeBallEntity
import com.cobblemon.mod.common.pokemon.Pokemon
import com.cobblemon.mod.common.util.itemRegistry
import net.minecraft.registry.RegistryKeys
import net.minecraft.server.network.ServerPlayerEntity
data class PokemonCapturedEvent (
val pokemon: Pokemon,
val player: ServerPlayerEntity,
val pokeBallEntity: EmptyPokeBallEntity
)
) {
val context = mapOf<String, MoValue>(
"pokemon" to pokemon.struct,
"player" to player.asMoLangValue(),
"poke_ball" to pokeBallEntity.struct,
"item" to player.world.itemRegistry.getEntry(pokeBallEntity.pokeBall.item).asMoLangValue(RegistryKeys.ITEM)
)
}
@@ -31,6 +31,7 @@ import com.cobblemon.mod.common.util.getBooleanOrNull
import com.cobblemon.mod.common.util.getDoubleOrNull
import com.cobblemon.mod.common.util.isInt
import com.cobblemon.mod.common.util.itemRegistry
import com.cobblemon.mod.common.util.server
import com.cobblemon.mod.common.util.worldRegistry
import com.mojang.datafixers.util.Either
import net.minecraft.block.Block
@@ -63,6 +64,11 @@ import net.minecraft.world.dimension.DimensionType
*/
object MoLangFunctions {
val generalFunctions = hashMapOf<String, java.util.function.Function<MoParams, Any>>(
"run_command" to java.util.function.Function { params ->
val command = params.getString(0)
val server = server() ?: return@Function DoubleValue(0)
server.commandManager.executeWithPrefix(server.commandSource, command)
},
"is_int" to java.util.function.Function { params -> DoubleValue(params.get<MoValue>(0).asString().isInt()) },
"is_number" to java.util.function.Function { params -> DoubleValue(params.get<MoValue>(0).asString().toDoubleOrNull() != null) },
"to_number" to java.util.function.Function { params -> DoubleValue(params.get<MoValue>(0).asString().toDoubleOrNull() ?: 0.0) },
@@ -135,6 +141,11 @@ object MoLangFunctions {
environment.structs["query"] = player.asMoLangValue()
environment
}
map.put("run_command") { params ->
val command = params.getString(0)
val server = server() ?: return@put DoubleValue(0)
server.commandManager.executeWithPrefix(player.commandSource, command)
}
map
}
)
@@ -10,6 +10,7 @@ package com.cobblemon.mod.common.data
import com.cobblemon.mod.common.Cobblemon
import com.cobblemon.mod.common.Cobblemon.LOGGER
import com.cobblemon.mod.common.CobblemonFlows
import com.cobblemon.mod.common.CobblemonMechanics
import com.cobblemon.mod.common.api.abilities.Abilities
import com.cobblemon.mod.common.api.berry.Berries
@@ -78,6 +79,7 @@ object CobblemonDataProvider : DataProvider {
this.register(NaturalMaterials)
this.register(Fossils)
this.register(NPCClasses)
this.register(CobblemonFlows)
CobblemonSpawnPools.load()
this.register(PokeRods)
@@ -43,6 +43,7 @@ import com.cobblemon.mod.common.net.messages.client.battle.BattleCaptureStartPac
import com.cobblemon.mod.common.net.messages.client.spawn.SpawnPokeballPacket
import com.cobblemon.mod.common.pokeball.PokeBall
import com.cobblemon.mod.common.pokemon.properties.UncatchableProperty
import com.cobblemon.mod.common.util.asArrayValue
import com.cobblemon.mod.common.util.*
import net.minecraft.entity.EntityDimensions
import net.minecraft.entity.EntityPose
@@ -113,6 +114,7 @@ class EmptyPokeBallEntity : ThrownItemEntity, Poseable, WaterDragModifier, Sched
override val struct = QueryStruct(hashMapOf())
.addFunction("capture_state") { StringValue(captureState.name) }
.addFunction("ball_type") { StringValue(pokeBall.name.toString()) }
.addFunction("aspects") { aspects.asArrayValue { StringValue(it) } }
override fun initDataTracker() {
super.initDataTracker()
@@ -25,6 +25,7 @@ import com.cobblemon.mod.common.api.interaction.PokemonEntityInteraction
import com.cobblemon.mod.common.api.molang.MoLangFunctions.addStandardFunctions
import com.cobblemon.mod.common.api.net.serializers.PoseTypeDataSerializer
import com.cobblemon.mod.common.api.net.serializers.StringSetDataSerializer
import com.cobblemon.mod.common.api.pokemon.PokemonProperties
import com.cobblemon.mod.common.api.pokemon.feature.FlagSpeciesFeature
import com.cobblemon.mod.common.api.pokemon.status.Statuses
import com.cobblemon.mod.common.api.reactive.ObservableSubscription
@@ -239,15 +240,25 @@ open class PokemonEntity(
.addFunction("is_wild") { DoubleValue(pokemon.isWild()) }
.addFunction("is_shiny") { DoubleValue(pokemon.shiny) }
.addFunction("form") { StringValue(pokemon.form.name) }
.addFunction("weight") { DoubleValue(pokemon.species.weight.toDouble()) }
.addFunction("width") { DoubleValue(boundingBox.xLength) }
.addFunction("height") { DoubleValue(boundingBox.yLength) }
.addFunction("horizontal_velocity") { DoubleValue(velocity.horizontalLength()) }
.addFunction("vertical_velocity") { DoubleValue(velocity.y) }
.addFunction("weight") { DoubleValue(pokemon.species.weight.toDouble()) }
.addFunction("is_moving") { DoubleValue((moveControl as? PokemonMoveControl)?.isMoving == true) }
.addFunction("is_underwater") { DoubleValue(getIsSubmerged()) }
.addFunction("is_flying") { DoubleValue(getBehaviourFlag(PokemonBehaviourFlag.FLYING)) }
.addFunction("is_passenger") { DoubleValue(hasVehicle()) }
.addFunction("pokemon") { pokemon.struct }
.addFunction("matches") {
val props = PokemonProperties.parse(it.getString(0))
DoubleValue(props.matches(this))
}
.addFunction("apply") {
val props = PokemonProperties.parse(it.getString(0))
props.apply(this)
DoubleValue(true)
}
init {
delegate.initialize(this)
@@ -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.events
import com.cobblemon.mod.common.CobblemonFlows
import com.cobblemon.mod.common.api.events.CobblemonEvents
import com.cobblemon.mod.common.util.cobblemonResource
/**
* Handles the registration of the default Cobblemon event hooks into flows.
*/
object FlowHandler {
fun setup() {
CobblemonEvents.POKEMON_CAPTURED.subscribe { CobblemonFlows.run(cobblemonResource("pokemon_captured"), it.context) }
}
}
@@ -0,0 +1,52 @@
/*
* 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.net.messages.client.data
import com.cobblemon.mod.common.CobblemonFlows
import com.cobblemon.mod.common.api.molang.ExpressionLike
import com.cobblemon.mod.common.util.asExpressionLike
import com.cobblemon.mod.common.util.cobblemonResource
import net.minecraft.network.PacketByteBuf
import net.minecraft.util.Identifier
/**
* A packet that synchronizes the flow registry with the client.
*
* @author Hiroku
* @since February 24th, 2024
*/
class FlowRegistrySyncPacket(entries: Collection<Map.Entry<Identifier, List<ExpressionLike>>>) : DataRegistrySyncPacket<Map.Entry<Identifier, List<ExpressionLike>>, FlowRegistrySyncPacket>(entries){
companion object {
val ID = cobblemonResource("flow_registry_sync")
fun decode(buffer: PacketByteBuf): FlowRegistrySyncPacket = FlowRegistrySyncPacket(emptyList()).apply { decodeBuffer(buffer) }
}
override val id = ID
override fun encodeEntry(buffer: PacketByteBuf, entry: Map.Entry<Identifier, List<ExpressionLike>>) {
buffer.writeIdentifier(entry.key)
buffer.writeCollection(entry.value) { _, expression -> buffer.writeString(expression.toString()) }
}
override fun decodeEntry(buffer: PacketByteBuf): Map.Entry<Identifier, List<ExpressionLike>> {
val key = buffer.readIdentifier()
val value = buffer.readList { buffer.readString().asExpressionLike() }
return object : Map.Entry<Identifier, List<ExpressionLike>> {
override val key = key
override val value = value
}
}
override fun synchronizeDecoded(entries: Collection<Map.Entry<Identifier, List<ExpressionLike>>>) {
entries.map { (identifier, flows) ->
val existing = CobblemonFlows.flows.getOrPut(identifier) { mutableListOf() }
existing += flows
}
}
}
@@ -8,6 +8,9 @@
package com.cobblemon.mod.common.pokeball
import com.bedrockk.molang.runtime.struct.QueryStruct
import com.bedrockk.molang.runtime.value.DoubleValue
import com.bedrockk.molang.runtime.value.StringValue
import com.cobblemon.mod.common.api.pokeball.PokeBalls
import com.cobblemon.mod.common.api.pokeball.catching.CaptureEffect
import com.cobblemon.mod.common.api.pokeball.catching.CatchRateModifier
@@ -37,6 +40,12 @@ open class PokeBall(
val throwPower: Float,
val ancient: Boolean
) {
val struct = QueryStruct(hashMapOf())
.addFunction("name") { StringValue(name.toString()) }
.addFunction("water_drag_value") { DoubleValue(waterDragValue) }
.addFunction("throw_power") { DoubleValue(throwPower) }
.addFunction("is_ancient") { DoubleValue(ancient) }
// .addFunction("item") { } // requires a registry which is hard
// This gets attached during item registry
internal lateinit var item: PokeBallItem
@@ -8,8 +8,10 @@
package com.cobblemon.mod.common.pokemon
import com.bedrockk.molang.runtime.struct.QueryStruct
import com.bedrockk.molang.runtime.struct.VariableStruct
import com.bedrockk.molang.runtime.value.DoubleValue
import com.bedrockk.molang.runtime.value.StringValue
import com.cobblemon.mod.common.Cobblemon
import com.cobblemon.mod.common.CobblemonNetwork.sendPacketToPlayers
import com.cobblemon.mod.common.CobblemonSounds
@@ -21,15 +23,32 @@ import com.cobblemon.mod.common.api.entity.PokemonSender
import com.cobblemon.mod.common.api.events.CobblemonEvents
import com.cobblemon.mod.common.api.events.CobblemonEvents.FRIENDSHIP_UPDATED
import com.cobblemon.mod.common.api.events.CobblemonEvents.POKEMON_FAINTED
import com.cobblemon.mod.common.api.events.pokemon.*
import com.cobblemon.mod.common.api.moves.*
import com.cobblemon.mod.common.api.events.pokemon.ExperienceGainedPostEvent
import com.cobblemon.mod.common.api.events.pokemon.ExperienceGainedPreEvent
import com.cobblemon.mod.common.api.events.pokemon.FriendshipUpdatedEvent
import com.cobblemon.mod.common.api.events.pokemon.HeldItemEvent
import com.cobblemon.mod.common.api.events.pokemon.LevelUpEvent
import com.cobblemon.mod.common.api.events.pokemon.PokemonFaintedEvent
import com.cobblemon.mod.common.api.events.pokemon.PokemonRecalledEvent
import com.cobblemon.mod.common.api.events.pokemon.PokemonSentPostEvent
import com.cobblemon.mod.common.api.events.pokemon.PokemonSentPreEvent
import com.cobblemon.mod.common.api.moves.BenchedMove
import com.cobblemon.mod.common.api.moves.BenchedMoves
import com.cobblemon.mod.common.api.moves.Move
import com.cobblemon.mod.common.api.moves.MoveSet
import com.cobblemon.mod.common.api.moves.MoveTemplate
import com.cobblemon.mod.common.api.moves.Moves
import com.cobblemon.mod.common.api.pokeball.PokeBalls
import com.cobblemon.mod.common.api.pokemon.Natures
import com.cobblemon.mod.common.api.pokemon.PokemonProperties
import com.cobblemon.mod.common.api.pokemon.PokemonPropertyExtractor
import com.cobblemon.mod.common.api.pokemon.PokemonSpecies
import com.cobblemon.mod.common.api.pokemon.aspect.AspectProvider
import com.cobblemon.mod.common.api.pokemon.evolution.*
import com.cobblemon.mod.common.api.pokemon.evolution.Evolution
import com.cobblemon.mod.common.api.pokemon.evolution.EvolutionController
import com.cobblemon.mod.common.api.pokemon.evolution.EvolutionDisplay
import com.cobblemon.mod.common.api.pokemon.evolution.EvolutionProxy
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.ExperienceSource
import com.cobblemon.mod.common.api.pokemon.feature.SpeciesFeature
@@ -62,7 +81,11 @@ import com.cobblemon.mod.common.net.messages.client.PokemonUpdatePacket
import com.cobblemon.mod.common.net.messages.client.pokemon.update.*
import com.cobblemon.mod.common.net.serverhandling.storage.SendOutPokemonHandler.SEND_OUT_DURATION
import com.cobblemon.mod.common.pokeball.PokeBall
import com.cobblemon.mod.common.pokemon.activestate.*
import com.cobblemon.mod.common.pokemon.activestate.ActivePokemonState
import com.cobblemon.mod.common.pokemon.activestate.InactivePokemonState
import com.cobblemon.mod.common.pokemon.activestate.PokemonState
import com.cobblemon.mod.common.pokemon.activestate.SentOutState
import com.cobblemon.mod.common.pokemon.activestate.ShoulderedState
import com.cobblemon.mod.common.pokemon.evolution.CobblemonEvolutionProxy
import com.cobblemon.mod.common.pokemon.evolution.progress.DamageTakenEvolutionProgress
import com.cobblemon.mod.common.pokemon.evolution.progress.RecoilEvolutionProgress
@@ -71,13 +94,32 @@ import com.cobblemon.mod.common.pokemon.misc.GimmighoulStashHandler
import com.cobblemon.mod.common.pokemon.properties.UncatchableProperty
import com.cobblemon.mod.common.pokemon.status.PersistentStatus
import com.cobblemon.mod.common.pokemon.status.PersistentStatusContainer
import com.cobblemon.mod.common.util.*
import com.cobblemon.mod.common.util.DataKeys
import com.cobblemon.mod.common.util.asIdentifierDefaultingNamespace
import com.cobblemon.mod.common.util.cobblemonResource
import com.cobblemon.mod.common.util.lang
import com.cobblemon.mod.common.util.playSoundServer
import com.cobblemon.mod.common.util.server
import com.cobblemon.mod.common.util.setPositionSafely
import com.cobblemon.mod.common.util.toBlockPos
import com.google.gson.JsonArray
import com.google.gson.JsonObject
import com.google.gson.JsonPrimitive
import com.mojang.serialization.Dynamic
import com.mojang.serialization.JsonOps
import net.minecraft.block.*
import java.util.UUID
import java.util.concurrent.CompletableFuture
import kotlin.math.absoluteValue
import kotlin.math.max
import kotlin.math.min
import kotlin.math.roundToInt
import kotlin.random.Random
import net.minecraft.block.CactusBlock
import net.minecraft.block.CampfireBlock
import net.minecraft.block.FireBlock
import net.minecraft.block.MagmaBlock
import net.minecraft.block.SweetBerryBushBlock
import net.minecraft.block.WitherRoseBlock
import net.minecraft.entity.LivingEntity
import net.minecraft.entity.player.PlayerEntity
import net.minecraft.item.ItemStack
@@ -100,13 +142,6 @@ import net.minecraft.util.math.MathHelper.ceil
import net.minecraft.util.math.MathHelper.clamp
import net.minecraft.util.math.Vec3d
import net.minecraft.world.World
import java.util.*
import java.util.concurrent.CompletableFuture
import kotlin.math.absoluteValue
import kotlin.math.max
import kotlin.math.min
import kotlin.math.roundToInt
import kotlin.random.Random
enum class OriginalTrainerType
{
@@ -1597,6 +1632,46 @@ open class Pokemon : ShowdownIdentifiable {
/** Returns an [Observable] that emits Unit whenever any change is made to this Pokémon. The change itself is not included. */
fun getChangeObservable(): Observable<Pokemon> = anyChangeObservable
val struct = QueryStruct(hashMapOf())
.addFunction("species") { species.struct }
.addFunction("is_shiny") { DoubleValue(shiny) }
.addFunction("form") { StringValue(form.name) }
.addFunction("is_wild") { DoubleValue(isWild()) }
.addFunction("level") { DoubleValue(level.toDouble()) }
.addFunction("max_hp") { DoubleValue(hp.toDouble()) }
.addFunction("current_hp") { DoubleValue(currentHealth.toDouble()) }
.addFunction("friendship") { DoubleValue(friendship.toDouble()) }
.addFunction("shiny") { DoubleValue(shiny) }
.addFunction("set_hp") { params ->
val value = params.params[0].asDouble()
if (value < 0) {
currentHealth = 0
} else if (value > hp) {
currentHealth = hp
} else {
currentHealth = value.toInt()
}
DoubleValue(currentHealth.toDouble())
}
.addFunction("set_shiny") { params ->
val value = params.params[0].asDouble() == 1.0
shiny = value
DoubleValue(if (shiny) 1.0 else 0.0)
}
.addFunction("matches") {
val props = PokemonProperties.parse(it.getString(0))
DoubleValue(props.matches(this))
}
.addFunction("apply") {
val props = PokemonProperties.parse(it.getString(0))
props.apply(this)
DoubleValue(true)
}
// .addFunction("ev") { evs.struct }
// .addFunction("iv") { ivs.struct }
fun writeVariables(struct: VariableStruct) {
struct.setDirectly("level", DoubleValue(level.toDouble()))
struct.setDirectly("max_hp", DoubleValue(hp.toDouble()))
@@ -8,6 +8,8 @@
package com.cobblemon.mod.common.pokemon
import com.bedrockk.molang.runtime.struct.QueryStruct
import com.bedrockk.molang.runtime.value.StringValue
import com.cobblemon.mod.common.Cobblemon
import com.cobblemon.mod.common.CobblemonSounds
import com.cobblemon.mod.common.api.abilities.AbilityPool
@@ -134,6 +136,22 @@ class Species : ClientDataSynchronizer<Species>, ShowdownIdentifiable {
var lightingData: LightingData? = null
private set
@Transient
val struct = QueryStruct(hashMapOf())
.addFunction("name") { StringValue(this.resourceIdentifier.toString()) }
.addFunction("national_pokedex_number") { StringValue(this.nationalPokedexNumber.toString()) }
.addFunction("primary_type") { StringValue(this.primaryType.name) }
.addFunction("secondary_type") { StringValue(this.secondaryType?.name ?: "null") }
.addFunction("experience_group") { StringValue(this.experienceGroup.name) }
.addFunction("height") { StringValue(this.height.toString()) }
.addFunction("weight") { StringValue(this.weight.toString()) }
.addFunction("base_scale") { StringValue(this.baseScale.toString()) }
.addFunction("hitbox_width") { StringValue(this.hitbox.width.toString()) }
.addFunction("hitbox_height") { StringValue(this.hitbox.height.toString()) }
.addFunction("hitbox_fixed") { StringValue(this.hitbox.fixed.toString()) }
.addFunction("catch_rate") { StringValue(this.catchRate.toString()) }
fun initialize() {
Cobblemon.statProvider.provide(this)
this.forms.forEach { it.initialize(this) }
@@ -14,6 +14,9 @@ import com.bedrockk.molang.ast.NumberExpression
import com.bedrockk.molang.runtime.MoLangEnvironment
import com.bedrockk.molang.runtime.MoLangRuntime
import com.bedrockk.molang.runtime.MoParams
import com.bedrockk.molang.runtime.MoScope
import com.bedrockk.molang.runtime.struct.ArrayStruct
import com.bedrockk.molang.runtime.struct.QueryStruct
import com.bedrockk.molang.runtime.struct.VariableStruct
import com.bedrockk.molang.runtime.value.MoValue
import com.cobblemon.mod.common.Cobblemon
@@ -37,7 +40,7 @@ fun MoLangRuntime.resolve(expression: Expression, context: Map<String, MoValue>
execute(listOf(expression), context)
// expression.evaluate(MoScope(), environment)
} catch (e: Exception) {
throw IllegalArgumentException("Unable to parse expression: ${expression.getString()}", e)
throw IllegalArgumentException("Unable to evaluate expression: ${expression.getString()}", e)
}
fun MoLangRuntime.resolveDouble(expression: Expression, context: Map<String, MoValue> = emptyMap()): Double = resolve(expression, context).asDouble()
fun MoLangRuntime.resolveFloat(expression: Expression, context: Map<String, MoValue> = emptyMap()): Float = resolve(expression, context).asDouble().toFloat()
@@ -185,4 +188,10 @@ fun MoLangRuntime.withQueryValue(name: String, value: MoValue): MoLangRuntime {
fun MoLangRuntime.withPlayerValue(name: String = "player", value: PlayerEntity) = withQueryValue(name, value.asMoLangValue())
//fun MoLangRuntime.withPokemonValue(name: String = "pokemon", value: Pokemon) = withQueryValue(name, value.asMoLangValue())
fun MoLangRuntime.withNPCValue(name: String = "npc", value: NPCEntity) = withQueryValue(name, value.struct)
fun MoLangRuntime.withNPCValue(name: String = "npc", value: NPCEntity) = withQueryValue(name, value.struct)
fun <T> Collection<T>.asArrayValue(mapper: (T) -> MoValue): ArrayStruct {
val array = ArrayStruct()
forEachIndexed { index, value -> array.setDirectly("$index", mapper(value)) }
return array
}