mirror of
https://gitlab.com/cable-mc/cobblemon.git
synced 2026-10-21 06:36:25 -04:00
Compare commits
3
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5661ae2cb0 | ||
|
|
9e9603d60d | ||
|
|
7fe91f7ad0 |
@@ -6,7 +6,6 @@
|
||||
- Cat Pokémon (Meowth, Persian, etc.) intimidate Creepers and Phantoms.
|
||||
- Sleep-related Pokémon (Munsharna, Komala, etc.) intimidate Phantoms.
|
||||
- Some Pokémon naturally hunt each other.
|
||||
- Some Pokémon herd together.
|
||||
- Added a Behaviour Editor to the NPC editing screen.
|
||||
- Added /behaviouredit command for opening the Behaviour Editor on Pokémon and NPCs.
|
||||
- Editing variables for Pokémon is not yet supported.
|
||||
|
||||
+1
-2
@@ -1,7 +1,6 @@
|
||||
### Additions
|
||||
- Added functionality for marks.
|
||||
- Added data for all marks and ribbons from the mainline Pokémon games.
|
||||
- Implemented fishing, personality, weather, and time related marks, that can rarely be granted to a wild-spawned Pokémon.
|
||||
- Added data for all marks and all title ribbons from Pokémon.
|
||||
- Added marks screen within the summary UI.
|
||||
- Added `/givemark <player> <partySlot> <mark>` command to give a mark to a Pokémon.
|
||||
- Added `/takemark <player> <partySlot> <mark>` command to remove a mark from a Pokémon.
|
||||
|
||||
+2
-11
@@ -1,28 +1,19 @@
|
||||
### Additions
|
||||
- Added ability to rename PC Boxes by clicking on the name of a box.
|
||||
- Added box options buttons for boxes, toggleable by clicking the right icon button in the bottom bar.
|
||||
- The option buttons on the left side allow for sorting the box by name, level, Pokédex number, gender, and type. Shift clicking allows for sorting in reverse order.
|
||||
- The button on the right allows for changing the box wallpaper.
|
||||
- 10 additional color-based wallpapers have been added.
|
||||
- 5 unlockable biome-based wallpapers have been added, which can be unlocked by visiting:
|
||||
- Forest biome
|
||||
- Ocean biome
|
||||
- Cave Biome
|
||||
- The End
|
||||
- The Nether
|
||||
- The option buttons on the left side allow for sorting the box by name, level, Pokédex number, gender, and type. Shift clicking allows for sorting in reverse order.
|
||||
- Added filter functionality in PC UI, which supports `PokemonProperties` (e.g. `shiny=yes` shows all shiny Pokémon).
|
||||
- Names can be filtered by exact or partial matches, e.g. entering "cha" will show Charmander, Charmeleon, etc.
|
||||
- Added `/changewallpaper <player> <boxNumber> <wallpaper>` command to change a box wallpaper through commands.
|
||||
- Added `/renamebox <player> <boxNumber> <name>` command to rename a PC box through commands.
|
||||
- Added IVs and EVs stat displays in PC.
|
||||
- The displays can be cycled through by scrolling when the display is hovered over.
|
||||
- Added ability to cycle through boxes by scrolling when the box is hovered over.
|
||||
- Added ability to change boxes by scrolling.
|
||||
- PC will now open to last box viewed within a session.
|
||||
|
||||
### Changes
|
||||
- Slots in pastures will now have darker backgrounds and italicised Pokémon names if the Pokémon is not owned by the player.
|
||||
- The pasture slot will show the name of the Pokémon owner when hovered if the Pokémon is not owned.
|
||||
- Increased the default PC box count from 30 to 40 to accommodate the fact that we have way more Pokémon now. If you've changed this config option then you'll need to edit it again after starting up with 1.7!
|
||||
|
||||
### Developer
|
||||
- Added `RenamePCBoxEvent.Pre` and `RenamePCBoxEvent.Post` events to prevent players from renaming a box or changing their input.
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
|
||||
### Fixes
|
||||
- Fixed the "enabled" property in spawn files not actually being respected. Where do they find these devs?
|
||||
- Fixed Terralith's shrubland not counting as plains for spawning purposes the way it was intended to.
|
||||
|
||||
### Developer
|
||||
- Spawning Influences now have the context of what the other buckets are when adjusting bucket weights. This will break existing influences that do bucket weight adjustment.
|
||||
|
||||
+17
-383
@@ -11,11 +11,11 @@
|
||||
- Pokémon's held items can now be rendered, with a visibility toggle in the Summary screen.
|
||||
- Added cosmetic item functionality for Pokémon. Certain cosmetic items can be given to applicable Pokémon via the interact menu.
|
||||
- Added the various log blocks as cosmetic items for Timburr and Komala.
|
||||
- Added cosmetics for Spoink, Gurdurr, Conkeldurr, Squirtle Line, Sneasler, Sandile line, Treecko line, Braixen, Delphox, and Dragonite.
|
||||
- Added Gilded Chest cosmetics for Chest Gimmighoul and Gholdengo
|
||||
- Added `visibility/hidden`, `visibility/hat` and `visibility/face` tags to control where and how certain items are rendered.
|
||||
- Added Pokémon markings, toggleable within the summary.
|
||||
- Added `/boxcount` command to change PC boxes amount
|
||||
- Added cosmetics for Gurdurr, Conkeldurr, Squirtle Line, Sneasler, Sandile line, Treecko line, Braixen, Delphox, and Dragonite.
|
||||
- Added cosmetics for Gurdurr, Conkeldurr, Squirtle Line, Sneasler, Sandle line, Treecko line, Braixen, Delphox, and Dragonite.
|
||||
- Added `/transformmodelpart (position|rotation|scale) <modelPart> <transform: x y z>` command that can add transformations to a pokemon's model part.
|
||||
- The player executing the command must be facing the target pokemon entity. Transformations are not persistent and will revert when resources are reloaded.
|
||||
- Added `legacy` and `special` sourced moves to Pokémon.
|
||||
@@ -23,7 +23,7 @@
|
||||
- Added `translucent_cull` boolean option into resolver's layer to allow for translucent textures with culling
|
||||
- Added [LambDynamicLights](https://modrinth.com/mod/lambdynamiclights) support for items held by Pokémon, evolution stone blocks, evolution stone items, Pokédex, Luminous Moss, Flame Orb, and Magmarizer.
|
||||
- Added the Clear Amulet, Grip Claw, Lagging Tail, Luminous Moss, Metal Alloy, Scroll of Darkness, Scroll of Waters
|
||||
- Added Recipes for Masterpiece Cup, Eject Pack.
|
||||
- Added Recipes for Masterpiece Cup, Eject Pack
|
||||
- Added modification to Minecraft Creative Inventory search to account for item names that contain `poké` when input contains `poke`.
|
||||
- Added Campfire Pot as well as loads of new food items (Poke Puffs, Ponigiri, Sinister Tea, etc)
|
||||
- Added Hearty Grains, a new crop used in the new cooking mechanic
|
||||
@@ -39,48 +39,21 @@
|
||||
- Pokémon with the ability Volt Absorb are immune to lightning damage and receive Regeneration II for a short duration
|
||||
- Ground type Pokémon are immune to lightning damage
|
||||
- Added functionality to Everstone when held by a Pokémon; suppresses evolution notification and hides evolve button in summary interface.
|
||||
- Added optional `filePath` parameter to MoLang functions to allow for global stores (ex. `../global/`). Path must end in a forward slash.
|
||||
- Added new optional property `attachment_options` for most EmitterShapes to be attached to the locator/entities scale, rotation, and/or position. Position is true by default.
|
||||
- Galarica Nut bushes now generate on beaches.
|
||||
- Some Pokémon now pitch their bodies in the direction they're moving.
|
||||
- Added new advancements Didn't Stop To Think, We Need To Cook, and Pokémon Jockey!.
|
||||
- Berries can now be smelted into their respective dyes.
|
||||
- Added Syrupy Apples.
|
||||
- Added `/runmolang <molang> [<npc>|<player>|<pokemon>]` command that executes a MoLang expression with the provided options as environment variables, as well as the entity (as `q.entity`) that executed the command.
|
||||
- Added bubble quirk to Kingler; like Krabby, Kingler will blows bubbles during dusk.
|
||||
- Added `.Pre` and `.Post` to the following events:
|
||||
- `PokemonRecallEvent`
|
||||
- `TradeEvent`
|
||||
- Added a new gamerule, 'healerHealsPC', when set to true a successful use of a healer will also heal all of the Pokemon in that player's PC.
|
||||
|
||||
### Pokémon Added
|
||||
|
||||
#### Gen 2
|
||||
- Marill
|
||||
- Azumarill
|
||||
- Hoppip
|
||||
- Skiploom
|
||||
- Jumpluff
|
||||
- Dunsparce
|
||||
- Togepi
|
||||
- Togetic
|
||||
- Unown
|
||||
- Houndour
|
||||
- Houndoom
|
||||
- Ho-Oh
|
||||
- Lugia
|
||||
- Alola Bias Pichu (built-in resourcepack)
|
||||
|
||||
#### Gen 3
|
||||
- Azurill
|
||||
- Meditite
|
||||
- Medicham
|
||||
- Electrike
|
||||
- Manectric
|
||||
- Spoink
|
||||
- Grumpig
|
||||
- Swablu
|
||||
- Altaria
|
||||
- Snorunt
|
||||
- Glalie
|
||||
- Latias
|
||||
@@ -94,9 +67,6 @@
|
||||
- Froslass
|
||||
- Glameow
|
||||
- Purugly
|
||||
- Skorupi
|
||||
- Drapion
|
||||
- Togekiss
|
||||
|
||||
#### Gen 5
|
||||
- Pansage
|
||||
@@ -119,60 +89,25 @@
|
||||
- Solosis
|
||||
- Duosion
|
||||
- Reuniclus
|
||||
- Tynamo
|
||||
- Eelektrik
|
||||
- Eelektross
|
||||
- Axew
|
||||
- Fraxure
|
||||
- Haxorus
|
||||
- Mienfoo
|
||||
- Mienshao
|
||||
- Sewaddle
|
||||
- Swadloon
|
||||
- Leavanny
|
||||
- Druddigon
|
||||
|
||||
#### Gen 6
|
||||
- Skiddo
|
||||
- Gogoat
|
||||
- Espurr
|
||||
- Meowstic
|
||||
- Inkay
|
||||
- Malamar
|
||||
- Hawlucha
|
||||
- Dedenne
|
||||
- Noibat
|
||||
- Noivern
|
||||
- Furfrou
|
||||
- You can change Furfrou's form by using shears on it while it holds a certain dye in its cosmetic slot.
|
||||
|
||||
#### Gen 7
|
||||
- Yungoos
|
||||
- Gumshoos
|
||||
- Drampa
|
||||
- Alolan Grimer
|
||||
- Alolan Muk
|
||||
- Togedemaru
|
||||
|
||||
#### Gen 8
|
||||
- Skwovet
|
||||
- Greedent
|
||||
- Chewtle
|
||||
- Drednaw
|
||||
- Toxel
|
||||
- Toxtricity
|
||||
- Morpeko
|
||||
- Silicobra
|
||||
- Sandaconda
|
||||
- Sinistea
|
||||
- Polteageist
|
||||
- Galarian Corsola
|
||||
- Cursola
|
||||
- Mr. Rime
|
||||
- Galarian Mr. Mime
|
||||
- Clobbopus
|
||||
- Grapploct
|
||||
- Galarian Weezing
|
||||
|
||||
#### Gen 9
|
||||
- Smoliv
|
||||
@@ -185,24 +120,13 @@
|
||||
- Cyclizar
|
||||
- Poltchageist
|
||||
- Sinistcha
|
||||
- Capsakid
|
||||
- Scovillain
|
||||
- Tadbulb
|
||||
- Bellibolt
|
||||
- Toedscool
|
||||
- Toedscruel
|
||||
- Rellor
|
||||
- Rabsca
|
||||
- Bramblin
|
||||
- Brambleghast
|
||||
|
||||
### Animation updates for the following Pokémon
|
||||
- Garchomp
|
||||
- Tropius
|
||||
- Torpius
|
||||
- Nosepass
|
||||
- Probopass
|
||||
- Sneasel
|
||||
- Weavile
|
||||
- Sneasler
|
||||
- Braixen
|
||||
- Delphox
|
||||
@@ -217,77 +141,8 @@
|
||||
- Dratini
|
||||
- Dragonair
|
||||
- Dragonite
|
||||
- G. Corsola
|
||||
- Cursola
|
||||
- Dunsparce
|
||||
- Dudunsparce (both forms)
|
||||
- Porygon
|
||||
- Porygon2
|
||||
- Porygon-Z
|
||||
- Wattrel
|
||||
- Kilowattrel
|
||||
- Golurk
|
||||
- Spinarak
|
||||
- Ariados
|
||||
- Wyrdeer
|
||||
- Tyrantrum
|
||||
- Pidove
|
||||
- Tranquill
|
||||
- Unfezant
|
||||
- Beldum
|
||||
- Metang
|
||||
- Metagross
|
||||
- Plusle
|
||||
- Minun
|
||||
- Murkrow
|
||||
- Honchkrow
|
||||
- Larvesta
|
||||
- Volcarona
|
||||
- Dwebble
|
||||
- Crustle
|
||||
- Mr. Mime
|
||||
- Flygon
|
||||
- Pichu
|
||||
- Pikachu
|
||||
- Raichu
|
||||
- Alolan Raichu
|
||||
- Espathra
|
||||
- Abra
|
||||
- Kadabra
|
||||
- Alakazam
|
||||
- Deino
|
||||
- Zweilous
|
||||
- Hydreigon
|
||||
- Slaking
|
||||
- Klink
|
||||
- Klang
|
||||
- Klinklang
|
||||
- Baltoy
|
||||
- Claydol
|
||||
- Mamoswine
|
||||
- Rufflet
|
||||
- Braviary
|
||||
- Girafarig
|
||||
- Farigiraf
|
||||
- Rookidee
|
||||
- Corvisquire
|
||||
- Corviknight
|
||||
- Venipede
|
||||
- Whirlipede
|
||||
- Scolipede
|
||||
- Venusaur
|
||||
- Parasect
|
||||
- Bastiodon
|
||||
- Amaura
|
||||
- Varoom
|
||||
- Revavroom
|
||||
- Bouffalant
|
||||
- Lickilicky
|
||||
|
||||
### Model updates for the following Pokémon
|
||||
- Cleffa
|
||||
- Clefairy
|
||||
- Clefable
|
||||
- Gyarados
|
||||
- Dragonite
|
||||
- Eevee
|
||||
@@ -333,66 +188,12 @@
|
||||
- Cacturne
|
||||
- Taillow
|
||||
- Swellow
|
||||
- Added Syrupy Apples.
|
||||
- Seel
|
||||
- Dewgong
|
||||
- Honedge
|
||||
- Doublade
|
||||
- Aegislash
|
||||
- Drowzee
|
||||
- Hypno
|
||||
- Mudkip
|
||||
- Marshtomp
|
||||
- Swampert
|
||||
- Shelmet
|
||||
- Escavalier
|
||||
- Klink
|
||||
- Klank
|
||||
- Klinklang
|
||||
- Spinarak
|
||||
- Ariados
|
||||
- Pidove
|
||||
- Tranquill
|
||||
- Unfezant
|
||||
- Sobble
|
||||
- Drizzile
|
||||
- Inteleon
|
||||
- Plusle
|
||||
- Minun
|
||||
- Murkrow
|
||||
- Zorua
|
||||
- Zoroark
|
||||
- Mime.Jr
|
||||
- Mr. Mime
|
||||
- Pichu
|
||||
- Pikachu
|
||||
- Raichu
|
||||
- Alolan Raichu
|
||||
- Dusknoir
|
||||
- Deino
|
||||
- Zweilous
|
||||
- Hydreigon
|
||||
- Dreepy
|
||||
- Drakloak
|
||||
- Dragapult
|
||||
- Mamoswine
|
||||
- Rookidee
|
||||
- Corvisquire
|
||||
- Corviknight
|
||||
- Venipede
|
||||
- Whirlipede
|
||||
- Scolipede
|
||||
- Farigiraf
|
||||
- Staryu
|
||||
- Starmie
|
||||
- Gimmighoul
|
||||
- Gholdengo
|
||||
- Starly
|
||||
- Staravia
|
||||
- Staraptor
|
||||
- Varoom
|
||||
- Revavroom
|
||||
- Nickit
|
||||
- Thievul
|
||||
|
||||
### Changes
|
||||
- Changed pokemon caught and seen count to update based on the current pokedex being looked
|
||||
@@ -448,14 +249,6 @@
|
||||
- MoLang `run_action_effect` now works on Pokémon.
|
||||
- Changed MoLang entity function `is_standing_on` to allow for block tags in the list.
|
||||
- Added entity (as `q.entity`) that executed the command to the `executemolangscript` command.
|
||||
- Refactored the following events to `.Pre` and `.Post` for consistency:
|
||||
- `PokemonSentEvent`
|
||||
- `ExperienceGainedEvent`
|
||||
- `BattleStartedEvent`
|
||||
- Updated `PokemonSentEvent` parameters to include the Position and Level of the Pokémon being sent out.
|
||||
- Updated `EvolutionCompleteEvent` parameters to include the Source Pokemon that evolved.
|
||||
- Updated `HatchEggEvent.Post` to include the Pokemon that hatched.
|
||||
- Roseli Berry Trees now naturally generate in their preferred biomes.
|
||||
|
||||
### Fixes
|
||||
- Fixed game crashing when removing national pokedex using datapacks
|
||||
@@ -499,8 +292,8 @@
|
||||
- Fix issue where locator X axis was not aligned with blockbench.
|
||||
- Fix issue where particle effects that play on frame 1 on sendout would never play (Gastly)
|
||||
- The Wiglett line will now sink in water again.
|
||||
- Fixed the Sprigatito line's portraits being zoomed in too far.
|
||||
- Fixed Floragato's battle cry animation from breaking.
|
||||
- Fixed the Sprigatito line's portraits being zoomed in too far.
|
||||
- Fixed Floragato's battle cry animation from breaking.
|
||||
- Fixed the block texture name for the Pep-Up Flower being inaccurate
|
||||
- Fixed issue where the restoration tank would not accept valid items from a hopper.
|
||||
- Fixed energy root not being shearable
|
||||
@@ -518,27 +311,13 @@
|
||||
- Improved flyers avoiding getting stuck on fence posts.
|
||||
- Fixed air balloon battle text not correctly displaying the Pokémon or item name
|
||||
- Fixed an issue where items retrieved from a Display case would disappear if a player's inventory is full
|
||||
- Fixed Pokédex Scanner not respecting the "Invert Mouse" option
|
||||
- Fixed recoil eyes on Shellder & Cloyster.
|
||||
- Fixed Shroomish spinning at lightning speed when fainting (no longer allowed to let it rip.)
|
||||
- Fixed Pokédex Scanner not respecting the "Invert Mouse" option.
|
||||
- Fixed a crash due to a ConcurrentModificationException that could occur during world generation.
|
||||
- Fixed Quaxly's animations showing hidden wing sets
|
||||
- Fixed Moon Ball moon phase logic to actually work correctly
|
||||
- Fixed `/pokedex printcalculations` to now show the correct percentage completed of the Pokedex
|
||||
- Fixed mod incompatibility with the `Raised` mod
|
||||
- Fixed a vulnerability that could cause party and PC rollbacks under specific circumstances.
|
||||
- Fixed a rare edge case where sorting your PC could be rolled back later.
|
||||
- Fixed BotanyPots built-in integration
|
||||
- Fixed shading of berries on berry trees.
|
||||
- Fixed static text cursor for nickname input in summary.
|
||||
- Fixed Cobblemon brewing recipes placing result into all slots, and not just slots with correct ingredients inside the brewing stand.
|
||||
- Fixed an issue where hoppers and brewing stands were not recognizing Cobblemon brewing recipes.
|
||||
- Fixed global species features... not working. Since they were created. Oops.
|
||||
- Fixed Pokémon with alternate forms being created with an incorrect 'forced' tag on their ability.
|
||||
- Fixed busted abilities and moves in Pokémon data due to removed datapacks etc. causing storage corruption. It now just rerolls their ability / uses Tackle.
|
||||
- Fixed singular Pokémon corruption causing entire storage corruption. Storages will now skip corrupted Pokémon and print an error to console.
|
||||
- Fixed species additions not being able to properly mark a species as implemented.
|
||||
|
||||
### Developer
|
||||
- A finished battle now has winners and losers set inside of `PokemonBattle` instead of them always being empty.
|
||||
@@ -550,8 +329,9 @@
|
||||
- Renamed Cobblemon's creative tabs to start with "Cobblemon: " to distinguish Cobblemon's tabs from tabs for other mods.
|
||||
- Various items now have a rarity value.
|
||||
- Reworked observable handling in `Pokemon.kt` to cut down on RAM usage and clarify the file.
|
||||
- Note: This will break mods that used our observable functionality there or in MoveSet, IVs, EVs, or BenchedMoves.
|
||||
- Note: This will break mods that used our observable functionality there or in MoveSet, IVs, EVs, or BenchedMoves.
|
||||
- Using `Pokemon#onChange()` is now the way to mark a Pokémon as needing a save.
|
||||
- Using `[Pokemon].changeObservable` is now the way to get an `Observable` for any save-worthy changes.
|
||||
- Updated NPCEntity beam positioning to properly account for the baseScale property.
|
||||
- Updated NPCEntity pokeball throw positioning to properly account for the baseScale property.
|
||||
- Fixed `[Pokemon].copyFrom` error causing forms, IVs, and EVs to not be applied properly when using `[Pokemon].loadFromJSON` or `[Pokemon].loadFromNBT`
|
||||
@@ -580,7 +360,7 @@
|
||||
- Added `Pokemon#hyperTrainIV()` and `IVs#setHyperTrainedIV(Stat, Int)`
|
||||
- `ElementalType` now implements `ShowdownIdentifiable` to ensure the communcation with showdown stays consistent (also in regards to TeraTypes)
|
||||
- Pokemon no longer have a change observable
|
||||
|
||||
|
||||
### MoLang & Datapacks
|
||||
- The following usages for item predicates can now use item conditions like advancements do, you can learn about them in the [Minecraft wiki](https://minecraft.wiki/w/Advancement_definition#minecraft:filled_bucket)
|
||||
- The `requiredContext` for an item interaction evolution
|
||||
@@ -632,152 +412,6 @@
|
||||
- Added `is_included`, `to_lower`, `to_upper`, and `string_length` as available Molang functions.
|
||||
- Fixed a crash that would occur during battles if the opponent wild Pokémon species comes from a namespace other than cobblemon
|
||||
- Fixed `clientActions` inside Dialogue pages being executed twice
|
||||
- Added `q.split_string(<text>, <delimiter/comma>)` Outputs an array with the divided text.
|
||||
- Added `q.spawn_npc(<x>, <y>, <z>, <npc>)` Spawns an NPC at the given coordinates and returns the NPC.
|
||||
- Added `q.player.seen_credits` Returns whether the player has seen the end credits.
|
||||
- Added `q.player.is_in_dialogue` Returns whether the player is currently in a dialogue.
|
||||
- Added `q.player.active_dialogue` Returns the active dialogue of the player, or null if none.
|
||||
- Added `q.player.is_spectator` Returns whether the player is in spectator mode.
|
||||
- Added `q.player.is_adventure` Returns whether the player is in adventure mode.
|
||||
- Added `q.player.is_creative` Returns whether the player is in creative mode.
|
||||
- Added `q.player.is_survival` Returns whether the player is in survival mode.
|
||||
- Added `q.player.set_battle_theme(<sound resource>)` Sets the player's battle theme to the given theme.
|
||||
- Added `q.player.battle_music(<sound_resource>, <volume>, <pitch>)` Plays the given battle music for the player.
|
||||
- Added `q.player.stop_battle_music()` Stops any currently playing battle music for the player. (With a fade out).
|
||||
- Added `q.player.riding_pokemon` Returns the Pokémon the player is currently riding.
|
||||
- Added `q.entity.is_player` Returns whether the entity is a player.
|
||||
- Added `q.entity.is_pokemon` Returns whether the entity is a Pokémon.
|
||||
- Added `q.entity.is_npc` Returns whether the entity is an NPC.
|
||||
- Added `q.entity.is_mob` Returns whether the entity is a vanilla mob.
|
||||
- Added `q.entity.is_animal` Returns whether the entity is an animal.
|
||||
- Added `q.entity.is_hostile` Returns whether the entity is a hostile mob.
|
||||
- Added `q.entity.is_baby` Returns whether the entity is a baby.
|
||||
- Added `q.entity.is_adult` Returns whether the entity is an adult.
|
||||
- Added `q.entity.is_tamable` Returns whether the entity is tamable.
|
||||
- Added `q.entity.is_tamed` Returns whether the entity is tamed.
|
||||
- Added `q.entity.add_effect(<effect>, <duration>, <amplifier>, <ambient> <show_particles>)` Adds a status effect to the entity.
|
||||
- Added `q.entity.remove_effect(<effect>)` Removes a status effect from the entity.
|
||||
- Added `q.entity.has_effect(<effect>)` Returns whether the entity has the given status effect.
|
||||
- Added `q.entity.is_looking_at(<entity>)` Returns whether the entity is looking at the given entity.
|
||||
- Added `q.entity.tags` Returns an array of the entity's tags.
|
||||
- Added `q.entity.add_tag(<tag>)` Adds the given tag to the entity.
|
||||
- Added `q.entity.remove_tag(<tag>)` Removes the given tag from the entity.
|
||||
- Added `q.entity.has_tag(<tag>)` Returns whether the entity has the given tag.
|
||||
- Added `q.entity.make_intangible(<true/false>)` Makes the entity intangible.
|
||||
- Added `q.pokemon.force_evolve(<index>)` Forces the Pokémon at the given index.
|
||||
- Added `q.pokemon.can_evolve` Returns whether the Pokémon at the given index can evolve.
|
||||
- Added `q.pokemon.is_busy` Returns whether the Pokémon is busy.
|
||||
- Added `q.pokemon.is_rideable` Returns whether the Pokémon is rideable.
|
||||
- Fixed `background` field and added `textColor` field for dialogues.
|
||||
|
||||
### Particles
|
||||
Added new/updated particles for the following moves:
|
||||
- Absorb
|
||||
- Acid
|
||||
- Acid Spray
|
||||
- Aerial Ace
|
||||
- Amnesia
|
||||
- Aurora Beam
|
||||
- Bite
|
||||
- Body Slam
|
||||
- Bubble
|
||||
- Bubble Beam
|
||||
- Bulldoze
|
||||
- Bullet Punch
|
||||
- Close Combat
|
||||
- Confusion
|
||||
- Crunch
|
||||
- Cotton Guard
|
||||
- Double Team
|
||||
- Dragon Claw
|
||||
- Egg Bomb
|
||||
- Ember
|
||||
- Eruption
|
||||
- Explosion
|
||||
- Fire Blast
|
||||
- Fire Punch
|
||||
- Fire Spin
|
||||
- Flame Burst
|
||||
- Flame Charge
|
||||
- Flamethrower
|
||||
- Flame Wheel
|
||||
- Frost Breath
|
||||
- Frustration
|
||||
- Giga Drain
|
||||
- Growl
|
||||
- Haze
|
||||
- Hidden Power
|
||||
- Horn Attack
|
||||
- Hyper Fang
|
||||
- Hypnosis
|
||||
- Ice Beam
|
||||
- Ice Punch
|
||||
- Ice Shard
|
||||
- Icy Wind
|
||||
- Infestation
|
||||
- Kinesis
|
||||
- Lava Plume
|
||||
- Leech Life
|
||||
- Leech Seed
|
||||
- Leer
|
||||
- Lick
|
||||
- Magical Leaf
|
||||
- Mega Drain
|
||||
- Minimize
|
||||
- Mist
|
||||
- Mud Bomb
|
||||
- MudSport
|
||||
- Mystical Fire
|
||||
- Nasty Plot
|
||||
- Poison Fang
|
||||
- Poison Gas
|
||||
- Poison Powder
|
||||
- Population Bomb
|
||||
- Pound
|
||||
- Powder
|
||||
- Powder Snow
|
||||
- Present
|
||||
- Protect
|
||||
- Psybeam
|
||||
- Psychic
|
||||
- Pursuit
|
||||
- Quick Attack
|
||||
- Rage Powder
|
||||
- Razor Leaf
|
||||
- Return
|
||||
- Rock Throw
|
||||
- Sand Attack
|
||||
- Scary Face
|
||||
- Scratch
|
||||
- Seed Bomb
|
||||
- Seismic Toss
|
||||
- Self Destruct
|
||||
- Shadow Ball
|
||||
- Shadow Claw
|
||||
- Sing
|
||||
- Sleep Powder
|
||||
- Sludge Bomb
|
||||
- Smokescreen
|
||||
- Spike
|
||||
- Spore
|
||||
- Stomp
|
||||
- String Shot
|
||||
- Stun Spore
|
||||
- Super Fang
|
||||
- Swords Dance
|
||||
- Tackle
|
||||
- Tail Whip
|
||||
- Thunder
|
||||
- Thunder Punch
|
||||
- Thunderbolt
|
||||
- Thunder Shock
|
||||
- Thunder Wave
|
||||
- Toxic
|
||||
- Water Gun
|
||||
- Water Pulse
|
||||
- Water Sport
|
||||
- Will-O-Wisp
|
||||
- Withdraw
|
||||
|
||||
## [1.6.1 (January 26th, 2025)](#1-6-1)
|
||||
|
||||
@@ -790,7 +424,7 @@ Added new/updated particles for the following moves:
|
||||
- Added optional box argument to the /pc command.
|
||||
- Pokédex and Dialogue screens now close when the inventory keybind is pressed.
|
||||
- Added config setting `maxPokedexScanningDetectionRange` to control from what distance the player can scan Pokémon using the Pokédex.
|
||||
- Added config setting `hideUnimplementedPokemonInThePokedex` which hides unimplemented Pokémon from the Pokédex when set to true.
|
||||
- Added config setting `hideUnimplementedPokemonInThePokedex` which hides unimplemented Pokémon from the Pokédex when set to true.
|
||||
- Added debug renderer for posable entity locators.
|
||||
- Added crossover paintings from Close Combat, Premonition, Altar, Slumber, and Nomad.
|
||||
- Added optional box argument to the /pc command
|
||||
@@ -944,7 +578,7 @@ Added new/updated particles for the following moves:
|
||||
- Fixed Vivichoke Dip and Leek & Potato Stew not returning a bowl upon consumption.
|
||||
- Fixed Fossil Restoration Tank not accepting Hay Bales as organic material.
|
||||
- Fixed Potion items applying double their intended healing value.
|
||||
- Fixed Fast Ball capture bonuses applying to all Pokémon, making it the Best Ball instead of the Mediocre Edge-Case Ball.
|
||||
- Fixed Fast Ball capture bonuses applying to all Pokémon, making it the Best Ball instead of the Mediocre Edge-Case Ball.
|
||||
- Fixed "learned new move" messages appearing for already-known moves on Pokémon evolutions.
|
||||
- Fixed Pokémon Item Models breaking shadows nearby when being placed in Display Cases or Item Frames.
|
||||
- Fixed berries not giving bonus yields when planted in their preferred biomes. I'm sure we've fixed that 5 times now.
|
||||
@@ -953,7 +587,7 @@ Added new/updated particles for the following moves:
|
||||
- Fixed players with shouldered Pokémon not being able to rejoin their 1.5.2 worlds using 1.6.
|
||||
- Fixed `PokemonProperties` utilizing `ability=<some ability>` being treated as a forced ability even when it is a legal ability for the Pokémon.
|
||||
- Fixed type formatting in Pokédex scanner mode when dual types require two lines.
|
||||
- Fixed trading sometimes crashing the game or server.
|
||||
- Fixed trading sometimes crashing the game or server.
|
||||
- Fixed Wild shiny sounds not respecting the `shinyNoticeParticlesDistance` config setting.
|
||||
- Fixed Pokémon being able to evolve mid-battle.
|
||||
- Fixed NPC held items being able to be stolen by players. Don't be a thief!
|
||||
@@ -1047,7 +681,7 @@ Added new/updated particles for the following moves:
|
||||
- Stonjourner Henge Ruins, Luna Henge Ruins, and Sol Henge Ruins.
|
||||
- Submerged Shipwreck Cove and Lush Shipwreck Cove.
|
||||
- Pokémon Centers to all 5 village types.
|
||||
|
||||
|
||||
### Pokémon Added
|
||||
#### Gen 1
|
||||
- Alola Bias Cubone (built-in resource pack)
|
||||
@@ -1370,7 +1004,7 @@ Added new/updated particles for the following moves:
|
||||
- Big Roots and Energy Roots now share the same sounds as intended.
|
||||
- Fixed sounds made by blocks playing at a lower pitch than intended.
|
||||
- Fixed Chimchar and Monferno comically T posing whenever they sleep.
|
||||
- Fixed Cetitan's cry breaking its walk and sleep animations.
|
||||
- Fixed Cetitan's cry breaking its walk and sleep animations.
|
||||
- Fixed the Magby line not having any placeholder walk animations.
|
||||
- Fixed Duskull and Dusclops using skylight levels for their nether spawn data. There is no sun in the Nether!
|
||||
- Fixed Hisuian Zoroark using base Zoroark stats.
|
||||
@@ -1386,7 +1020,7 @@ Added new/updated particles for the following moves:
|
||||
- Fixed Trevenant T-posing after 8 seconds of sleeping. I also do that.
|
||||
- Fixed Bewear T-posing for a bit if a wild one faints where you can see.
|
||||
- Fixed Noctowl's placeholder fly animation.
|
||||
- Corrected Lotad blinking animation.
|
||||
- Corrected Lotad blinking animation.
|
||||
- Fixed reviving items causing errors when used in battle.
|
||||
- Fixed messages for Focus Sash, Confusion, Mummy, Ice Face, Own Tempo, and Revive.
|
||||
- Improve error handling when loading spawn-sets to ensure invalid configurations don't crash the server.
|
||||
@@ -1476,7 +1110,7 @@ Added new/updated particles for the following moves:
|
||||
- Added a new universal locator called "top".
|
||||
- Added `eggs_collected` and `eggs_hatched` Advancement triggers.
|
||||
- Added missing `minYaw` configuration to the `q.look()` function for JSON posers.
|
||||
- Some pose condition names have been changed:
|
||||
- Some pose condition names have been changed:
|
||||
- `isTouchingWaterOrRain` has been changed to `isInWaterOrRain`
|
||||
- `isSubermegedInWater` has been changed to `isUnderWater`
|
||||
|
||||
|
||||
@@ -94,4 +94,4 @@ sourceSets {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,62 +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.mixin;
|
||||
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
import net.minecraft.world.InteractionResultHolder;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.EnderpearlItem;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.phys.AABB;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
import java.util.Comparator;
|
||||
|
||||
@Mixin(EnderpearlItem.class)
|
||||
public abstract class EnderPearlItemMixin {
|
||||
@Inject(method = "use", at = @At(value = "HEAD"), cancellable = true)
|
||||
private void cobblemon$use(Level level, Player player, InteractionHand usedHand, CallbackInfoReturnable<InteractionResultHolder<ItemStack>> cir) {
|
||||
double range = player.entityInteractionRange();
|
||||
Entity closestEntity = level.getEntities(player, AABB.ofSize(player.position(), range, range, range)).stream()
|
||||
.filter(entity -> isLookingAt(player, entity))
|
||||
.min(Comparator.comparingDouble(entity -> entity.distanceTo(player)))
|
||||
.orElse(null);
|
||||
|
||||
if (closestEntity instanceof PokemonEntity pokemonEntity) {
|
||||
if (player.isCrouching() && pokemonEntity.getOwnerUUID() == player.getUUID()) {
|
||||
cir.cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isLookingAt(Player player, Entity other) {
|
||||
float maxDistance = 10F;
|
||||
float stepDistance = 0.1F;
|
||||
double step = stepDistance;
|
||||
Vec3 startPos = player.getEyePosition();
|
||||
Vec3 direction = player.getLookAngle();
|
||||
|
||||
while (step <= maxDistance) {
|
||||
Vec3 location = startPos.add(direction.scale(step));
|
||||
step += stepDistance;
|
||||
|
||||
if (other.getBoundingBox().contains(location)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1,62 +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.mixin;
|
||||
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity;
|
||||
import com.cobblemon.mod.common.pokemon.ai.EntityBehaviour;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.entity.Mob;
|
||||
import net.minecraft.world.entity.ai.goal.AvoidEntityGoal;
|
||||
import net.minecraft.world.entity.animal.Fox;
|
||||
import net.minecraft.world.entity.monster.Creeper;
|
||||
import net.minecraft.world.level.Level;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
@Mixin(Fox.class)
|
||||
public class EntityFoxMixin extends Mob {
|
||||
|
||||
private EntityFoxMixin(net.minecraft.world.entity.EntityType<? extends Creeper> entityType, Level world) {
|
||||
super(entityType, world);
|
||||
}
|
||||
|
||||
@Inject(method = "registerGoals", at = @At(value = "TAIL"), cancellable = false)
|
||||
private void cobblemon$initGoals(CallbackInfo callbackInfo) {
|
||||
final Fox fox = (Fox) (Object) this;
|
||||
// Pokemon Entities
|
||||
this.goalSelector.addGoal(
|
||||
4,
|
||||
new AvoidEntityGoal<>(
|
||||
fox,
|
||||
PokemonEntity.class,
|
||||
8.0f,
|
||||
1.6,
|
||||
1.4,
|
||||
entity -> ((PokemonEntity)entity).getBehaviour().getEntityInteract().getAvoidedByFox() && ((PokemonEntity)entity).getBeamMode() != 1
|
||||
)
|
||||
);
|
||||
|
||||
// Players with shoulder mounted Pokemon
|
||||
this.goalSelector.addGoal(
|
||||
3,
|
||||
new AvoidEntityGoal<>(
|
||||
fox,
|
||||
ServerPlayer.class,
|
||||
8.0f,
|
||||
1.6,
|
||||
1.4,
|
||||
entity -> EntityBehaviour.Companion.hasFoxFearedShoulderMount((ServerPlayer)entity)
|
||||
)
|
||||
);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,9 +58,11 @@ public abstract class LivingEntityMixin extends Entity implements OrientationCon
|
||||
@Override
|
||||
public @NotNull HitResult pick(double hitDistance, float partialTicks, boolean hitFluids) {
|
||||
Entity vehicle = this.getVehicle();
|
||||
if (vehicle instanceof PokemonEntity pokemonEntity && pokemonEntity.getDelegate() instanceof PokemonClientDelegate delegate) {
|
||||
if (vehicle instanceof PokemonEntity pokemonEntity) {
|
||||
int seatIndex = pokemonEntity.getPassengers().indexOf(this);
|
||||
Seat seat = pokemonEntity.getSeats().get(seatIndex);
|
||||
|
||||
PokemonClientDelegate delegate = (PokemonClientDelegate) pokemonEntity.getDelegate();
|
||||
MatrixWrapper locator = delegate.getLocatorStates().get(seat.getLocator());
|
||||
|
||||
Vec3 locatorOffset = new Vec3(locator.getMatrix().getTranslation(new Vector3f()));
|
||||
|
||||
@@ -1,28 +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.mixin;
|
||||
|
||||
import com.bedrockk.molang.runtime.value.DoubleValue;
|
||||
import com.cobblemon.mod.common.entity.MoLangScriptingEntity;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.level.block.PowderSnowBlock;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
@Mixin(PowderSnowBlock.class)
|
||||
public abstract class PowderSnowBlockMixin {
|
||||
@Inject(method = "canEntityWalkOnPowderSnow", at = @At(value = "RETURN"), cancellable = true)
|
||||
private static void cobblemon$canEntityWalkOnPowderSnow(Entity entity, CallbackInfoReturnable<Boolean> ci) {
|
||||
if (ci.getReturnValue() == false && entity instanceof MoLangScriptingEntity) {
|
||||
ci.setReturnValue(((MoLangScriptingEntity) entity).getConfig().getMap().getOrDefault("can_stand_on_powder_snow", DoubleValue.ZERO).asDouble() == 1.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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.mixin;
|
||||
|
||||
import com.bedrockk.molang.runtime.value.DoubleValue;
|
||||
import com.cobblemon.mod.common.entity.MoLangScriptingEntity;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.SweetBerryBushBlock;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
|
||||
@Mixin(SweetBerryBushBlock.class)
|
||||
public abstract class SweetBerryBushBlockMixin {
|
||||
|
||||
@Inject(method = "entityInside", at = @At(value = "HEAD"), cancellable = true)
|
||||
private void cobblemon$entityInside(BlockState state, Level level, BlockPos pos, Entity entity, CallbackInfo callbackInfo) {
|
||||
if (entity instanceof MoLangScriptingEntity) {
|
||||
if (((MoLangScriptingEntity) entity).getConfig().getMap().getOrDefault("immune_to_sweet_berry_bush_block", DoubleValue.ZERO).asDouble() == 1.0) {
|
||||
callbackInfo.cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -25,9 +25,9 @@ public class TargetingConditionsMixin {
|
||||
@Inject(method = "test", at = @At("HEAD"), cancellable = true)
|
||||
public void test(@Nullable LivingEntity baseEntity, LivingEntity targetEntity, CallbackInfoReturnable<Boolean> ci) {
|
||||
if (targetEntity instanceof ServerPlayer player) {
|
||||
if (player.level().getGameRules().getBoolean(CobblemonGameRules.MOB_TARGET_IN_BATTLE)) return;
|
||||
boolean canTargetInBattle = player.level().getGameRules().getBoolean(CobblemonGameRules.MOB_TARGET_IN_BATTLE);
|
||||
boolean targetInBattle = Cobblemon.INSTANCE.getBattleRegistry().getBattleByParticipatingPlayer(player) != null;
|
||||
if (targetInBattle) ci.setReturnValue(false);
|
||||
if (!canTargetInBattle && targetInBattle) ci.setReturnValue(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-38
@@ -15,11 +15,9 @@ import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
|
||||
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
|
||||
import com.llamalad7.mixinextras.sugar.Local;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.core.NonNullList;
|
||||
import net.minecraft.world.Containers;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.Items;
|
||||
import net.minecraft.world.item.alchemy.PotionBrewing;
|
||||
import net.minecraft.world.item.crafting.RecipeHolder;
|
||||
import net.minecraft.world.item.crafting.RecipeManager;
|
||||
@@ -29,8 +27,6 @@ import net.minecraft.world.level.block.entity.BrewingStandBlockEntity;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
@@ -47,9 +43,7 @@ public class BrewingStandBlockEntityMixin {
|
||||
//copied from vanilla doBrew logic, but slightly tweaked to work for cobblemon, this was needed as replacing the loop was not quite possible inside doBrew
|
||||
ItemStack itemStack = slots.get(3);
|
||||
for(int i = 0; i < 3; ++i) {
|
||||
if (!slots.get(i).isEmpty()){
|
||||
slots.set(i, recipe.getResult().copy());
|
||||
}
|
||||
slots.set(i, recipe.getResult().copy());
|
||||
}
|
||||
|
||||
itemStack.shrink(1);
|
||||
@@ -97,35 +91,4 @@ public class BrewingStandBlockEntityMixin {
|
||||
|
||||
return recipeHolder.map(RecipeHolder::value).orElse(null);
|
||||
}
|
||||
|
||||
@Inject(method = "canPlaceItem", at = @At("HEAD"), cancellable = true)
|
||||
private void cobblemon$canPlaceItem(int slot, ItemStack stack, CallbackInfoReturnable<Boolean> cir) {
|
||||
if (stack == null || stack.isEmpty()) return;
|
||||
|
||||
BrewingStandBlockEntity self = (BrewingStandBlockEntity) (Object) this;
|
||||
Level level = self.getLevel();
|
||||
|
||||
if (level != null) {
|
||||
|
||||
var rm = level.getRecipeManager();
|
||||
|
||||
//Input slot
|
||||
if (slot == 3) {
|
||||
if (BrewingStandRecipe.Companion.isInput(stack, rm)) {
|
||||
cir.setReturnValue(true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Output slots
|
||||
if (slot >= 0 && slot < 3) {
|
||||
if (BrewingStandRecipe.Companion.isBottle(stack, rm)) {
|
||||
if (self.getItem(slot).isEmpty()) {
|
||||
cir.setReturnValue(true);
|
||||
} else {
|
||||
cir.setReturnValue(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -55,7 +55,7 @@ public abstract class CameraMixin {
|
||||
@Inject(method = "setRotation", at = @At("HEAD"), cancellable = true)
|
||||
|
||||
public void cobblemon$setRotation(float f, float g, CallbackInfo ci) {
|
||||
if (!(this.entity instanceof OrientationControllable controllable)) return;
|
||||
if (!(this.entity instanceof OrientationControllable controllable) || Cobblemon.config.getDisableRoll()) return;
|
||||
var controller = controllable.getOrientationController();
|
||||
if (!controller.isActive() && controller.getOrientation() != null) {
|
||||
if(this.returnTimer < 1) {
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
|
||||
package com.cobblemon.mod.common.mixin.client;
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon;
|
||||
import com.cobblemon.mod.common.OrientationControllable;
|
||||
import com.cobblemon.mod.common.client.CobblemonClient;
|
||||
import com.cobblemon.mod.common.client.keybind.keybinds.PartySendBinding;
|
||||
@@ -130,11 +129,6 @@ public abstract class MouseHandlerMixin {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Clamp player rotation if riding and the vehicle demands it
|
||||
if (player.isPassenger() && player.getVehicle() instanceof PokemonEntity vehicle) {
|
||||
vehicle.clampPassengerRotation(player);
|
||||
}
|
||||
|
||||
if (!(player instanceof OrientationControllable controllable)) return true;
|
||||
|
||||
if (!controllable.getOrientationController().isActive()) {
|
||||
@@ -216,18 +210,6 @@ public abstract class MouseHandlerMixin {
|
||||
if (vehicle == null) return Vec3.ZERO;
|
||||
if (!(vehicle instanceof PokemonEntity pokemonEntity)) return Vec3.ZERO;
|
||||
|
||||
var invertYaw = Cobblemon.config.getInvertYaw();
|
||||
var invertPitch = Cobblemon.config.getInvertPitch();
|
||||
|
||||
var xValue = mouseX * Cobblemon.config.getXAxisSensitivity();
|
||||
var yValue = mouseY * Cobblemon.config.getYAxisSensitivity();
|
||||
|
||||
var swapXAndY = Cobblemon.config.getSwapXAndYAxes();
|
||||
|
||||
var yaw = (swapXAndY ? yValue : xValue) * (invertYaw? -1.0f : 1.0f);
|
||||
|
||||
var pitch = (swapXAndY ? xValue : yValue) * (invertPitch? -1.0f : 1.0f);
|
||||
|
||||
var sensitivity = cobblemon$getRidingSensitivity();
|
||||
return pokemonEntity.ifRidingAvailableSupply(Vec3.ZERO, (behaviour, settings, state) -> {
|
||||
return behaviour.rotationOnMouseXY(
|
||||
@@ -235,8 +217,8 @@ public abstract class MouseHandlerMixin {
|
||||
state,
|
||||
pokemonEntity,
|
||||
player,
|
||||
pitch,
|
||||
yaw,
|
||||
mouseY,
|
||||
mouseX,
|
||||
yMouseSmoother,
|
||||
xMouseSmoother,
|
||||
sensitivity,
|
||||
|
||||
@@ -9,18 +9,12 @@
|
||||
package com.cobblemon.mod.common.mixin.entity;
|
||||
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity;
|
||||
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
|
||||
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.level.Level;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
@Mixin(Entity.class)
|
||||
@@ -35,27 +29,4 @@ public abstract class EntityMixin {
|
||||
}
|
||||
}
|
||||
|
||||
@WrapOperation(
|
||||
method = "collide(Lnet/minecraft/world/phys/Vec3;)Lnet/minecraft/world/phys/Vec3;",
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "Lnet/minecraft/world/entity/Entity;onGround()Z"
|
||||
)
|
||||
)
|
||||
public boolean cobblemon$forceOnGroundForStepUp(Entity entity, Operation<Boolean> original) {
|
||||
if (entity instanceof PokemonEntity && entity.hasControllingPassenger()) {
|
||||
BlockPos below = entity.blockPosition().below();
|
||||
Level level = entity.level();
|
||||
var blockStateBelow = level.getBlockState(below);
|
||||
boolean isAirOrLiquid = blockStateBelow.isAir() || !blockStateBelow.getFluidState().isEmpty();
|
||||
boolean canSupportEntity = blockStateBelow.isFaceSturdy(level, below, Direction.UP);
|
||||
boolean standingOnSolid = canSupportEntity && !isAirOrLiquid;
|
||||
if (standingOnSolid) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return original.call(entity);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -76,7 +76,7 @@ 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.EntityCallbackHandler
|
||||
import com.cobblemon.mod.common.events.CallbackHandler
|
||||
import com.cobblemon.mod.common.events.FlowHandler
|
||||
import com.cobblemon.mod.common.events.PokedexHandler
|
||||
import com.cobblemon.mod.common.events.ServerTickHandler
|
||||
import com.cobblemon.mod.common.net.messages.client.settings.ServerSettingsPacket
|
||||
@@ -313,7 +313,7 @@ object Cobblemon {
|
||||
|
||||
CobblemonEvents.POKEMON_PROPERTY_INITIALISED.emit(Unit)
|
||||
|
||||
CallbackHandler.setup()
|
||||
FlowHandler.setup()
|
||||
EntityCallbackHandler.setup()
|
||||
|
||||
ifDedicatedServer {
|
||||
|
||||
@@ -128,7 +128,7 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
|
||||
@JvmField
|
||||
val APRICORN_FENCE = this.create("apricorn_fence", FenceBlock(BlockBehaviour.Properties.of().mapColor(APRICORN_PLANKS.defaultMapColor()).instrument(NoteBlockInstrument.BASS).strength(2.0f, 3.0f).sound(SoundType.WOOD)))
|
||||
@JvmField
|
||||
val APRICORN_FENCE_GATE = this.create("apricorn_fence_gate", FenceGateBlock(APRICORN_WOOD_TYPE, BlockBehaviour.Properties.of().mapColor(APRICORN_PLANKS.defaultMapColor()).strength(2.0f, 3.0f).sound(SoundType.WOOD).ignitedByLava().forceSolidOn()))
|
||||
val APRICORN_FENCE_GATE = this.create("apricorn_fence_gate", FenceGateBlock(APRICORN_WOOD_TYPE, BlockBehaviour.Properties.of().mapColor(APRICORN_PLANKS.defaultMapColor()).strength(2.0f, 3.0f).sound(SoundType.WOOD)))
|
||||
@JvmField
|
||||
val APRICORN_BUTTON = this.create("apricorn_button", BlocksInvoker.createWoodenButtonBlock(APRICORN_BLOCK_SET_TYPE))
|
||||
@JvmField
|
||||
@@ -205,7 +205,7 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
|
||||
@JvmField
|
||||
val SACCHARINE_FENCE = this.create("saccharine_fence", FenceBlock(BlockBehaviour.Properties.of().mapColor(SACCHARINE_PLANKS.defaultMapColor()).instrument(NoteBlockInstrument.BASS).strength(2.0f, 3.0f).sound(SoundType.WOOD)))
|
||||
@JvmField
|
||||
val SACCHARINE_FENCE_GATE = this.create("saccharine_fence_gate", FenceGateBlock(SACCHARINE_WOOD_TYPE, BlockBehaviour.Properties.of().mapColor(SACCHARINE_PLANKS.defaultMapColor()).instrument(NoteBlockInstrument.BASS).strength(2.0f, 3.0f).sound(SoundType.WOOD).ignitedByLava().forceSolidOn()))
|
||||
val SACCHARINE_FENCE_GATE = this.create("saccharine_fence_gate", FenceGateBlock(SACCHARINE_WOOD_TYPE, BlockBehaviour.Properties.of().mapColor(SACCHARINE_PLANKS.defaultMapColor()).instrument(NoteBlockInstrument.BASS).strength(2.0f, 3.0f).sound(SoundType.WOOD)))
|
||||
@JvmField
|
||||
val SACCHARINE_BUTTON = this.create("saccharine_button", BlocksInvoker.createWoodenButtonBlock(BlockSetType.OAK))
|
||||
@JvmField
|
||||
|
||||
@@ -71,6 +71,7 @@ object CobblemonCommands {
|
||||
MarkGiveAllCommand.register(dispatcher)
|
||||
PcSearchCommand.register(dispatcher)
|
||||
PcTakeCommand.register(dispatcher)
|
||||
ValidateTeamCommand.register(dispatcher)
|
||||
|
||||
// Possibly lock down registration if and only if under dev environment or running in an environment
|
||||
// with a certain system environment variable set
|
||||
|
||||
+35
-41
@@ -18,78 +18,72 @@ 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.net.messages.client.data.CallbackRegistrySyncPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.data.FlowRegistrySyncPacket
|
||||
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 java.util.function.Predicate
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.server.packs.PackType
|
||||
import net.minecraft.server.packs.resources.ResourceManager
|
||||
|
||||
/**
|
||||
* Holds all the callbacks that are loaded from the server's data packs. A callback is foldered under the event 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 CobblemonCallbacks : DataRegistry {
|
||||
override val id = cobblemonResource("callbacks")
|
||||
override val observable = SimpleObservable<CobblemonCallbacks>()
|
||||
object CobblemonFlows : DataRegistry {
|
||||
override val id = cobblemonResource("flows")
|
||||
override val observable = SimpleObservable<CobblemonFlows>()
|
||||
override val type = PackType.SERVER_DATA
|
||||
override fun sync(player: ServerPlayer) {
|
||||
player.sendPacket(CallbackRegistrySyncPacket(clientCallbacks.entries))
|
||||
player.sendPacket(FlowRegistrySyncPacket(clientFlows.entries))
|
||||
}
|
||||
|
||||
val runtime by lazy { MoLangRuntime().setup() } // Lazy for if someone adds to generalFunctions in MoLangFunctions
|
||||
|
||||
val clientCallbacks = hashMapOf<ResourceLocation, MutableList<ExpressionLike>>()
|
||||
val callbacks = hashMapOf<ResourceLocation, MutableList<ExpressionLike>>()
|
||||
|
||||
val clientFlows = hashMapOf<ResourceLocation, MutableList<ExpressionLike>>()
|
||||
val flows = hashMapOf<ResourceLocation, MutableList<ExpressionLike>>()
|
||||
|
||||
override fun reload(manager: ResourceManager) {
|
||||
clientCallbacks.clear()
|
||||
callbacks.clear()
|
||||
clientFlows.clear()
|
||||
flows.clear()
|
||||
|
||||
val unsortedCallbacks = mutableMapOf<ResourceLocation, MutableList<Pair<String, ExpressionLike>>>()
|
||||
val unsortedFlows = mutableMapOf<ResourceLocation, MutableList<Pair<String, ExpressionLike>>>()
|
||||
val folderBeforeNameRegex = ".*\\/([^\\/]+)\\/[^\\/]+\$".toRegex()
|
||||
val predicate: Predicate<ResourceLocation> = Predicate { path -> path.endsWith(CobblemonScripts.MOLANG_EXTENSION) }
|
||||
manager.listResources("flows") { path -> path.endsWith(CobblemonScripts.MOLANG_EXTENSION) }.forEach { (identifier, resource) ->
|
||||
resource.openAsReader().use { stream ->
|
||||
stream.buffered().use { reader ->
|
||||
try {
|
||||
val expression = reader.readText().asExpressionLike()
|
||||
|
||||
manager.listResources("callbacks", predicate)
|
||||
.plus(manager.listResources("flows", predicate)) // old name
|
||||
.forEach { (identifier, resource) ->
|
||||
resource.openAsReader().use { stream ->
|
||||
stream.buffered().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.")
|
||||
|
||||
val event = folderBeforeNameRegex.find(identifier.path)?.groupValues?.get(1)
|
||||
?: throw IllegalArgumentException("Invalid callback path: $identifier. Should have a folder structure that includes the name of the event to callback.")
|
||||
|
||||
val callbackKey = ResourceLocation.fromNamespaceAndPath(identifier.namespace, event)
|
||||
unsortedCallbacks.putIfAbsent(callbackKey, mutableListOf())
|
||||
unsortedCallbacks[callbackKey]!!.add(identifier.path to expression)
|
||||
} catch (exception: Exception) {
|
||||
throw ExecutionException("Error loading MoLang script for callback: $identifier", exception)
|
||||
}
|
||||
val flowKey = ResourceLocation.fromNamespaceAndPath(identifier.namespace, event)
|
||||
unsortedFlows.putIfAbsent(flowKey, mutableListOf())
|
||||
unsortedFlows[flowKey]!!.add(identifier.path to expression)
|
||||
} catch (exception: Exception) {
|
||||
throw ExecutionException("Error loading MoLang script for flow: $identifier", exception)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsortedCallbacks.forEach { (key, value) ->
|
||||
value.sortBy { it.first }
|
||||
if (key.path.startsWith("flows/client/") || key.path.startsWith("callbacks/client/")) {
|
||||
clientCallbacks.getOrPut(key) { mutableListOf() }.addAll(value.map { it.second })
|
||||
} else {
|
||||
callbacks.getOrPut(key) { mutableListOf() }.addAll(value.map { it.second })
|
||||
}
|
||||
}
|
||||
|
||||
Cobblemon.LOGGER.info("Loaded ${callbacks.size} callbacks and ${clientCallbacks.size} client callbacks")
|
||||
unsortedFlows.forEach { (key, value) ->
|
||||
value.sortBy { it.first }
|
||||
if (key.path.startsWith("flows/client/")) {
|
||||
clientFlows.getOrPut(key) { mutableListOf() }.addAll(value.map { it.second })
|
||||
} else {
|
||||
flows.getOrPut(key) { mutableListOf() }.addAll(value.map { it.second })
|
||||
}
|
||||
}
|
||||
|
||||
Cobblemon.LOGGER.info("Loaded ${flows.size} flows and ${clientFlows.size} client flows")
|
||||
observable.emit(this)
|
||||
}
|
||||
|
||||
@@ -99,7 +93,7 @@ object CobblemonCallbacks : DataRegistry {
|
||||
functions: Map<String, (MoParams) -> Any> = emptyMap(),
|
||||
cancelable: Cancelable? = null
|
||||
) {
|
||||
if (eventResourceLocation !in callbacks) return
|
||||
if (eventResourceLocation !in flows) return
|
||||
|
||||
if (cancelable == null) {
|
||||
runtime.environment.query.functions.remove("cancel")
|
||||
@@ -112,7 +106,7 @@ object CobblemonCallbacks : DataRegistry {
|
||||
|
||||
functions.forEach { (name, function) -> runtime.environment.query.addFunction(name, function) }
|
||||
|
||||
callbacks[eventResourceLocation]?.forEach {
|
||||
flows[eventResourceLocation]?.forEach {
|
||||
if (cancelable != null && cancelable.isCanceled) {
|
||||
return
|
||||
}
|
||||
@@ -22,7 +22,6 @@ import com.cobblemon.mod.common.block.BerryBlock
|
||||
import com.cobblemon.mod.common.block.MintBlock
|
||||
import com.cobblemon.mod.common.block.MintBlock.MintType
|
||||
import com.cobblemon.mod.common.client.pokedex.PokedexType
|
||||
import com.cobblemon.mod.common.block.campfirepot.CampfirePotColor
|
||||
import com.cobblemon.mod.common.entity.boat.CobblemonBoatType
|
||||
import com.cobblemon.mod.common.item.*
|
||||
import com.cobblemon.mod.common.item.armor.CobblemonArmorTrims
|
||||
@@ -193,19 +192,19 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
|
||||
val campfire_pots = mutableListOf<CampfirePotItem>()
|
||||
@JvmField
|
||||
val CAMPFIRE_POT_RED = campfirePotItem(CobblemonBlocks.RED_CAMPFIRE_POT, CampfirePotColor.RED)
|
||||
val CAMPFIRE_POT_RED = campfirePotItem(CobblemonBlocks.RED_CAMPFIRE_POT, "red")
|
||||
@JvmField
|
||||
val CAMPFIRE_POT_YELLOW = campfirePotItem(CobblemonBlocks.YELLOW_CAMPFIRE_POT, CampfirePotColor.YELLOW)
|
||||
val CAMPFIRE_POT_YELLOW = campfirePotItem(CobblemonBlocks.YELLOW_CAMPFIRE_POT, "yellow")
|
||||
@JvmField
|
||||
val CAMPFIRE_POT_GREEN = campfirePotItem(CobblemonBlocks.GREEN_CAMPFIRE_POT, CampfirePotColor.GREEN)
|
||||
val CAMPFIRE_POT_GREEN = campfirePotItem(CobblemonBlocks.GREEN_CAMPFIRE_POT, "green")
|
||||
@JvmField
|
||||
val CAMPFIRE_POT_BLUE = campfirePotItem(CobblemonBlocks.BLUE_CAMPFIRE_POT, CampfirePotColor.BLUE)
|
||||
val CAMPFIRE_POT_BLUE = campfirePotItem(CobblemonBlocks.BLUE_CAMPFIRE_POT, "blue")
|
||||
@JvmField
|
||||
val CAMPFIRE_POT_PINK = campfirePotItem(CobblemonBlocks.PINK_CAMPFIRE_POT, CampfirePotColor.PINK)
|
||||
val CAMPFIRE_POT_PINK = campfirePotItem(CobblemonBlocks.PINK_CAMPFIRE_POT, "pink")
|
||||
@JvmField
|
||||
val CAMPFIRE_POT_BLACK = campfirePotItem(CobblemonBlocks.BLACK_CAMPFIRE_POT, CampfirePotColor.BLACK)
|
||||
val CAMPFIRE_POT_BLACK = campfirePotItem(CobblemonBlocks.BLACK_CAMPFIRE_POT, "black")
|
||||
@JvmField
|
||||
val CAMPFIRE_POT_WHITE = campfirePotItem(CobblemonBlocks.WHITE_CAMPFIRE_POT, CampfirePotColor.WHITE)
|
||||
val CAMPFIRE_POT_WHITE = campfirePotItem(CobblemonBlocks.WHITE_CAMPFIRE_POT, "white")
|
||||
|
||||
@JvmField
|
||||
val HEARTY_GRAINS = compostableItem("hearty_grains", ItemNameBlockItem(CobblemonBlocks.HEARTY_GRAINS, Properties().rarity(Rarity.COMMON)))
|
||||
@@ -401,7 +400,7 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
@JvmField
|
||||
val OLD_GATEAU = regionalFoodItem("old_gateau", 64, 9, 0.1335f, false)
|
||||
@JvmField
|
||||
val CASTELIACONE = regionalFoodItem("casteliacone", 64, 5, 0.28f, false)
|
||||
val CASTELIACONE = regionalFoodItem("casteliacone", 64, 5, .28f, false)
|
||||
@JvmField
|
||||
val LUMIOSE_GALETTE = regionalFoodItem("lumiose_galette", 64, 4, 0.4f, false)
|
||||
@JvmField
|
||||
@@ -696,7 +695,7 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
@JvmField
|
||||
val SUPERB_REMEDY = compostableItem("superb_remedy", RemedyItem(RemedyItem.SUPERB), 0.85f)
|
||||
@JvmField
|
||||
val MOOMOO_MILK = create("moomoo_milk", CobblemonItem(Item.Properties().craftRemainder(Items.GLASS_BOTTLE).stacksTo((16))))
|
||||
val MOOMOO_MILK = create("moomoo_milk", CobblemonItem(Item.Properties().craftRemainder(Items.GLASS_BOTTLE)))
|
||||
|
||||
@JvmField
|
||||
val POTION = create("potion", PotionItem(PotionType.POTION))
|
||||
@@ -1501,8 +1500,8 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
}
|
||||
)
|
||||
|
||||
private fun campfirePotItem(block: Block, color: CampfirePotColor): CampfirePotItem {
|
||||
val item = create("campfire_pot_${color.suffix}", CampfirePotItem(block, color))
|
||||
private fun campfirePotItem(block: Block, type: String): CampfirePotItem {
|
||||
val item = create("campfire_pot_${type}", CampfirePotItem(block))
|
||||
campfire_pots.add(item)
|
||||
return item
|
||||
}
|
||||
@@ -1649,4 +1648,4 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
private fun foodItem(nutrition: Int, saturationModifier: Float): Item {
|
||||
return CobblemonItem(Item.Properties().food(FoodProperties.Builder().nutrition(nutrition).saturationModifier(saturationModifier).build()))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,7 +9,6 @@
|
||||
package com.cobblemon.mod.common
|
||||
|
||||
import com.cobblemon.mod.common.api.ai.CobblemonAttackTargetData
|
||||
import com.cobblemon.mod.common.api.ai.CobblemonAvoidTargetData
|
||||
import com.cobblemon.mod.common.api.ai.CobblemonWanderControl
|
||||
import com.cobblemon.mod.common.api.dialogue.ActiveDialogue
|
||||
import com.cobblemon.mod.common.api.moves.animations.ActionEffectContext
|
||||
@@ -44,10 +43,6 @@ object CobblemonMemories {
|
||||
val TARGETED_BATTLE_POKEMON = register<UUID>("targeted_battle_pokemon")
|
||||
val NEAREST_VISIBLE_ATTACKER = register<LivingEntity>("nearest_visible_attacker")
|
||||
val NEARBY_GROWABLE_CROPS = register<BlockPos>("nearby_growable_crops")
|
||||
val NEARBY_SWEET_BERRY_BUSH = register<BlockPos>("nearest_sweet_berry_bush")
|
||||
val DISABLE_WALK_TO_BERRY_BUSH = register<Boolean>("disable_walk_to_berry_bush")
|
||||
val TIME_TRYING_TO_REACH_BERRY_BUSH = register<Int>("time_trying_to_reach_berry_bush")
|
||||
val IS_CONSUMING_ITEM = register<Boolean>("is_consuming_item")
|
||||
val RECENTLY_ATE_GRASS = register<Boolean>("recently_ate_grass")
|
||||
val HIVE_LOCATION = register<BlockPos>("hive_location")
|
||||
val HIVE_COOLDOWN = register<Boolean>("hive_cooldown")
|
||||
@@ -58,11 +53,7 @@ object CobblemonMemories {
|
||||
/** how many are following me rn? */
|
||||
val HERD_SIZE = register<Int>("herd_size") // Don't bother saving it, we'll try to keep count roughly.
|
||||
val ATTACK_TARGET_DATA = register<CobblemonAttackTargetData>("attack_target_data") // This is used to store additional information about the attack target, such as when to give up pursuit.
|
||||
val AVOID_TARGET_DATA = register<CobblemonAvoidTargetData>("avoid_target_data") // This is used to store additional information about the avoid target, such as how fast to move.
|
||||
val WANDER_CONTROL = register<CobblemonWanderControl>("wander_control")
|
||||
val DISABLE_WALK_TO_WANTED_ITEM = register<Boolean>("disable_walk_to_wanted_item")
|
||||
val TIME_TRYING_TO_REACH_WANTED_ITEM = register<Int>("time_trying_to_wanted_item")
|
||||
val RECENT_CATCH_ATTEMPT = register<UUID>("recent_catch_attempt")
|
||||
|
||||
fun <U> register(id: String, codec: Codec<U>): MemoryModuleType<U> {
|
||||
val memoryModule = MemoryModuleType(Optional.of(codec))
|
||||
|
||||
@@ -157,7 +157,6 @@ import com.cobblemon.mod.common.net.messages.server.callback.party.PartyPokemonS
|
||||
import com.cobblemon.mod.common.net.messages.server.callback.party.PartySelectCancelledPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.callback.partymove.PartyMoveSelectCancelledPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.callback.partymove.PartyPokemonMoveSelectedPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.debug.ServerboundUpdateRidingSettingsPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.debug.ServerboundUpdateRidingStatRangePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.debug.ServerboundUpdateRidingStatsPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.dialogue.EscapeDialoguePacket
|
||||
@@ -209,7 +208,6 @@ import com.cobblemon.mod.common.net.serverhandling.callback.party.PartyPokemonSe
|
||||
import com.cobblemon.mod.common.net.serverhandling.callback.party.PartySelectCancelledHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.callback.partymove.PartyMoveSelectCancelledHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.callback.partymove.PartyPokemonMoveSelectedHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.debug.ServerboundUpdateRidingSettingsHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.debug.ServerboundUpdateRidingStatRangeHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.debug.ServerboundUpdateRidingStatsHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.dialogue.EscapeDialogueHandler
|
||||
@@ -403,7 +401,7 @@ object CobblemonNetwork {
|
||||
list.add(PacketRegisterInfo(DexEntrySyncPacket.ID, DexEntrySyncPacket::decode, DataRegistrySyncPacketHandler()))
|
||||
list.add(PacketRegisterInfo(SpawnBaitRegistrySyncPacket.ID, SpawnBaitRegistrySyncPacket::decode, DataRegistrySyncPacketHandler()))
|
||||
list.add(PacketRegisterInfo(SeasoningRegistrySyncPacket.ID, SeasoningRegistrySyncPacket::decode, DataRegistrySyncPacketHandler()))
|
||||
list.add(PacketRegisterInfo(CallbackRegistrySyncPacket.ID, CallbackRegistrySyncPacket::decode, DataRegistrySyncPacketHandler()))
|
||||
list.add(PacketRegisterInfo(FlowRegistrySyncPacket.ID, FlowRegistrySyncPacket::decode, DataRegistrySyncPacketHandler()))
|
||||
list.add(PacketRegisterInfo(CosmeticItemAssignmentSyncPacket.ID, CosmeticItemAssignmentSyncPacket::decode, DataRegistrySyncPacketHandler()))
|
||||
list.add(PacketRegisterInfo(BehaviourSyncPacket.ID, BehaviourSyncPacket::decode, DataRegistrySyncPacketHandler()))
|
||||
list.add(PacketRegisterInfo(MarkRegistrySyncPacket.ID, MarkRegistrySyncPacket::decode, DataRegistrySyncPacketHandler()))
|
||||
@@ -580,7 +578,6 @@ object CobblemonNetwork {
|
||||
list.add(PacketRegisterInfo(ServerboundUpdateRidingStatePacket.ID, ServerboundUpdateRidingStatePacket::decode, ServerboundUpdateRidingStateHandler))
|
||||
list.add(PacketRegisterInfo(ServerboundUpdateRidingStatsPacket.ID, ServerboundUpdateRidingStatsPacket::decode, ServerboundUpdateRidingStatsHandler))
|
||||
list.add(PacketRegisterInfo(ServerboundUpdateRidingStatRangePacket.ID, ServerboundUpdateRidingStatRangePacket::decode, ServerboundUpdateRidingStatRangeHandler))
|
||||
list.add(PacketRegisterInfo(ServerboundUpdateRidingSettingsPacket.ID, ServerboundUpdateRidingSettingsPacket::decode, ServerboundUpdateRidingSettingsHandler))
|
||||
list.add(PacketRegisterInfo(DismountPokemonPacket.ID, DismountPokemonPacket::decode, DismountPokemonPacketHandler))
|
||||
list.add(PacketRegisterInfo(ServerboundUpdateDriverInputPacket.ID, ServerboundUpdateDriverInputPacket::decode, DriverInputPacketHandler))
|
||||
|
||||
|
||||
@@ -37,10 +37,6 @@ object CobblemonSensors {
|
||||
|
||||
val NEARBY_FLOWER = register("nearby_flower", ::FlowerSensor)
|
||||
|
||||
val NEARBY_SWEET_BERRY_BUSH = register("nearby_sweet_berry_bush", ::SweetBerryBushSensor)
|
||||
|
||||
val POKEMON_NEARBY_WANTED_ITEM = register("pokemon_nearby_wanted_item", ::PokemonItemSensor)
|
||||
|
||||
fun <E : Entity, U : Sensor<E>> register(id: String, supplier: Supplier<U>): SensorType<U> {
|
||||
val sensor = SensorType(supplier)
|
||||
sensors[id] = sensor
|
||||
|
||||
@@ -78,7 +78,6 @@ object Abilities : DataRegistry {
|
||||
fun all() = this.abilityMap.values.toList()
|
||||
fun first() = this.abilityMap.values.first()
|
||||
fun get(name: String) = abilityMap[name.lowercase()]
|
||||
fun getOrDummy(name: String) = get(name) ?: DUMMY
|
||||
fun getOrException(name: String) = get(name) ?: throw IllegalArgumentException("Unable to find ability of name: $name")
|
||||
fun count() = this.abilityMap.size
|
||||
|
||||
|
||||
@@ -49,9 +49,10 @@ class AbilityTemplate(
|
||||
|
||||
@JvmStatic
|
||||
val CODEC: Codec<AbilityTemplate> = CodecUtils.createByStringCodec(
|
||||
Abilities::getOrDummy,
|
||||
Abilities::get,
|
||||
AbilityTemplate::name
|
||||
) { id -> "No ability for ID $id" }
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+10
-54
@@ -9,34 +9,23 @@
|
||||
package com.cobblemon.mod.common.api.ai
|
||||
|
||||
import com.bedrockk.molang.runtime.MoLangRuntime
|
||||
import com.bedrockk.molang.runtime.struct.QueryStruct
|
||||
import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.api.ai.config.BehaviourConfig
|
||||
import com.cobblemon.mod.common.api.molang.ExpressionLike
|
||||
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.setup
|
||||
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.util.activityRegistry
|
||||
import com.cobblemon.mod.common.util.asIdentifierDefaultingNamespace
|
||||
import com.cobblemon.mod.common.util.resolve
|
||||
import com.cobblemon.mod.common.util.withQueryValue
|
||||
import com.mojang.datafixers.util.Pair
|
||||
import com.mojang.serialization.Dynamic
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
import net.minecraft.world.entity.ai.sensing.SensorType
|
||||
import net.minecraft.world.entity.schedule.Activity
|
||||
import net.minecraft.world.entity.schedule.Schedule
|
||||
|
||||
class BehaviourConfigurationContext {
|
||||
val runtime = MoLangRuntime().setup()
|
||||
|
||||
var appliedBehaviours: Set<ResourceLocation> = setOf()
|
||||
|
||||
var defaultActivity = Activity.IDLE
|
||||
@@ -46,6 +35,7 @@ class BehaviourConfigurationContext {
|
||||
val memories = mutableSetOf<MemoryModuleType<*>>()
|
||||
val sensors = mutableSetOf<SensorType<*>>()
|
||||
|
||||
val onAddScripts = mutableListOf<ResourceLocation>()
|
||||
val onAdd = mutableListOf<ExpressionLike>()
|
||||
|
||||
fun getOrCreateActivity(activity: Activity): ActivityConfigurationContext {
|
||||
@@ -68,27 +58,32 @@ class BehaviourConfigurationContext {
|
||||
this.sensors.addAll(sensors)
|
||||
}
|
||||
|
||||
fun addOnAddScript(script: ResourceLocation) {
|
||||
onAddScripts.add(script)
|
||||
}
|
||||
|
||||
fun addOnAddScript(script: ExpressionLike) {
|
||||
onAdd.add(script)
|
||||
}
|
||||
|
||||
fun apply(entity: LivingEntity, behaviourConfigs: List<BehaviourConfig>, dynamic: Dynamic<*>) {
|
||||
runtime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
runtime.withQueryValue("brain", createBrainStruct(entity, this))
|
||||
|
||||
if (entity is MoLangScriptingEntity) {
|
||||
entity.registerVariables(behaviourConfigs.flatMap { it.getVariables(entity, this) })
|
||||
entity.registerVariables(behaviourConfigs.flatMap { it.getVariables(entity) })
|
||||
entity.initializeScripting()
|
||||
}
|
||||
|
||||
// Setup the brain config
|
||||
behaviourConfigs.forEach { it.preconfigure(entity, this) }
|
||||
behaviourConfigs.forEach { it.configure(entity, this) }
|
||||
|
||||
var brain = entity.brain
|
||||
// Apply the brain config
|
||||
if (entity is MoLangScriptingEntity) {
|
||||
brain = entity.assignNewBrainWithMemoriesAndSensors(dynamic, memories, sensors)
|
||||
|
||||
val runtime = MoLangRuntime().setup()
|
||||
runtime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
onAddScripts.forEach { CobblemonScripts.run(it, runtime) }
|
||||
onAdd.forEach { runtime.resolve(it) }
|
||||
}
|
||||
activities.forEach { it.apply(entity) }
|
||||
@@ -97,43 +92,4 @@ class BehaviourConfigurationContext {
|
||||
brain.schedule = schedule
|
||||
brain.setActiveActivityIfPossible(defaultActivity)
|
||||
}
|
||||
|
||||
fun createBrainStruct(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext): QueryStruct {
|
||||
return QueryStruct(hashMapOf()).addStandardFunctions()
|
||||
.addFunction("entity") { entity.asMostSpecificMoLangValue() }
|
||||
.addFunction("create_activity") { params ->
|
||||
val name = params.getString(0).asIdentifierDefaultingNamespace()
|
||||
val activity = entity.level().activityRegistry.get(name) ?: return@addFunction run {
|
||||
Cobblemon.LOGGER.error("Tried loading activity $name as part of an entity brain but that activity does not exist")
|
||||
DoubleValue.ZERO
|
||||
}
|
||||
val existingActivityBuilder = behaviourConfigurationContext.activities.find { it.activity == activity }
|
||||
if (existingActivityBuilder != null) {
|
||||
return@addFunction createActivityStruct(existingActivityBuilder)
|
||||
} else {
|
||||
val activityConfigurationContext = ActivityConfigurationContext(activity)
|
||||
behaviourConfigurationContext.activities.add(activityConfigurationContext)
|
||||
return@addFunction createActivityStruct(activityConfigurationContext)
|
||||
}
|
||||
}
|
||||
.addFunction("set_core_activities") { params ->
|
||||
behaviourConfigurationContext.coreActivities = params.params.map { (it as ObjectValue<ActivityConfigurationContext>).obj.activity }.toSet()
|
||||
return@addFunction DoubleValue.ONE
|
||||
}
|
||||
.addFunction("set_default_activity") { params ->
|
||||
behaviourConfigurationContext.defaultActivity = params.get<ObjectValue<ActivityConfigurationContext>>(0).obj.activity
|
||||
return@addFunction DoubleValue.ONE
|
||||
}
|
||||
}
|
||||
|
||||
fun createActivityStruct(activityConfigurationContext: ActivityConfigurationContext): ObjectValue<ActivityConfigurationContext> {
|
||||
val struct = ObjectValue(activityConfigurationContext)
|
||||
struct.addStandardFunctions()
|
||||
.addFunction("add_task") { params ->
|
||||
val priority = params.getInt(0)
|
||||
val task = params.get(1) as ObjectValue<BehaviorControl<in LivingEntity>>
|
||||
activityConfigurationContext.tasks.add(Pair(priority, task.obj))
|
||||
}
|
||||
return struct
|
||||
}
|
||||
}
|
||||
+7
-22
@@ -20,8 +20,6 @@ import com.cobblemon.mod.common.util.asExpression
|
||||
import com.cobblemon.mod.common.util.asIdentifierDefaultingNamespace
|
||||
import com.cobblemon.mod.common.util.resolve
|
||||
import net.minecraft.world.entity.Entity
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
|
||||
/**
|
||||
* This is used in the AI system to store optional additional information about the attack target,
|
||||
@@ -43,21 +41,15 @@ import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
class CobblemonAttackTargetData(
|
||||
/** An expression that returns false when the target is no longer worth attacking. */
|
||||
var shouldContinue: Expression = "true".asExpression(),
|
||||
var dealtHitsUntilDisengage: Int = -1, // -1 means no limit
|
||||
var disengageAction: (entity: LivingEntity) -> Unit = ::defaultDisengage
|
||||
var hitsUntilDisengage: Int = -1, // -1 means no limit
|
||||
var disengageAction: (entity: Entity) -> Unit = {}
|
||||
) {
|
||||
companion object {
|
||||
fun defaultDisengage(entity: LivingEntity) {
|
||||
entity.brain.eraseMemory(MemoryModuleType.ATTACK_TARGET)
|
||||
entity.brain.updateActivityFromSchedule(entity.level().dayTime, entity.level().gameTime)
|
||||
}
|
||||
}
|
||||
val struct = ObjectValue<CobblemonAttackTargetData>(this).also {
|
||||
it.addFunction("dealt_hits_until_disengage") { DoubleValue(dealtHitsUntilDisengage.toDouble()) }
|
||||
it.addFunction("set_dealt_hits_until_disengage") { params ->
|
||||
it.addFunction("hits_until_disengage") { DoubleValue(hitsUntilDisengage.toDouble()) }
|
||||
it.addFunction("set_hits_until_disengage") { params ->
|
||||
val value = params.getDouble(0)
|
||||
dealtHitsUntilDisengage = value.toInt()
|
||||
DoubleValue(dealtHitsUntilDisengage.toDouble())
|
||||
hitsUntilDisengage = value.toInt()
|
||||
DoubleValue(hitsUntilDisengage.toDouble())
|
||||
}
|
||||
it.addFunction("set_disengage_action") { params ->
|
||||
val script = params.getString(0).asIdentifierDefaultingNamespace()
|
||||
@@ -72,15 +64,8 @@ class CobblemonAttackTargetData(
|
||||
}
|
||||
DoubleValue.ONE
|
||||
}
|
||||
it.addFunction("reset") {
|
||||
shouldContinue = "true".asExpression()
|
||||
dealtHitsUntilDisengage = -1
|
||||
disengageAction = ::defaultDisengage
|
||||
DoubleValue.ONE
|
||||
}
|
||||
it.addFunction("unset_disengage_action") { params ->
|
||||
disengageAction = ::defaultDisengage
|
||||
disengageAction = {}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,23 +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.ai
|
||||
|
||||
import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.cobblemon.mod.common.api.molang.ObjectValue
|
||||
import com.cobblemon.mod.common.util.getDoubleOrNull
|
||||
|
||||
class CobblemonAvoidTargetData {
|
||||
var walkSpeed: Float? = null
|
||||
|
||||
@Transient
|
||||
val struct = ObjectValue<CobblemonAvoidTargetData>(this).also {
|
||||
it.addFunction("walk_speed") { DoubleValue(walkSpeed) }
|
||||
it.addFunction("set_walk_speed") { walkSpeed = it.getDoubleOrNull(0)?.toFloat() }
|
||||
}
|
||||
}
|
||||
@@ -33,13 +33,19 @@ class CobblemonBehaviour(
|
||||
// detect if it's a ResourceLocation and failing that, Expression. The on[..]Script fields are kinda fringe though.
|
||||
@SerializedName("onRemove", alternate = ["undo"])
|
||||
val onRemove: ExpressionLike? = null,
|
||||
@SerializedName("onRemoveScript", alternate = ["undoScript"])
|
||||
val onRemoveScript: ResourceLocation? = null,
|
||||
val onAdd: ExpressionLike? = null,
|
||||
val onAddScript: ResourceLocation? = null,
|
||||
) {
|
||||
fun canBeApplied(entity: LivingEntity) = entityType?.let { entityType == entity.type.builtInRegistryHolder().unwrapKey().get().location() } != false
|
||||
fun configure(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext) {
|
||||
if (onAdd != null) {
|
||||
behaviourConfigurationContext.addOnAddScript(onAdd)
|
||||
}
|
||||
if (onAddScript != null) {
|
||||
behaviourConfigurationContext.addOnAddScript(onAddScript)
|
||||
}
|
||||
configurations.forEach { it.configure(entity, behaviourConfigurationContext) }
|
||||
}
|
||||
|
||||
@@ -47,6 +53,9 @@ class CobblemonBehaviour(
|
||||
fun onRemove(entity: LivingEntity) {
|
||||
val runtime = MoLangRuntime().setup()
|
||||
runtime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
if (onRemoveScript != null) {
|
||||
CobblemonScripts.run(onRemoveScript, runtime)
|
||||
}
|
||||
if (onRemove != null) {
|
||||
runtime.resolve(onRemove)
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ import com.cobblemon.mod.common.util.getBooleanOrNull
|
||||
import com.cobblemon.mod.common.util.getDoubleOrNull
|
||||
import kotlin.math.sqrt
|
||||
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
|
||||
@@ -29,8 +30,7 @@ class CobblemonWanderControl(
|
||||
var allowWater: Boolean = false,
|
||||
var allowAir: Boolean = false,
|
||||
var pathCooldownTicks: Int = 20 * 5, // Used to mitigate the cost of pathfinding.
|
||||
var speedMultiplier: Float = 1F,
|
||||
var wanderChance: Float? = null
|
||||
var wanderSpeed: Float = 0.35F,
|
||||
) {
|
||||
class WanderCenter(val x: Number, val y: Number, val z: Number, val minRange: Float, val maxRange: Float)
|
||||
|
||||
@@ -46,7 +46,7 @@ class CobblemonWanderControl(
|
||||
.addFunction("allow_water") { if (allowWater) 1.0 else 0.0 }
|
||||
.addFunction("allow_air") { if (allowAir) 1.0 else 0.0 }
|
||||
.addFunction("path_cooldown_ticks") { pathCooldownTicks.toDouble() }
|
||||
.addFunction("speed_multiplier") { speedMultiplier }
|
||||
.addFunction("wander_speed") { wanderSpeed }
|
||||
.addFunction("set_center") { params ->
|
||||
if (params.params.size < 3) {
|
||||
throw IllegalArgumentException("set_center requires at least 3 parameters: x, y, z")
|
||||
@@ -69,19 +69,15 @@ class CobblemonWanderControl(
|
||||
.addFunction("set_allow_water") { params -> allowWater = params.getBooleanOrNull(0) ?: false }
|
||||
.addFunction("set_allow_air") { params -> allowAir = params.getBooleanOrNull(0) ?: false }
|
||||
.addFunction("set_path_cooldown_ticks") { params -> pathCooldownTicks = params.getDoubleOrNull(0)?.toInt() ?: (20 * 5) }
|
||||
.addFunction("set_speed_multiplier") { params -> speedMultiplier = params.getDoubleOrNull(0)?.toFloat() ?: 0.35F }
|
||||
.addFunction("set_wander_chance") { params ->
|
||||
wanderChance = params.getDoubleOrNull(0)?.toFloat()
|
||||
}
|
||||
.addFunction("set_wander_speed") { params -> wanderSpeed = params.getDoubleOrNull(0)?.toFloat() ?: 0.35F }
|
||||
.addFunction("reset") {
|
||||
center = null
|
||||
allowLand = false
|
||||
allowWater = false
|
||||
allowAir = false
|
||||
pathCooldownTicks = 20 * 5
|
||||
speedMultiplier = 1F
|
||||
wanderSpeed = 0.35F
|
||||
maxAttempts = 4
|
||||
wanderChance = null
|
||||
}
|
||||
|
||||
fun isSuitable(position: BlockPos): Boolean {
|
||||
|
||||
@@ -13,22 +13,6 @@ import com.cobblemon.mod.common.api.npc.configuration.MoLangConfigVariable
|
||||
import com.mojang.datafixers.util.Either
|
||||
import kotlin.jvm.optionals.getOrNull
|
||||
|
||||
/**
|
||||
* The issue in a lot of the behaviour datapacking is that there are times when a property should be exposed to
|
||||
* the user and other times that you want to fix the value in place. The remedy to this is using an [Either] where
|
||||
* one side is an Expression, ergo a value that is not exposed to the user, and the other side is a fully defined
|
||||
* configuration variable.
|
||||
*
|
||||
* When users are editing JSONs they can have a simple expression, or they can declare full variable to show to the
|
||||
* user. Similarly, the classes for tasks and brain configurations can have defaults that hide from the user or
|
||||
* defaults that are properly defined variables. One example where this is useful is Wander tasks which might be reused
|
||||
* in panic activities where the walk speed is tuned up. When specifying the task in the panic activity, the value of
|
||||
* the walk speed would be set (overriding the default which is the walk_speed MoLang variable) to a separate config
|
||||
* variable that is exposed to the user. Pretty neat!
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since January 4th, 2025
|
||||
*/
|
||||
typealias ExpressionOrEntityVariable = Either<Expression, MoLangConfigVariable>
|
||||
|
||||
/**
|
||||
|
||||
+2
-3
@@ -12,7 +12,6 @@ import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
|
||||
import com.cobblemon.mod.common.api.ai.ExpressionOrEntityVariable
|
||||
import com.cobblemon.mod.common.api.ai.asVariables
|
||||
import com.cobblemon.mod.common.util.asExpression
|
||||
import com.cobblemon.mod.common.util.resolveBoolean
|
||||
import com.mojang.datafixers.util.Either
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
@@ -29,9 +28,9 @@ class AddMemoriesAndSensorsConfig : BehaviourConfig {
|
||||
val memories: Set<MemoryModuleType<*>> = emptySet()
|
||||
val sensors: Set<SensorType<*>> = mutableSetOf()
|
||||
|
||||
override fun getVariables(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext) = listOf(condition).asVariables()
|
||||
override fun getVariables(entity: LivingEntity) = listOf(condition).asVariables()
|
||||
override fun configure(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext) {
|
||||
if (!checkCondition(behaviourConfigurationContext, condition)) return
|
||||
if (!checkCondition(entity, condition)) return
|
||||
behaviourConfigurationContext.addMemories(memories)
|
||||
behaviourConfigurationContext.addSensors(sensors)
|
||||
}
|
||||
|
||||
@@ -24,13 +24,9 @@ class AddTasksToActivity : BehaviourConfig {
|
||||
val condition: ExpressionOrEntityVariable = Either.left("true".asExpression())
|
||||
val tasksByPriority = mutableMapOf<Int, List<TaskConfig>>()
|
||||
|
||||
override fun getVariables(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext) = tasksByPriority.values
|
||||
.flatten()
|
||||
.flatMap {
|
||||
it.getVariables(entity, behaviourConfigurationContext)
|
||||
} + listOf(condition).asVariables()
|
||||
override fun getVariables(entity: LivingEntity) = tasksByPriority.values.flatten().flatMap { it.getVariables(entity) } + listOf(condition).asVariables()
|
||||
override fun configure(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext) {
|
||||
if (!checkCondition(behaviourConfigurationContext, condition)) return
|
||||
if (!checkCondition(entity, condition)) return
|
||||
|
||||
val activities = if (activity != null) (activities + activity) else activities
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ import com.cobblemon.mod.common.api.npc.configuration.MoLangConfigVariable
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
|
||||
class AddVariablesConfig(val variables: List<MoLangConfigVariable> = emptyList()) : BehaviourConfig {
|
||||
override fun getVariables(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext) = variables
|
||||
override fun getVariables(entity: LivingEntity) = variables
|
||||
|
||||
// Configuration happens naturally through the override on variables
|
||||
override fun configure(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext) {}
|
||||
|
||||
@@ -25,27 +25,18 @@ class ApplyBehaviours : BehaviourConfig {
|
||||
@SerializedName("behaviours", alternate = ["behaviors"])
|
||||
val behaviours = mutableListOf<ResourceLocation>()
|
||||
|
||||
override fun getVariables(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext): List<MoLangConfigVariable> {
|
||||
return if (checkCondition(behaviourConfigurationContext, condition)) {
|
||||
override fun getVariables(entity: LivingEntity): List<MoLangConfigVariable> {
|
||||
return if (checkCondition(entity, condition)) {
|
||||
behaviours.flatMap {
|
||||
CobblemonBehaviours.behaviours[it]?.configurations?.flatMap { it.getVariables(entity, behaviourConfigurationContext) } ?: emptyList()
|
||||
CobblemonBehaviours.behaviours[it]?.configurations?.flatMap { it.getVariables(entity) } ?: emptyList()
|
||||
} + listOf(condition).asVariables()
|
||||
} else {
|
||||
listOf(condition).asVariables()
|
||||
}
|
||||
}
|
||||
|
||||
override fun preconfigure(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext) {
|
||||
if (!checkCondition(behaviourConfigurationContext, condition)) return
|
||||
|
||||
val configurations = behaviours.map { CobblemonBehaviours.behaviours[it]?.takeIf { it.canBeApplied(entity) } ?: return }
|
||||
configurations.forEach {
|
||||
it.configurations.forEach { it.preconfigure(entity, behaviourConfigurationContext) }
|
||||
}
|
||||
}
|
||||
|
||||
override fun configure(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext) {
|
||||
if (!checkCondition(behaviourConfigurationContext, condition)) return
|
||||
if (!checkCondition(entity, condition)) return
|
||||
|
||||
val configurations = behaviours.map { CobblemonBehaviours.behaviours[it]?.takeIf { it.canBeApplied(entity) } ?: return Cobblemon.LOGGER.warn("Behaviour $it not found") }
|
||||
// Why not just add the presets to the context directly?
|
||||
|
||||
@@ -37,6 +37,7 @@ interface BehaviourConfig {
|
||||
companion object {
|
||||
val types = mutableMapOf<ResourceLocation, Class<out BehaviourConfig>>(
|
||||
cobblemonResource("script") to ScriptBehaviourConfig::class.java,
|
||||
cobblemonResource("custom_script") to CustomScriptBehaviourConfig::class.java,
|
||||
cobblemonResource("add_tasks_to_activity") to AddTasksToActivity::class.java,
|
||||
cobblemonResource("apply_behaviours") to ApplyBehaviours::class.java,
|
||||
cobblemonResource("set_default_activity") to SetDefaultActivity::class.java,
|
||||
@@ -47,16 +48,12 @@ interface BehaviourConfig {
|
||||
)
|
||||
}
|
||||
|
||||
/** Literally just here for shorthand. */
|
||||
fun checkCondition(behaviourConfigurationContext: BehaviourConfigurationContext, expressionOrEntityVariable: ExpressionOrEntityVariable): Boolean {
|
||||
return behaviourConfigurationContext.runtime.resolveBoolean(expressionOrEntityVariable.map({ it }, { "q.entity.config.${it.variableName}".asExpression() }))
|
||||
}
|
||||
|
||||
fun getVariables(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext): List<MoLangConfigVariable>
|
||||
|
||||
fun preconfigure(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext) {
|
||||
// Default implementation does nothing, can be overridden if needed
|
||||
fun checkCondition(entity: LivingEntity, expressionOrEntityVariable: ExpressionOrEntityVariable): Boolean {
|
||||
val runtime = MoLangRuntime().setup()
|
||||
runtime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
return runtime.resolveBoolean(expressionOrEntityVariable.map({ it }, { "q.entity.config.${it.variableName}".asExpression() }))
|
||||
}
|
||||
|
||||
fun getVariables(entity: LivingEntity): List<MoLangConfigVariable>
|
||||
fun configure(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext)
|
||||
}
|
||||
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* 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.ai.config
|
||||
|
||||
import com.bedrockk.molang.runtime.MoLangRuntime
|
||||
import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
|
||||
import com.cobblemon.mod.common.api.ai.ExpressionOrEntityVariable
|
||||
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.setup
|
||||
import com.cobblemon.mod.common.api.npc.configuration.MoLangConfigVariable
|
||||
import com.cobblemon.mod.common.util.asExpression
|
||||
import com.cobblemon.mod.common.util.asExpressionLike
|
||||
import com.cobblemon.mod.common.util.resolve
|
||||
import com.cobblemon.mod.common.util.withQueryValue
|
||||
import com.mojang.datafixers.util.Either
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
import net.minecraft.world.entity.ai.sensing.SensorType
|
||||
|
||||
class CustomScriptBehaviourConfig : BehaviourConfig {
|
||||
companion object {
|
||||
val runtime = MoLangRuntime().setup()
|
||||
}
|
||||
|
||||
var condition: ExpressionOrEntityVariable = Either.left("true".asExpression())
|
||||
val variables: List<MoLangConfigVariable> = emptyList()
|
||||
val script: ExpressionLike = "0".asExpressionLike()
|
||||
val memories = emptySet<MemoryModuleType<*>>()
|
||||
val sensors = emptySet<SensorType<*>>()
|
||||
|
||||
override fun getVariables(entity: LivingEntity) = variables
|
||||
override fun configure(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext) {
|
||||
if (!checkCondition(entity, condition)) return
|
||||
behaviourConfigurationContext.addMemories(memories)
|
||||
behaviourConfigurationContext.addSensors(sensors)
|
||||
runtime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
runtime.resolve(script)
|
||||
}
|
||||
}
|
||||
@@ -117,7 +117,7 @@ Example behaviour (`uses_healing_machine.json`):
|
||||
"configurations": [
|
||||
{
|
||||
"type": "add_tasks_to_activity",
|
||||
"activity": "minecraft:idle",
|
||||
"activity": "idle",
|
||||
"tasksByPriority": {
|
||||
"1": [
|
||||
"heal_using_healing_machine",
|
||||
@@ -177,26 +177,27 @@ Example:
|
||||
|
||||
### script
|
||||
The `script` type executes a registered MoLang script which will apply some changes to the brain or entity. This can be
|
||||
useful for complex variable configuration. `q.entity` will refer to the entity.
|
||||
|
||||
- `executeEarly`: If true, the script will be executed in the variable phase which occurs before tasks are added to the brain. Use this when your script might influence which tasks are put onto the brain.
|
||||
- `script`: Either a resource location for the `molang` datapack folder or a MoLang expression that will be executed.
|
||||
- `variables`: A list of variables that can be configured in the UI. Each variable has the same properties as in `add_variables`.
|
||||
useful if the goal is to apply some kind of configuration to the entity that would otherwise be performed by an NPC preset
|
||||
or NPC class. `q.entity` will refer to the entity. This is powerful when combined with [add_variables](#add_variables)
|
||||
configs in the same behaviour preset.
|
||||
|
||||
Example:
|
||||
```json
|
||||
{
|
||||
"type": "script",
|
||||
"executeEarly": true,
|
||||
"script": "cobblemon:configure_npc_party",
|
||||
"variables": [
|
||||
{
|
||||
"variableName": "party_size",
|
||||
"defaultValue": "3",
|
||||
"displayName": "Party Size",
|
||||
"description": "The number of Pokémon in the NPC's party.",
|
||||
"type": "NUMBER"
|
||||
}
|
||||
]
|
||||
"script": "cobblemon:configure_npc_party"
|
||||
}
|
||||
```
|
||||
|
||||
### custom_script
|
||||
The `custom_script` type executes a custom MoLang script from this config which will apply some changes to the brain or
|
||||
entity. This is useful for when you want to apply some kind of configuration to the entity that would otherwise be
|
||||
by an NPC preset or NPC class. `q.entity` will refer to the entity.
|
||||
|
||||
Example:
|
||||
```json
|
||||
{
|
||||
"type": "custom_script",
|
||||
"script": "q.entity.set_pathfinding_malus('WATER', -1);"
|
||||
}
|
||||
```
|
||||
+73
-29
@@ -9,50 +9,94 @@
|
||||
package com.cobblemon.mod.common.api.ai.config
|
||||
|
||||
import com.bedrockk.molang.runtime.MoLangRuntime
|
||||
import com.bedrockk.molang.runtime.struct.QueryStruct
|
||||
import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.api.ai.ActivityConfigurationContext
|
||||
import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
|
||||
import com.cobblemon.mod.common.api.ai.ExpressionOrEntityVariable
|
||||
import com.cobblemon.mod.common.api.molang.ExpressionLike
|
||||
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.setup
|
||||
import com.cobblemon.mod.common.api.molang.ObjectValue
|
||||
import com.cobblemon.mod.common.api.npc.configuration.MoLangConfigVariable
|
||||
import com.cobblemon.mod.common.api.scripting.CobblemonScripts
|
||||
import com.cobblemon.mod.common.util.activityRegistry
|
||||
import com.cobblemon.mod.common.util.asExpression
|
||||
import com.cobblemon.mod.common.util.asExpressionLike
|
||||
import com.cobblemon.mod.common.util.asIdentifierDefaultingNamespace
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.cobblemon.mod.common.util.resolve
|
||||
import com.cobblemon.mod.common.util.withQueryValue
|
||||
import com.mojang.datafixers.util.Either
|
||||
import com.mojang.datafixers.util.Pair
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
import net.minecraft.world.entity.ai.sensing.SensorType
|
||||
|
||||
/**
|
||||
* Runs a MoLang script as part of the entity's behaviour configuration. Variables can be configured here for convenience.
|
||||
*
|
||||
* When [executeEarly] is true, the script will run in an earlier phase than most configs, allowing it to get ahead of
|
||||
* other behaviour configurations that might depend on the changes made by the script.
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since August 11th, 2025
|
||||
*/
|
||||
class ScriptBehaviourConfig : BehaviourConfig {
|
||||
/** If true, the script will execute as part of the getVariables phase. */
|
||||
val executeEarly: Boolean = false
|
||||
val condition: ExpressionOrEntityVariable = Either.left("true".asExpression())
|
||||
val script: ExpressionLike = "0".asExpressionLike()
|
||||
val script = cobblemonResource("dummy")
|
||||
val variables = mutableListOf<MoLangConfigVariable>()
|
||||
val memories = emptySet<MemoryModuleType<*>>()
|
||||
val sensors = emptySet<SensorType<*>>()
|
||||
|
||||
private fun runScript(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext) {
|
||||
if (!checkCondition(behaviourConfigurationContext, condition)) return
|
||||
script.resolve(behaviourConfigurationContext.runtime)
|
||||
}
|
||||
|
||||
override fun getVariables(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext) = variables
|
||||
|
||||
override fun preconfigure(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext) {
|
||||
if (executeEarly) {
|
||||
runScript(entity = entity, behaviourConfigurationContext = behaviourConfigurationContext)
|
||||
}
|
||||
}
|
||||
override fun getVariables(entity: LivingEntity) = variables
|
||||
|
||||
override fun configure(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext) {
|
||||
if (!executeEarly) {
|
||||
runScript(entity = entity, behaviourConfigurationContext = behaviourConfigurationContext)
|
||||
}
|
||||
if (!checkCondition(entity, condition)) return
|
||||
val runtime = MoLangRuntime().setup()
|
||||
runtime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
|
||||
val struct = createBrainStruct(entity, behaviourConfigurationContext)
|
||||
val script = CobblemonScripts.scripts[this.script]
|
||||
?: run {
|
||||
Cobblemon.LOGGER.error("Tried loading script $script as part of an entity brain but that script does not exist")
|
||||
return
|
||||
}
|
||||
|
||||
behaviourConfigurationContext.addMemories(memories)
|
||||
behaviourConfigurationContext.addSensors(sensors)
|
||||
|
||||
runtime.resolve(script, mapOf("brain" to struct))
|
||||
}
|
||||
|
||||
fun createBrainStruct(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext): QueryStruct {
|
||||
return QueryStruct(hashMapOf()).addStandardFunctions()
|
||||
.addFunction("entity") { entity.asMostSpecificMoLangValue() }
|
||||
.addFunction("create_activity") { params ->
|
||||
val name = params.getString(0).asIdentifierDefaultingNamespace()
|
||||
val activity = entity.level().activityRegistry.get(name) ?: return@addFunction run {
|
||||
Cobblemon.LOGGER.error("Tried loading activity $name as part of an entity brain but that activity does not exist")
|
||||
DoubleValue.ZERO
|
||||
}
|
||||
val existingActivityBuilder = behaviourConfigurationContext.activities.find { it.activity == activity }
|
||||
if (existingActivityBuilder != null) {
|
||||
return@addFunction createActivityStruct(existingActivityBuilder)
|
||||
} else {
|
||||
val activityConfigurationContext = ActivityConfigurationContext(activity)
|
||||
behaviourConfigurationContext.activities.add(activityConfigurationContext)
|
||||
return@addFunction createActivityStruct(activityConfigurationContext)
|
||||
}
|
||||
}
|
||||
.addFunction("set_core_activities") { params ->
|
||||
behaviourConfigurationContext.coreActivities = params.params.map { (it as ObjectValue<ActivityConfigurationContext>).obj.activity }.toSet()
|
||||
return@addFunction DoubleValue.ONE
|
||||
}
|
||||
.addFunction("set_default_activity") { params ->
|
||||
behaviourConfigurationContext.defaultActivity = params.get<ObjectValue<ActivityConfigurationContext>>(0).obj.activity
|
||||
return@addFunction DoubleValue.ONE
|
||||
}
|
||||
}
|
||||
|
||||
fun createActivityStruct(activityConfigurationContext: ActivityConfigurationContext): ObjectValue<ActivityConfigurationContext> {
|
||||
val struct = ObjectValue(activityConfigurationContext)
|
||||
struct.addStandardFunctions()
|
||||
.addFunction("add_task") { params ->
|
||||
val priority = params.getInt(0)
|
||||
val task = params.get(1) as ObjectValue<BehaviorControl<in LivingEntity>>
|
||||
activityConfigurationContext.tasks.add(Pair(priority, task.obj))
|
||||
}
|
||||
return struct
|
||||
}
|
||||
}
|
||||
@@ -15,7 +15,7 @@ import net.minecraft.world.entity.schedule.Activity
|
||||
|
||||
class SetCoreActivities : BehaviourConfig {
|
||||
val activities = mutableListOf<Activity>()
|
||||
override fun getVariables(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext) = emptyList<MoLangConfigVariable>()
|
||||
override fun getVariables(entity: LivingEntity) = emptyList<MoLangConfigVariable>()
|
||||
override fun configure(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext) {
|
||||
behaviourConfigurationContext.coreActivities = activities.toSet()
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ import net.minecraft.world.entity.schedule.Activity
|
||||
class SetDefaultActivity : BehaviourConfig {
|
||||
val activity: Activity = Activity.IDLE
|
||||
|
||||
override fun getVariables(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext) = emptyList<MoLangConfigVariable>()
|
||||
override fun getVariables(entity: LivingEntity) = emptyList<MoLangConfigVariable>()
|
||||
override fun configure(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext) {
|
||||
behaviourConfigurationContext.defaultActivity = activity
|
||||
}
|
||||
|
||||
@@ -8,21 +8,27 @@
|
||||
|
||||
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.molang.ExpressionLike
|
||||
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.entity.MoLangScriptingEntity
|
||||
import com.cobblemon.mod.common.util.resolve
|
||||
import com.cobblemon.mod.common.util.withQueryValue
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
|
||||
class SetVariablesConfig : BehaviourConfig {
|
||||
var variableValues = mutableMapOf<String, ExpressionLike>()
|
||||
|
||||
override fun getVariables(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext) = emptyList<MoLangConfigVariable>()
|
||||
override fun getVariables(entity: LivingEntity) = emptyList<MoLangConfigVariable>()
|
||||
override fun configure(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext) {
|
||||
val runtime = MoLangRuntime().setup()
|
||||
runtime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
if (entity is MoLangScriptingEntity) {
|
||||
variableValues.forEach { (variableName, valueExpression) ->
|
||||
entity.config.setDirectly(variableName, behaviourConfigurationContext.runtime.resolve(valueExpression))
|
||||
entity.config.setDirectly(variableName, runtime.resolve(valueExpression))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+4
-5
@@ -13,7 +13,6 @@ import com.cobblemon.mod.common.api.molang.ExpressionLike
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMostSpecificMoLangValue
|
||||
import com.cobblemon.mod.common.api.npc.configuration.MoLangConfigVariable
|
||||
import com.cobblemon.mod.common.util.asExpressionLike
|
||||
import com.cobblemon.mod.common.util.mainThreadRuntime
|
||||
import com.cobblemon.mod.common.util.withQueryValue
|
||||
import net.minecraft.server.level.ServerLevel
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
@@ -25,16 +24,16 @@ class ActivityChangeTaskConfig : SingleTaskConfig {
|
||||
val activity: Activity = Activity.IDLE
|
||||
val condition: ExpressionLike = "false".asExpressionLike()
|
||||
|
||||
override fun getVariables(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext): List<MoLangConfigVariable> = emptyList()
|
||||
override fun getVariables(entity: LivingEntity): List<MoLangConfigVariable> = emptyList()
|
||||
|
||||
override fun createTask(
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
): BehaviorControl<in LivingEntity> {
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
return object : OneShot<LivingEntity>() {
|
||||
override fun trigger(serverLevel: ServerLevel, livingEntity: LivingEntity, l: Long): Boolean {
|
||||
mainThreadRuntime.withQueryValue("entity", livingEntity.asMostSpecificMoLangValue())
|
||||
if (condition.resolveBoolean(mainThreadRuntime)) {
|
||||
runtime.withQueryValue("entity", livingEntity.asMostSpecificMoLangValue())
|
||||
if (condition.resolveBoolean(runtime)) {
|
||||
livingEntity.brain.setActiveActivityIfPossible(activity)
|
||||
return true
|
||||
} else {
|
||||
|
||||
+5
-6
@@ -16,7 +16,6 @@ import com.cobblemon.mod.common.api.ai.config.task.WanderTaskConfig.Companion.WA
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMostSpecificMoLangValue
|
||||
import com.cobblemon.mod.common.api.npc.configuration.MoLangConfigVariable
|
||||
import com.cobblemon.mod.common.util.asExpression
|
||||
import com.cobblemon.mod.common.util.mainThreadRuntime
|
||||
import com.cobblemon.mod.common.util.resolveFloat
|
||||
import com.cobblemon.mod.common.util.withQueryValue
|
||||
import com.mojang.datafixers.util.Either
|
||||
@@ -39,7 +38,7 @@ class AirWanderTaskConfig : SingleTaskConfig {
|
||||
val minUpwardsMovement: ExpressionOrEntityVariable = Either.left("3.0".asExpression())
|
||||
val minDownwardsMovement: ExpressionOrEntityVariable = Either.left("3.0".asExpression())
|
||||
|
||||
override fun getVariables(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext): List<MoLangConfigVariable> {
|
||||
override fun getVariables(entity: LivingEntity): List<MoLangConfigVariable> {
|
||||
return listOf(condition, wanderChance, horizontalRange, verticalRange, speedMultiplier, minUpwardsMovement, minDownwardsMovement).asVariables()
|
||||
}
|
||||
|
||||
@@ -47,7 +46,8 @@ class AirWanderTaskConfig : SingleTaskConfig {
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
if (!condition.resolveBoolean(behaviourConfigurationContext.runtime)) return null
|
||||
runtime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
if (!condition.resolveBoolean()) return null
|
||||
behaviourConfigurationContext.addMemories(MemoryModuleType.WALK_TARGET, MemoryModuleType.LOOK_TARGET, CobblemonMemories.PATH_COOLDOWN)
|
||||
val wanderChanceExpression = wanderChance.asSimplifiedExpression(entity)
|
||||
|
||||
@@ -62,16 +62,15 @@ class AirWanderTaskConfig : SingleTaskConfig {
|
||||
return@Trigger false
|
||||
}
|
||||
|
||||
val runtime = mainThreadRuntime
|
||||
runtime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
val wanderChance = runtime.resolveFloat(wanderChanceExpression)
|
||||
if (wanderChance <= 0 || world.random.nextFloat() > wanderChance) return@Trigger false
|
||||
|
||||
val rotVec = entity.getViewVector(0F)
|
||||
pathCooldown.setWithExpiry(true, 60L)
|
||||
val target = HoverRandomPos.getPos(entity, horizontalRange.resolveInt(runtime), verticalRange.resolveInt(runtime), rotVec.x, rotVec.y, 1.5707964f, minUpwardsMovement.resolveInt(runtime), minDownwardsMovement.resolveInt(runtime))
|
||||
val target = HoverRandomPos.getPos(entity, horizontalRange.resolveInt(), verticalRange.resolveInt(), rotVec.x, rotVec.y, 1.5707964f, minUpwardsMovement.resolveInt(), minDownwardsMovement.resolveInt())
|
||||
?: return@Trigger false
|
||||
walkTarget.set(WalkTarget(target, speedMultiplier.resolveFloat(runtime), 3))
|
||||
walkTarget.set(WalkTarget(target, speedMultiplier.resolveFloat(), 3))
|
||||
lookTarget.set(BlockPosTracker(target))
|
||||
return@Trigger true
|
||||
}
|
||||
|
||||
+6
-2
@@ -10,7 +10,9 @@ package com.cobblemon.mod.common.api.ai.config.task
|
||||
|
||||
import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
|
||||
import com.cobblemon.mod.common.api.ai.ExpressionOrEntityVariable
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMostSpecificMoLangValue
|
||||
import com.cobblemon.mod.common.util.asExpression
|
||||
import com.cobblemon.mod.common.util.withQueryValue
|
||||
import com.mojang.datafixers.util.Either
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
@@ -19,12 +21,14 @@ class AllOfTaskConfig : TaskConfig {
|
||||
val condition: ExpressionOrEntityVariable = Either.left("true".asExpression())
|
||||
val tasks: List<TaskConfig> = emptyList()
|
||||
|
||||
override fun getVariables(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext) = tasks.flatMap { it.getVariables(entity, behaviourConfigurationContext) }
|
||||
override fun getVariables(entity: LivingEntity) = tasks.flatMap { it.getVariables(entity) }
|
||||
override fun createTasks(
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
): List<BehaviorControl<in LivingEntity>> {
|
||||
if (!condition.resolveBoolean(behaviourConfigurationContext.runtime)) return emptyList()
|
||||
runtime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
if (!condition.resolveBoolean()) return emptyList()
|
||||
|
||||
return tasks.flatMap { it.createTasks(entity, behaviourConfigurationContext) }
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -17,7 +17,7 @@ import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
|
||||
class AttackAngryAtTaskConfig : SingleTaskConfig {
|
||||
override fun getVariables(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext) = emptyList<MoLangConfigVariable>()
|
||||
override fun getVariables(entity: LivingEntity) = emptyList<MoLangConfigVariable>()
|
||||
override fun createTask(
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
|
||||
+2
-2
@@ -16,8 +16,8 @@ import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
|
||||
class AttackHostileMobsTaskConfig : SingleTaskConfig {
|
||||
override fun getVariables(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext): List<MoLangConfigVariable> {
|
||||
return emptyList()
|
||||
override fun getVariables(entity: LivingEntity): List<MoLangConfigVariable> {
|
||||
return emptyList<MoLangConfigVariable>()
|
||||
}
|
||||
|
||||
override fun createTask(
|
||||
|
||||
+6
-2
@@ -10,8 +10,11 @@ package com.cobblemon.mod.common.api.ai.config.task
|
||||
|
||||
import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
|
||||
import com.cobblemon.mod.common.api.ai.ExpressionOrEntityVariable
|
||||
import com.cobblemon.mod.common.api.ai.asVariables
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMostSpecificMoLangValue
|
||||
import com.cobblemon.mod.common.api.npc.configuration.MoLangConfigVariable
|
||||
import com.cobblemon.mod.common.util.asExpression
|
||||
import com.cobblemon.mod.common.util.withQueryValue
|
||||
import com.mojang.datafixers.util.Either
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
@@ -21,12 +24,13 @@ import net.minecraft.world.entity.ai.sensing.SensorType
|
||||
|
||||
class CalmDownTaskConfig : SingleTaskConfig {
|
||||
var condition: ExpressionOrEntityVariable = Either.left("true".asExpression())
|
||||
override fun getVariables(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext) = emptyList<MoLangConfigVariable>()
|
||||
override fun getVariables(entity: LivingEntity) = emptyList<MoLangConfigVariable>()
|
||||
override fun createTask(
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
if (!condition.resolveBoolean(behaviourConfigurationContext.runtime)) return null
|
||||
runtime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
if (!condition.resolveBoolean()) return null
|
||||
behaviourConfigurationContext.addMemories(
|
||||
MemoryModuleType.HURT_BY,
|
||||
MemoryModuleType.HURT_BY_ENTITY,
|
||||
|
||||
+6
-5
@@ -12,9 +12,11 @@ import com.cobblemon.mod.common.CobblemonMemories
|
||||
import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
|
||||
import com.cobblemon.mod.common.api.ai.ExpressionOrEntityVariable
|
||||
import com.cobblemon.mod.common.api.ai.asVariables
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMostSpecificMoLangValue
|
||||
import com.cobblemon.mod.common.api.npc.configuration.MoLangConfigVariable
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.util.asExpression
|
||||
import com.cobblemon.mod.common.util.withQueryValue
|
||||
import com.mojang.datafixers.util.Either
|
||||
import kotlin.jvm.optionals.getOrNull
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
@@ -25,9 +27,7 @@ import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
import net.minecraft.world.entity.ai.sensing.SensorType
|
||||
|
||||
/**
|
||||
* Checks nearby entities and counts how many have nominated this entity as their leader. We normally update this
|
||||
* as people join and leave the herd, but this is a fallback to make sure we don't get stuck with an incorrect value
|
||||
* like if the entities die or whatever.
|
||||
* Checks nearby entities and counts how many have nominated this entity as their leader.
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since June 17th, 2025
|
||||
@@ -35,7 +35,7 @@ import net.minecraft.world.entity.ai.sensing.SensorType
|
||||
class CountFollowersTaskConfig : SingleTaskConfig {
|
||||
val checkTicks: ExpressionOrEntityVariable = Either.left("10".asExpression())
|
||||
|
||||
override fun getVariables(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext): List<MoLangConfigVariable> {
|
||||
override fun getVariables(entity: LivingEntity): List<MoLangConfigVariable> {
|
||||
return listOf(checkTicks).asVariables()
|
||||
}
|
||||
|
||||
@@ -43,7 +43,8 @@ class CountFollowersTaskConfig : SingleTaskConfig {
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
val checkTicksValue = checkTicks.resolveInt(behaviourConfigurationContext.runtime)
|
||||
runtime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
val checkTicksValue = checkTicks.resolveInt()
|
||||
behaviourConfigurationContext.addMemories(
|
||||
MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES,
|
||||
CobblemonMemories.HERD_SIZE,
|
||||
|
||||
+4
-4
@@ -23,14 +23,14 @@ class DoNothingTaskConfig : SingleTaskConfig {
|
||||
val condition: ExpressionOrEntityVariable = Either.left("true".asExpression())
|
||||
val minDurationTicks: ExpressionOrEntityVariable = Either.left("40".asExpression())
|
||||
val maxDurationTicks: ExpressionOrEntityVariable = Either.left("80".asExpression())
|
||||
|
||||
override fun getVariables(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext) = listOf(minDurationTicks, maxDurationTicks).asVariables()
|
||||
override fun getVariables(entity: LivingEntity) = listOf(minDurationTicks, maxDurationTicks).asVariables()
|
||||
|
||||
override fun createTask(
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
if (!condition.resolveBoolean(behaviourConfigurationContext.runtime)) return null
|
||||
return DoNothing(minDurationTicks.resolveInt(behaviourConfigurationContext.runtime), maxDurationTicks.resolveInt(behaviourConfigurationContext.runtime))
|
||||
runtime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
if (!condition.resolveBoolean()) return null
|
||||
return DoNothing(minDurationTicks.resolveInt(), maxDurationTicks.resolveInt())
|
||||
}
|
||||
}
|
||||
+3
-3
@@ -29,7 +29,7 @@ class EatGrassTaskConfig : SingleTaskConfig {
|
||||
val cooldown = numberVariable(category = EATING_GRASS, name = COOLDOWN, default = 20 * 20).asExpressible()
|
||||
val eatGrassChance = numberVariable(category = EATING_GRASS, name = EAT_GRASS_CHANCE, default = 1 / (20 * 20F)).asExpressible()
|
||||
|
||||
override fun getVariables(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext): List<MoLangConfigVariable> {
|
||||
override fun getVariables(entity: LivingEntity): List<MoLangConfigVariable> {
|
||||
return listOf(
|
||||
cooldown,
|
||||
eatGrassChance
|
||||
@@ -44,7 +44,7 @@ class EatGrassTaskConfig : SingleTaskConfig {
|
||||
return null
|
||||
}
|
||||
|
||||
val chance = eatGrassChance.resolveFloat(behaviourConfigurationContext.runtime)
|
||||
val chance = eatGrassChance.resolveFloat()
|
||||
if (chance == 0F) {
|
||||
return null
|
||||
}
|
||||
@@ -54,7 +54,7 @@ class EatGrassTaskConfig : SingleTaskConfig {
|
||||
return WrapperLivingEntityTask(
|
||||
EatGrassTask(
|
||||
chance,
|
||||
cooldown.resolveInt(behaviourConfigurationContext.runtime).toLong()
|
||||
cooldown.resolveInt().toLong()
|
||||
),
|
||||
PokemonEntity::class.java
|
||||
)
|
||||
|
||||
-38
@@ -1,38 +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.ai.config.task
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonMemories
|
||||
import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
|
||||
import com.cobblemon.mod.common.api.ai.WrapperLivingEntityTask.Companion.wrapped
|
||||
import com.cobblemon.mod.common.api.npc.configuration.MoLangConfigVariable
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.entity.pokemon.ai.tasks.EatHeldItemTask
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
|
||||
class EatHeldItemTaskConfig : SingleTaskConfig {
|
||||
override fun getVariables(
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
) = emptyList<MoLangConfigVariable>()
|
||||
|
||||
override fun createTask(
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
if (entity !is PokemonEntity) {
|
||||
return null
|
||||
}
|
||||
behaviourConfigurationContext.addMemories(
|
||||
CobblemonMemories.IS_CONSUMING_ITEM,
|
||||
)
|
||||
return EatHeldItemTask(entity).wrapped<PokemonEntity>()
|
||||
}
|
||||
}
|
||||
+4
-3
@@ -28,7 +28,7 @@ class ExitBattleWhenHurtTaskConfig : SingleTaskConfig {
|
||||
var condition = booleanVariable(SharedEntityVariables.BATTLING_CATEGORY, "exit_battle_when_hurt", true).asExpressible()
|
||||
var includePassiveDamage = booleanVariable(SharedEntityVariables.BATTLING_CATEGORY, "exit_battle_from_passive_damage", true).asExpressible()
|
||||
|
||||
override fun getVariables(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext) = listOf(
|
||||
override fun getVariables(entity: LivingEntity) = listOf(
|
||||
condition,
|
||||
includePassiveDamage
|
||||
).asVariables()
|
||||
@@ -37,9 +37,10 @@ class ExitBattleWhenHurtTaskConfig : SingleTaskConfig {
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
if (!condition.resolveBoolean(behaviourConfigurationContext.runtime)) return null
|
||||
runtime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
if (!condition.resolveBoolean()) return null
|
||||
|
||||
val includePassiveDamage = includePassiveDamage.resolveBoolean(behaviourConfigurationContext.runtime)
|
||||
val includePassiveDamage = includePassiveDamage.resolveBoolean()
|
||||
|
||||
behaviourConfigurationContext.addMemories(
|
||||
MemoryModuleType.HURT_BY,
|
||||
|
||||
+1
-1
@@ -32,7 +32,7 @@ import net.minecraft.world.level.pathfinder.PathComputationType
|
||||
*/
|
||||
class FindAirTaskConfig : SingleTaskConfig {
|
||||
val walkSpeed = numberVariable(SharedEntityVariables.MOVEMENT_CATEGORY, SharedEntityVariables.WALK_SPEED, 0.35).asExpressible()
|
||||
override fun getVariables(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext): List<MoLangConfigVariable> {
|
||||
override fun getVariables(entity: LivingEntity): List<MoLangConfigVariable> {
|
||||
return listOf(walkSpeed).asVariables()
|
||||
}
|
||||
|
||||
|
||||
+13
-13
@@ -8,16 +8,17 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.ai.config.task
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.CobblemonMemories
|
||||
import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
|
||||
import com.cobblemon.mod.common.api.ai.ExpressionOrEntityVariable
|
||||
import com.cobblemon.mod.common.api.ai.asVariables
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMostSpecificMoLangValue
|
||||
import com.cobblemon.mod.common.api.npc.configuration.MoLangConfigVariable
|
||||
import com.cobblemon.mod.common.api.storage.party.PartyStore
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.pokemon.ai.ToleratedHerdLeader
|
||||
import com.cobblemon.mod.common.util.asExpression
|
||||
import com.cobblemon.mod.common.util.withQueryValue
|
||||
import com.mojang.datafixers.util.Either
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
@@ -52,25 +53,24 @@ class FindHerdLeaderTaskConfig : SingleTaskConfig {
|
||||
it is PokemonEntity &&
|
||||
it != currentLeader &&
|
||||
it.pokemon.storeCoordinates.get()?.store !is PartyStore &&
|
||||
it.getHerdSize() < it.behaviour.herd.maxSize &&
|
||||
!it.brain.hasMemoryValue(CobblemonMemories.POKEMON_DROWSY)
|
||||
it.getHerdSize() < it.behaviour.herd.maxSize
|
||||
}.forEach { possibleLeader ->
|
||||
possibleLeader as PokemonEntity
|
||||
val bestMatchingHerdLeader = entity.behaviour.herd.bestMatchLeader(entity, possibleLeader) ?: return@forEach
|
||||
val possibleLeaderIsAlreadyALeader = possibleLeader.brain.hasMemoryValue(CobblemonMemories.HERD_SIZE)
|
||||
val currentLeaderHerdTier = currentLeaderEntity?.getHerdTier() ?: entity.getHerdTier()
|
||||
if (currentLeaderHerdTier >= bestMatchingHerdLeader.tier) {
|
||||
val matchingHerdLeader = entity.behaviour.herd.bestMatchLeader(entity, possibleLeader) ?: return@forEach
|
||||
val alreadyIsALeader = possibleLeader.brain.hasMemoryValue(CobblemonMemories.HERD_SIZE)
|
||||
val nestedHerdTier = currentLeaderEntity?.getHerdTier() ?: 0
|
||||
if (nestedHerdTier >= matchingHerdLeader.tier) {
|
||||
return@forEach // This leader is following a leader of a higher tier, we can't replace them
|
||||
}
|
||||
val distance = entity.distanceTo(possibleLeader)
|
||||
if (bestMatchingHerdLeader.tier < bestTier) {
|
||||
if (matchingHerdLeader.tier < bestTier) {
|
||||
return@forEach // No need to check further if this leader is worse than the best found so far
|
||||
} else if ((distance > bestDistance && !possibleLeaderIsAlreadyALeader) && bestMatchingHerdLeader.tier == bestTier) {
|
||||
} else if ((distance > bestDistance && !alreadyIsALeader) && matchingHerdLeader.tier == bestTier) {
|
||||
return@forEach // No need to check further if this leader is farther than the best found so far, unless they are already a leader - I'd prefer to join a pack
|
||||
} else {
|
||||
bestLeader = possibleLeader
|
||||
bestDistance = distance
|
||||
bestTier = bestMatchingHerdLeader.tier
|
||||
bestTier = matchingHerdLeader.tier
|
||||
}
|
||||
}
|
||||
return bestLeader ?: currentLeaderEntity
|
||||
@@ -80,7 +80,7 @@ class FindHerdLeaderTaskConfig : SingleTaskConfig {
|
||||
// How frequently to check for whether it should herd. Probably isn't that expensive but might use this for chance.
|
||||
val checkTicks: ExpressionOrEntityVariable = Either.left("60".asExpression())
|
||||
|
||||
override fun getVariables(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext): List<MoLangConfigVariable> {
|
||||
override fun getVariables(entity: LivingEntity): List<MoLangConfigVariable> {
|
||||
return listOf(checkTicks).asVariables()
|
||||
}
|
||||
|
||||
@@ -98,7 +98,8 @@ class FindHerdLeaderTaskConfig : SingleTaskConfig {
|
||||
MemoryModuleType.WALK_TARGET
|
||||
)
|
||||
behaviourConfigurationContext.addSensors(SensorType.NEAREST_LIVING_ENTITIES)
|
||||
val checkTicksValue = checkTicks.resolveInt(behaviourConfigurationContext.runtime)
|
||||
runtime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
val checkTicksValue = checkTicks.resolveInt()
|
||||
return BehaviorBuilder.create { instance ->
|
||||
instance.group(
|
||||
instance.present(MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES),
|
||||
@@ -118,7 +119,6 @@ class FindHerdLeaderTaskConfig : SingleTaskConfig {
|
||||
|
||||
herdLeader.set(bestLeader.uuid.toString())
|
||||
bestLeader.brain.eraseMemory(CobblemonMemories.HERD_LEADER)
|
||||
bestLeader.adjustHerdSize(1)
|
||||
return@Trigger true
|
||||
}
|
||||
}
|
||||
|
||||
+2
-13
@@ -14,34 +14,23 @@ import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
|
||||
import com.cobblemon.mod.common.api.ai.ExpressionOrEntityVariable
|
||||
import com.cobblemon.mod.common.api.ai.WrapperLivingEntityTask
|
||||
import com.cobblemon.mod.common.api.ai.asVariables
|
||||
import com.cobblemon.mod.common.api.molang.ExpressionLike
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.entity.pokemon.ai.tasks.FindRestingPlaceTask
|
||||
import com.cobblemon.mod.common.util.asExpression
|
||||
import com.cobblemon.mod.common.util.asExpressionLike
|
||||
import com.cobblemon.mod.common.util.resolveBoolean
|
||||
import com.mojang.datafixers.util.Either
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
|
||||
class FindRestingPlaceTaskConfig : SingleTaskConfig {
|
||||
val condition: ExpressionLike = "true".asExpressionLike()
|
||||
val horizontalSearchDistance: ExpressionOrEntityVariable = Either.left("16".asExpression())
|
||||
val verticalSearchDistance: ExpressionOrEntityVariable = Either.left("5".asExpression())
|
||||
|
||||
override fun getVariables(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext) = listOf(horizontalSearchDistance, verticalSearchDistance).asVariables()
|
||||
override fun getVariables(entity: LivingEntity) = listOf(horizontalSearchDistance, verticalSearchDistance).asVariables()
|
||||
override fun createTask(
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
if (entity !is PokemonEntity) {
|
||||
return null
|
||||
}
|
||||
if (!behaviourConfigurationContext.runtime.resolveBoolean(condition)) {
|
||||
return null
|
||||
}
|
||||
|
||||
behaviourConfigurationContext.addMemories(
|
||||
CobblemonMemories.PATH_COOLDOWN,
|
||||
CobblemonMemories.POKEMON_DROWSY,
|
||||
@@ -50,7 +39,7 @@ class FindRestingPlaceTaskConfig : SingleTaskConfig {
|
||||
behaviourConfigurationContext.addSensors(CobblemonSensors.POKEMON_DROWSY)
|
||||
|
||||
return WrapperLivingEntityTask(
|
||||
FindRestingPlaceTask.create(horizontalSearchDistance.resolveInt(behaviourConfigurationContext.runtime), verticalSearchDistance.resolveInt(behaviourConfigurationContext.runtime)),
|
||||
FindRestingPlaceTask.create(horizontalSearchDistance.resolveInt(), verticalSearchDistance.resolveInt()),
|
||||
PokemonEntity::class.java
|
||||
)
|
||||
}
|
||||
|
||||
+27
-18
@@ -9,36 +9,45 @@
|
||||
package com.cobblemon.mod.common.api.ai.config.task
|
||||
|
||||
import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
|
||||
import com.cobblemon.mod.common.api.ai.ExpressionOrEntityVariable
|
||||
import com.cobblemon.mod.common.api.ai.WrapperLivingEntityTask
|
||||
import com.cobblemon.mod.common.api.ai.asVariables
|
||||
import com.cobblemon.mod.common.api.npc.configuration.MoLangConfigVariable
|
||||
import com.cobblemon.mod.common.entity.ai.FleeFromAttackerTask
|
||||
import com.cobblemon.mod.common.util.asExpression
|
||||
import com.mojang.datafixers.util.Either
|
||||
import com.cobblemon.mod.common.api.ai.config.task.SharedEntityVariables.FLEE_DESIRED_DISTANCE
|
||||
import com.cobblemon.mod.common.api.ai.config.task.SharedEntityVariables.FLEE_SPEED_MULTIPLIER
|
||||
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.PathfinderMob
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
import net.minecraft.world.entity.ai.behavior.SetWalkTargetAwayFrom
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
import net.minecraft.world.entity.ai.sensing.SensorType
|
||||
|
||||
class FleeAttackerTaskConfig : SingleTaskConfig {
|
||||
val avoidDurationTicks: ExpressionOrEntityVariable = Either.left("600".asExpression())
|
||||
var condition = booleanVariable(SharedEntityVariables.FEAR_CATEGORY, "flee_attacker", true).asExpressible()
|
||||
var speedMultiplier = numberVariable(SharedEntityVariables.FEAR_CATEGORY, FLEE_SPEED_MULTIPLIER, 0.5).asExpressible()
|
||||
var desiredDistance = numberVariable(SharedEntityVariables.FEAR_CATEGORY, FLEE_DESIRED_DISTANCE, 9).asExpressible()
|
||||
|
||||
override fun getVariables(
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
): List<MoLangConfigVariable> {
|
||||
return listOf(avoidDurationTicks).asVariables()
|
||||
}
|
||||
override fun getVariables(entity: LivingEntity) = listOf(
|
||||
condition,
|
||||
speedMultiplier,
|
||||
desiredDistance
|
||||
).asVariables()
|
||||
|
||||
override fun createTask(
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
): BehaviorControl<in LivingEntity> {
|
||||
behaviourConfigurationContext.addMemories(
|
||||
MemoryModuleType.HURT_BY_ENTITY,
|
||||
MemoryModuleType.AVOID_TARGET
|
||||
)
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
runtime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
if (!condition.resolveBoolean() || entity !is PathfinderMob) return null
|
||||
|
||||
behaviourConfigurationContext.addMemories(MemoryModuleType.HURT_BY_ENTITY, MemoryModuleType.WALK_TARGET)
|
||||
behaviourConfigurationContext.addSensors(SensorType.HURT_BY)
|
||||
return FleeFromAttackerTask.create(avoidDurationTicks.asExpression())
|
||||
|
||||
val speedMultiplier = speedMultiplier.resolveFloat()
|
||||
val desiredDistance = desiredDistance.resolveInt()
|
||||
return WrapperLivingEntityTask(
|
||||
SetWalkTargetAwayFrom.entity(MemoryModuleType.HURT_BY_ENTITY, speedMultiplier, desiredDistance, false),
|
||||
PathfinderMob::class.java
|
||||
)
|
||||
}
|
||||
}
|
||||
+5
-4
@@ -27,17 +27,18 @@ class FleeNearestHostileTaskConfig : SingleTaskConfig {
|
||||
var speedMultiplier = numberVariable(SharedEntityVariables.FEAR_CATEGORY, FLEE_SPEED_MULTIPLIER, 0.5).asExpressible()
|
||||
var desiredDistance = numberVariable(SharedEntityVariables.FEAR_CATEGORY, FLEE_DESIRED_DISTANCE, 9).asExpressible()
|
||||
|
||||
override fun getVariables(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext) = listOf(condition, speedMultiplier, desiredDistance).asVariables()
|
||||
override fun getVariables(entity: LivingEntity) = listOf(condition, speedMultiplier, desiredDistance).asVariables()
|
||||
|
||||
override fun createTask(
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
if (!condition.resolveBoolean(behaviourConfigurationContext.runtime) || entity !is PathfinderMob) return null
|
||||
runtime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
if (!condition.resolveBoolean() || entity !is PathfinderMob) return null
|
||||
behaviourConfigurationContext.addMemories(MemoryModuleType.NEAREST_HOSTILE, MemoryModuleType.WALK_TARGET)
|
||||
behaviourConfigurationContext.addSensors(SensorType.VILLAGER_HOSTILES)
|
||||
val speedMultiplier = speedMultiplier.resolveFloat(behaviourConfigurationContext.runtime)
|
||||
val desiredDistance = desiredDistance.resolveInt(behaviourConfigurationContext.runtime)
|
||||
val speedMultiplier = speedMultiplier.resolveFloat()
|
||||
val desiredDistance = desiredDistance.resolveInt()
|
||||
return WrapperLivingEntityTask(
|
||||
SetWalkTargetAwayFrom.entity(MemoryModuleType.NEAREST_HOSTILE, speedMultiplier, desiredDistance, false),
|
||||
PathfinderMob::class.java
|
||||
|
||||
+8
-7
@@ -38,7 +38,7 @@ class FlyInCirclesTaskConfig : SingleTaskConfig {
|
||||
val minDurationTicks: ExpressionOrEntityVariable = Either.left("60".asExpression())
|
||||
val maxDurationTicks: ExpressionOrEntityVariable = Either.left("180".asExpression())
|
||||
|
||||
override fun getVariables(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext): List<MoLangConfigVariable> {
|
||||
override fun getVariables(entity: LivingEntity): List<MoLangConfigVariable> {
|
||||
return listOf(
|
||||
minAngularVelocityDegrees,
|
||||
maxAngularVelocityDegrees,
|
||||
@@ -57,14 +57,15 @@ class FlyInCirclesTaskConfig : SingleTaskConfig {
|
||||
return null
|
||||
}
|
||||
behaviourConfigurationContext.addMemories(MemoryModuleType.WALK_TARGET, MemoryModuleType.PATH)
|
||||
runtime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
return CircleAroundTask(
|
||||
poseTypes = poseTypes,
|
||||
minTurnAngleDegrees = minAngularVelocityDegrees.resolveFloat(behaviourConfigurationContext.runtime),
|
||||
maxTurnAngleDegrees = maxAngularVelocityDegrees.resolveFloat(behaviourConfigurationContext.runtime),
|
||||
speed = speed.resolveFloat(behaviourConfigurationContext.runtime),
|
||||
verticalSpeed = verticalSpeed.resolveFloat(behaviourConfigurationContext.runtime),
|
||||
minDurationTicks = minDurationTicks.resolveFloat(behaviourConfigurationContext.runtime).toInt(),
|
||||
maxDurationTicks = maxDurationTicks.resolveFloat(behaviourConfigurationContext.runtime).toInt()
|
||||
minTurnAngleDegrees = minAngularVelocityDegrees.resolveFloat(),
|
||||
maxTurnAngleDegrees = maxAngularVelocityDegrees.resolveFloat(),
|
||||
speed = speed.resolveFloat(),
|
||||
verticalSpeed = verticalSpeed.resolveFloat(),
|
||||
minDurationTicks = minDurationTicks.resolveFloat().toInt(),
|
||||
maxDurationTicks = maxDurationTicks.resolveFloat().toInt()
|
||||
).wrapped<PokemonEntity>()
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -19,7 +19,7 @@ import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
|
||||
class FollowHerdLeaderTaskConfig : SingleTaskConfig {
|
||||
override fun getVariables(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext): List<MoLangConfigVariable> {
|
||||
override fun getVariables(entity: LivingEntity): List<MoLangConfigVariable> {
|
||||
return listOf()
|
||||
}
|
||||
|
||||
|
||||
+3
-2
@@ -27,12 +27,13 @@ class FollowWalkTargetTaskConfig : SingleTaskConfig {
|
||||
val minRunTicks: ExpressionOrEntityVariable = Either.left("150".asExpression())
|
||||
val maxRunTicks: ExpressionOrEntityVariable = Either.left("250".asExpression())
|
||||
|
||||
override fun getVariables(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext) = listOf(minRunTicks, maxRunTicks).asVariables()
|
||||
override fun getVariables(entity: LivingEntity) = listOf(minRunTicks, maxRunTicks).asVariables()
|
||||
|
||||
override fun createTask(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext): BehaviorControl<LivingEntity>? {
|
||||
runtime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
behaviourConfigurationContext.addMemories(MemoryModuleType.WALK_TARGET, MemoryModuleType.PATH, MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE)
|
||||
return WrapperLivingEntityTask(
|
||||
FollowWalkTargetTask(minRunTicks.resolveInt(behaviourConfigurationContext.runtime), maxRunTicks.resolveInt(behaviourConfigurationContext.runtime)),
|
||||
FollowWalkTargetTask(minRunTicks.resolveInt(), maxRunTicks.resolveInt()),
|
||||
PathfinderMob::class.java
|
||||
)
|
||||
}
|
||||
|
||||
+3
-2
@@ -26,13 +26,14 @@ class GetAngryAtAttackerTaskConfig : SingleTaskConfig {
|
||||
|
||||
val condition = booleanVariable(ATTACKING_CATEGORY, GET_ANGRY_AT_ATTACKER, true).asExpressible()
|
||||
|
||||
override fun getVariables(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext) = listOf(condition).asVariables()
|
||||
override fun getVariables(entity: LivingEntity) = listOf(condition).asVariables()
|
||||
|
||||
override fun createTask(
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
if (!condition.resolveBoolean(behaviourConfigurationContext.runtime)) return null
|
||||
runtime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
if (!condition.resolveBoolean()) return null
|
||||
behaviourConfigurationContext.addMemories(
|
||||
MemoryModuleType.HURT_BY_ENTITY,
|
||||
MemoryModuleType.ANGRY_AT,
|
||||
|
||||
+3
-2
@@ -30,7 +30,7 @@ class GoToHealingMachineTaskConfig : SingleTaskConfig {
|
||||
val completionRange: ExpressionOrEntityVariable = Either.left("1".asExpression())
|
||||
val walkSpeed = numberVariable(SharedEntityVariables.MOVEMENT_CATEGORY, SharedEntityVariables.WALK_SPEED, 0.35).asExpressible()
|
||||
|
||||
override fun getVariables(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext) = listOf(condition, walkSpeed, horizontalSearchRange, verticalSearchRange, completionRange).asVariables()
|
||||
override fun getVariables(entity: LivingEntity) = listOf(condition, walkSpeed, horizontalSearchRange, verticalSearchRange, completionRange).asVariables()
|
||||
|
||||
companion object {
|
||||
const val SELF_HEALING = "self_healing"
|
||||
@@ -41,7 +41,8 @@ class GoToHealingMachineTaskConfig : SingleTaskConfig {
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
if (!condition.resolveBoolean(behaviourConfigurationContext.runtime)) return null
|
||||
runtime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
if (!condition.resolveBoolean()) return null
|
||||
behaviourConfigurationContext.addMemories(
|
||||
MemoryModuleType.WALK_TARGET,
|
||||
MemoryModuleType.LOOK_TARGET,
|
||||
|
||||
+2
-6
@@ -11,12 +11,9 @@ package com.cobblemon.mod.common.api.ai.config.task
|
||||
import com.cobblemon.mod.common.CobblemonMemories
|
||||
import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
|
||||
import com.cobblemon.mod.common.api.ai.asVariables
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMostSpecificMoLangValue
|
||||
import com.cobblemon.mod.common.api.npc.configuration.MoLangConfigVariable
|
||||
import com.cobblemon.mod.common.entity.OmniPathingEntity
|
||||
import com.cobblemon.mod.common.util.closestPosition
|
||||
import com.cobblemon.mod.common.util.mainThreadRuntime
|
||||
import com.cobblemon.mod.common.util.withQueryValue
|
||||
import kotlin.math.ceil
|
||||
import kotlin.math.floor
|
||||
import net.minecraft.core.BlockPos
|
||||
@@ -36,7 +33,7 @@ import net.minecraft.world.level.pathfinder.PathComputationType
|
||||
*/
|
||||
class GoToLandTaskConfig : SingleTaskConfig {
|
||||
val walkSpeed = numberVariable(SharedEntityVariables.MOVEMENT_CATEGORY, SharedEntityVariables.WALK_SPEED, 0.35).asExpressible()
|
||||
override fun getVariables(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext): List<MoLangConfigVariable> {
|
||||
override fun getVariables(entity: LivingEntity): List<MoLangConfigVariable> {
|
||||
return listOf(walkSpeed).asVariables()
|
||||
}
|
||||
|
||||
@@ -63,8 +60,7 @@ class GoToLandTaskConfig : SingleTaskConfig {
|
||||
|
||||
entity as PathfinderMob
|
||||
|
||||
mainThreadRuntime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
val walkSpeedValue = walkSpeed.resolveFloat(mainThreadRuntime)
|
||||
val walkSpeedValue = walkSpeed.resolveFloat()
|
||||
|
||||
val iterable = BlockPos.betweenClosed(
|
||||
Mth.floor(entity.x - 8.0),
|
||||
|
||||
+2
-7
@@ -11,21 +11,16 @@ package com.cobblemon.mod.common.api.ai.config.task
|
||||
import com.cobblemon.mod.common.CobblemonMemories
|
||||
import com.cobblemon.mod.common.CobblemonSensors
|
||||
import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
|
||||
import com.cobblemon.mod.common.api.ai.ExpressionOrEntityVariable
|
||||
import com.cobblemon.mod.common.api.ai.WrapperLivingEntityTask
|
||||
import com.cobblemon.mod.common.api.npc.configuration.MoLangConfigVariable
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.entity.pokemon.ai.tasks.GoToSleepTask
|
||||
import com.cobblemon.mod.common.util.asExpression
|
||||
import com.cobblemon.mod.common.util.resolveBoolean
|
||||
import com.mojang.datafixers.util.Either
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
|
||||
class GoToSleepTaskConfig : SingleTaskConfig {
|
||||
var onlyFromStatus: ExpressionOrEntityVariable = Either.left("false".asExpression())
|
||||
override fun getVariables(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext) = emptyList<MoLangConfigVariable>()
|
||||
override fun getVariables(entity: LivingEntity) = emptyList<MoLangConfigVariable>()
|
||||
override fun createTask(
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
@@ -39,6 +34,6 @@ class GoToSleepTaskConfig : SingleTaskConfig {
|
||||
CobblemonMemories.POKEMON_SLEEPING
|
||||
)
|
||||
behaviourConfigurationContext.addSensors(CobblemonSensors.POKEMON_DROWSY)
|
||||
return WrapperLivingEntityTask(GoToSleepTask.create(onlyFromStatus.resolveBoolean(behaviourConfigurationContext.runtime)), PokemonEntity::class.java)
|
||||
return WrapperLivingEntityTask(GoToSleepTask.create(), PokemonEntity::class.java)
|
||||
}
|
||||
}
|
||||
-39
@@ -1,39 +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.ai.config.task
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonMemories
|
||||
import com.cobblemon.mod.common.CobblemonSensors
|
||||
import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
|
||||
import com.cobblemon.mod.common.api.npc.configuration.MoLangConfigVariable
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.entity.pokemon.ai.tasks.HarvestSweetBerryBushTask
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
|
||||
class HarvestSweetBerryBushTaskConfig : SingleTaskConfig {
|
||||
override fun getVariables(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext) = emptyList<MoLangConfigVariable>()
|
||||
override fun createTask(
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
if (entity !is PokemonEntity) {
|
||||
return null
|
||||
}
|
||||
behaviourConfigurationContext.addMemories(
|
||||
CobblemonMemories.NEARBY_SWEET_BERRY_BUSH,
|
||||
CobblemonMemories.DISABLE_WALK_TO_BERRY_BUSH,
|
||||
CobblemonMemories.TIME_TRYING_TO_REACH_BERRY_BUSH,
|
||||
MemoryModuleType.WALK_TARGET,
|
||||
MemoryModuleType.LOOK_TARGET)
|
||||
behaviourConfigurationContext.addSensors(CobblemonSensors.NEARBY_SWEET_BERRY_BUSH)
|
||||
return HarvestSweetBerryBushTask()
|
||||
}
|
||||
}
|
||||
+4
-5
@@ -14,7 +14,6 @@ import com.cobblemon.mod.common.api.ai.ExpressionOrEntityVariable
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMostSpecificMoLangValue
|
||||
import com.cobblemon.mod.common.api.npc.configuration.MoLangConfigVariable
|
||||
import com.cobblemon.mod.common.util.asExpression
|
||||
import com.cobblemon.mod.common.util.mainThreadRuntime
|
||||
import com.cobblemon.mod.common.util.resolveBoolean
|
||||
import com.cobblemon.mod.common.util.withQueryValue
|
||||
import com.mojang.datafixers.util.Either
|
||||
@@ -35,12 +34,12 @@ class HateEntityTaskConfig : SingleTaskConfig {
|
||||
val entityCondition: Expression = "true".asExpression()
|
||||
val range: ExpressionOrEntityVariable = Either.left("24".asExpression())
|
||||
|
||||
override fun getVariables(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext) = emptyList<MoLangConfigVariable>()
|
||||
override fun getVariables(entity: LivingEntity) = emptyList<MoLangConfigVariable>()
|
||||
override fun createTask(
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
val range = range.resolveFloat(behaviourConfigurationContext.runtime)
|
||||
val range = range.resolveFloat()
|
||||
behaviourConfigurationContext.addMemories(
|
||||
MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES,
|
||||
MemoryModuleType.ANGRY_AT
|
||||
@@ -53,8 +52,8 @@ class HateEntityTaskConfig : SingleTaskConfig {
|
||||
).apply(instance) { entities, angryAt ->
|
||||
Trigger { world, entity, _ ->
|
||||
val target = instance.get(entities).findClosest {
|
||||
mainThreadRuntime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
return@findClosest mainThreadRuntime.resolveBoolean(entityCondition)
|
||||
runtime.withQueryValue("entity", it.asMostSpecificMoLangValue())
|
||||
return@findClosest runtime.resolveBoolean(entityCondition)
|
||||
}.orElse(null)
|
||||
|
||||
if (target != null && target.distanceTo(entity) <= range) {
|
||||
|
||||
+3
-2
@@ -29,13 +29,14 @@ class HealUsingHealingMachineTaskConfig : SingleTaskConfig {
|
||||
val horizontalUseRange: ExpressionOrEntityVariable = Either.left("2".asExpression())
|
||||
val verticalUseRange: ExpressionOrEntityVariable = Either.left("1".asExpression())
|
||||
|
||||
override fun getVariables(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext) = listOf(condition, horizontalUseRange, verticalUseRange).asVariables()
|
||||
override fun getVariables(entity: LivingEntity) = listOf(condition, horizontalUseRange, verticalUseRange).asVariables()
|
||||
|
||||
override fun createTask(
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
if (!condition.resolveBoolean(behaviourConfigurationContext.runtime)) return null
|
||||
runtime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
if (!condition.resolveBoolean()) return null
|
||||
behaviourConfigurationContext.addMemories(MemoryModuleType.WALK_TARGET, CobblemonMemories.NPC_BATTLING,)
|
||||
behaviourConfigurationContext.addSensors(CobblemonSensors.NPC_BATTLING)
|
||||
return HealUsingHealingMachineTask(horizontalUseRange.asExpression(), verticalUseRange.asExpression())
|
||||
|
||||
+7
-5
@@ -8,14 +8,15 @@
|
||||
|
||||
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.CobblemonSensors
|
||||
import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
|
||||
import com.cobblemon.mod.common.api.ai.ExpressionOrEntityVariable
|
||||
import com.cobblemon.mod.common.api.ai.asVariables
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMostSpecificMoLangValue
|
||||
import com.cobblemon.mod.common.entity.npc.ai.LookAtBattlingPokemonTask
|
||||
import com.cobblemon.mod.common.util.asExpression
|
||||
import com.cobblemon.mod.common.util.withQueryValue
|
||||
import com.mojang.datafixers.util.Either
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
@@ -30,7 +31,7 @@ class LookAtBattlingPokemonTaskConfig : SingleTaskConfig {
|
||||
val minDurationTicks: ExpressionOrEntityVariable = Either.left("40".asExpression())
|
||||
val maxDurationTicks: ExpressionOrEntityVariable = Either.left("80".asExpression())
|
||||
|
||||
override fun getVariables(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext) = listOf(
|
||||
override fun getVariables(entity: LivingEntity) = listOf(
|
||||
condition,
|
||||
minDurationTicks,
|
||||
maxDurationTicks
|
||||
@@ -40,15 +41,16 @@ class LookAtBattlingPokemonTaskConfig : SingleTaskConfig {
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
if (!resolveBooleanVariable(LOOK_AT_BATTLING_POKEMON, behaviourConfigurationContext.runtime)) return null
|
||||
runtime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
if (!resolveBooleanVariable(LOOK_AT_BATTLING_POKEMON)) return null
|
||||
behaviourConfigurationContext.addMemories(
|
||||
MemoryModuleType.LOOK_TARGET,
|
||||
CobblemonMemories.BATTLING_POKEMON
|
||||
)
|
||||
behaviourConfigurationContext.addSensors(CobblemonSensors.BATTLING_POKEMON)
|
||||
return LookAtBattlingPokemonTask.create(
|
||||
minDurationTicks = minDurationTicks.resolveInt(behaviourConfigurationContext.runtime),
|
||||
maxDurationTicks = maxDurationTicks.resolveInt(behaviourConfigurationContext.runtime)
|
||||
minDurationTicks = minDurationTicks.resolveInt(),
|
||||
maxDurationTicks = maxDurationTicks.resolveInt()
|
||||
)
|
||||
}
|
||||
}
|
||||
+4
-3
@@ -27,7 +27,7 @@ class LookAtEntitiesTaskConfig : SingleTaskConfig {
|
||||
val condition = booleanVariable(SharedEntityVariables.LOOKING_CATEGORY, LOOK_AT_ENTITIES, true).asExpressible()
|
||||
val maxDistance = numberVariable(SharedEntityVariables.LOOKING_CATEGORY, SEE_DISTANCE, 15).asExpressible()
|
||||
|
||||
override fun getVariables(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext) = listOf(
|
||||
override fun getVariables(entity: LivingEntity) = listOf(
|
||||
condition,
|
||||
maxDistance
|
||||
).asVariables()
|
||||
@@ -36,9 +36,10 @@ class LookAtEntitiesTaskConfig : SingleTaskConfig {
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
if (!condition.resolveBoolean(behaviourConfigurationContext.runtime)) return null
|
||||
runtime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
if (!condition.resolveBoolean()) return null
|
||||
behaviourConfigurationContext.addMemories(MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES, MemoryModuleType.LOOK_TARGET)
|
||||
behaviourConfigurationContext.addSensors(SensorType.NEAREST_LIVING_ENTITIES)
|
||||
return SetEntityLookTarget.create(maxDistance.resolveFloat(behaviourConfigurationContext.runtime))
|
||||
return SetEntityLookTarget.create(maxDistance.resolveFloat())
|
||||
}
|
||||
}
|
||||
+3
-14
@@ -10,28 +10,17 @@ package com.cobblemon.mod.common.api.ai.config.task
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonMemories
|
||||
import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
|
||||
import com.cobblemon.mod.common.api.ai.ExpressionOrEntityVariable
|
||||
import com.cobblemon.mod.common.api.npc.configuration.MoLangConfigVariable
|
||||
import com.cobblemon.mod.common.entity.npc.ai.LookAtSpeakerTask
|
||||
import com.cobblemon.mod.common.util.asExpression
|
||||
import com.mojang.datafixers.util.Either
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
|
||||
class LookAtSpeakerTaskConfig : SingleTaskConfig {
|
||||
val condition: ExpressionOrEntityVariable = Either.left("true".asExpression())
|
||||
override fun getVariables(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext) = emptyList<MoLangConfigVariable>()
|
||||
override fun getVariables(entity: LivingEntity) = emptyList<MoLangConfigVariable>()
|
||||
override fun createTask(
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
if (!condition.resolveBoolean(behaviourConfigurationContext.runtime)) {
|
||||
return null
|
||||
}
|
||||
|
||||
return LookAtSpeakerTask.create().also {
|
||||
behaviourConfigurationContext.addMemories(MemoryModuleType.LOOK_TARGET, CobblemonMemories.DIALOGUES)
|
||||
}
|
||||
) = LookAtSpeakerTask.create().also {
|
||||
behaviourConfigurationContext.addMemories(MemoryModuleType.LOOK_TARGET, CobblemonMemories.DIALOGUES)
|
||||
}
|
||||
}
|
||||
+4
-3
@@ -28,7 +28,7 @@ class LookAtTargetTaskConfig : SingleTaskConfig {
|
||||
val minDurationTicks: ExpressionOrEntityVariable = Either.left("80".asExpression())
|
||||
val maxDurationTicks: ExpressionOrEntityVariable = Either.left("160".asExpression())
|
||||
|
||||
override fun getVariables(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext) = listOf(
|
||||
override fun getVariables(entity: LivingEntity) = listOf(
|
||||
condition,
|
||||
minDurationTicks,
|
||||
maxDurationTicks
|
||||
@@ -38,9 +38,10 @@ class LookAtTargetTaskConfig : SingleTaskConfig {
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
if (!condition.resolveBoolean(behaviourConfigurationContext.runtime)) return null
|
||||
runtime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
if (!condition.resolveBoolean()) return null
|
||||
behaviourConfigurationContext.addMemories(MemoryModuleType.LOOK_TARGET, MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES)
|
||||
behaviourConfigurationContext.addSensors(SensorType.NEAREST_LIVING_ENTITIES)
|
||||
return WrapperLivingEntityTask(LookAtTargetSink(minDurationTicks.resolveInt(behaviourConfigurationContext.runtime), maxDurationTicks.resolveInt(behaviourConfigurationContext.runtime)), Mob::class.java)
|
||||
return WrapperLivingEntityTask(LookAtTargetSink(minDurationTicks.resolveInt(), maxDurationTicks.resolveInt()), Mob::class.java)
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -19,7 +19,7 @@ import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
|
||||
class LookAtTargetedBattlePokemonTaskConfig : SingleTaskConfig {
|
||||
override fun getVariables(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext) = emptyList<MoLangConfigVariable>()
|
||||
override fun getVariables(entity: LivingEntity) = emptyList<MoLangConfigVariable>()
|
||||
override fun createTask(
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
|
||||
+1
-1
@@ -20,7 +20,7 @@ class LookInDirectionTaskConfig : SingleTaskConfig {
|
||||
var yaw = numberVariable(LOOKING_CATEGORY, "locked_yaw", 0F).asExpressible()
|
||||
var pitch = numberVariable(LOOKING_CATEGORY, "locked_pitch", 0F).asExpressible()
|
||||
|
||||
override fun getVariables(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext) = listOf(
|
||||
override fun getVariables(entity: LivingEntity) = listOf(
|
||||
condition,
|
||||
yaw,
|
||||
pitch
|
||||
|
||||
+5
-5
@@ -8,14 +8,15 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.ai.config.task
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.CobblemonMemories
|
||||
import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
|
||||
import com.cobblemon.mod.common.api.ai.ExpressionOrEntityVariable
|
||||
import com.cobblemon.mod.common.api.ai.asVariables
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMostSpecificMoLangValue
|
||||
import com.cobblemon.mod.common.api.npc.configuration.MoLangConfigVariable
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.util.asExpression
|
||||
import com.cobblemon.mod.common.util.withQueryValue
|
||||
import com.mojang.datafixers.util.Either
|
||||
import java.util.UUID
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
@@ -36,7 +37,7 @@ class MaintainHerdLeaderTaskConfig : SingleTaskConfig {
|
||||
// How frequently to check for a better herd leader
|
||||
val checkTicks: ExpressionOrEntityVariable = Either.left("60".asExpression())
|
||||
|
||||
override fun getVariables(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext): List<MoLangConfigVariable> {
|
||||
override fun getVariables(entity: LivingEntity): List<MoLangConfigVariable> {
|
||||
return listOf(checkTicks).asVariables()
|
||||
}
|
||||
|
||||
@@ -52,7 +53,8 @@ class MaintainHerdLeaderTaskConfig : SingleTaskConfig {
|
||||
MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES,
|
||||
)
|
||||
behaviourConfigurationContext.addSensors(SensorType.NEAREST_LIVING_ENTITIES)
|
||||
val checkTicks = checkTicks.resolveInt(behaviourConfigurationContext.runtime)
|
||||
runtime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
val checkTicks = checkTicks.resolveInt()
|
||||
return BehaviorBuilder.create { instance ->
|
||||
instance.group(
|
||||
instance.present(CobblemonMemories.HERD_LEADER),
|
||||
@@ -81,8 +83,6 @@ class MaintainHerdLeaderTaskConfig : SingleTaskConfig {
|
||||
if (bestLeader != null && bestLeader != leader) {
|
||||
bestLeader.brain.eraseMemory(CobblemonMemories.HERD_LEADER)
|
||||
entity.brain.setMemory(CobblemonMemories.HERD_LEADER, bestLeader.uuid.toString())
|
||||
bestLeader.adjustHerdSize(1)
|
||||
leader.adjustHerdSize(-1)
|
||||
}
|
||||
}
|
||||
return@Trigger true
|
||||
|
||||
+1
-1
@@ -17,7 +17,7 @@ import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
|
||||
class ManageFlightInBattleTaskConfig : SingleTaskConfig {
|
||||
override fun getVariables(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext) = emptyList<MoLangConfigVariable>()
|
||||
override fun getVariables(entity: LivingEntity) = emptyList<MoLangConfigVariable>()
|
||||
override fun createTask(
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
|
||||
+3
-2
@@ -22,7 +22,7 @@ class MeleeAttackTaskConfig : SingleTaskConfig {
|
||||
val range = numberVariable(SharedEntityVariables.ATTACKING_CATEGORY, "melee_range", 1.5F).asExpressible()
|
||||
val cooldownTicks = numberVariable(SharedEntityVariables.ATTACKING_CATEGORY, "melee_cooldown", 20).asExpressible()
|
||||
|
||||
override fun getVariables(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext) = listOf(
|
||||
override fun getVariables(entity: LivingEntity) = listOf(
|
||||
condition,
|
||||
range,
|
||||
cooldownTicks
|
||||
@@ -32,7 +32,8 @@ class MeleeAttackTaskConfig : SingleTaskConfig {
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
if (!condition.resolveBoolean(behaviourConfigurationContext.runtime)) return null
|
||||
runtime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
if (!condition.resolveBoolean()) return null
|
||||
behaviourConfigurationContext.addMemories(
|
||||
MemoryModuleType.ATTACK_TARGET,
|
||||
MemoryModuleType.ATTACK_COOLING_DOWN
|
||||
|
||||
+2
-4
@@ -9,7 +9,6 @@
|
||||
package com.cobblemon.mod.common.api.ai.config.task
|
||||
|
||||
import com.bedrockk.molang.ast.StringExpression
|
||||
import com.bedrockk.molang.runtime.MoLangRuntime
|
||||
import com.bedrockk.molang.runtime.value.StringValue
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
|
||||
@@ -17,7 +16,6 @@ import com.cobblemon.mod.common.api.ai.ExpressionOrEntityVariable
|
||||
import com.cobblemon.mod.common.api.ai.asVariables
|
||||
import com.cobblemon.mod.common.entity.npc.NPCEntity
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.util.resolveString
|
||||
import com.mojang.datafixers.util.Either
|
||||
import net.minecraft.server.level.ServerLevel
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
@@ -37,7 +35,7 @@ class MemoryAspectTaskConfig : SingleTaskConfig {
|
||||
var memory: MemoryModuleType<*> = MemoryModuleType.DUMMY
|
||||
var aspect: ExpressionOrEntityVariable = Either.left(StringExpression(StringValue("")))
|
||||
|
||||
override fun getVariables(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext) = listOf(aspect).asVariables()
|
||||
override fun getVariables(entity: LivingEntity) = listOf(aspect).asVariables()
|
||||
override fun createTask(
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
@@ -52,7 +50,7 @@ class MemoryAspectTaskConfig : SingleTaskConfig {
|
||||
return null
|
||||
}
|
||||
|
||||
val aspect = behaviourConfigurationContext.runtime.resolveString(aspect.asExpression())
|
||||
val aspect = aspect.resolveString()
|
||||
|
||||
return object : Behavior<LivingEntity>(
|
||||
mapOf(memory to MemoryStatus.REGISTERED),
|
||||
|
||||
+11
-8
@@ -12,10 +12,12 @@ import com.cobblemon.mod.common.CobblemonMemories
|
||||
import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
|
||||
import com.cobblemon.mod.common.api.ai.ExpressionOrEntityVariable
|
||||
import com.cobblemon.mod.common.api.ai.asVariables
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMostSpecificMoLangValue
|
||||
import com.cobblemon.mod.common.api.npc.configuration.MoLangConfigVariable
|
||||
import com.cobblemon.mod.common.entity.ai.CobblemonWalkTarget
|
||||
import com.cobblemon.mod.common.util.asExpression
|
||||
import com.cobblemon.mod.common.util.closestPosition
|
||||
import com.cobblemon.mod.common.util.withQueryValue
|
||||
import com.mojang.datafixers.util.Either
|
||||
import java.util.function.Predicate
|
||||
import net.minecraft.core.BlockPos
|
||||
@@ -44,7 +46,7 @@ class MoveIntoFluidTaskConfig : SingleTaskConfig {
|
||||
val horizontalSearchRange: ExpressionOrEntityVariable = Either.left("8".asExpression())
|
||||
val verticalSearchRange: ExpressionOrEntityVariable = Either.left("8".asExpression())
|
||||
|
||||
override fun getVariables(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext): List<MoLangConfigVariable> {
|
||||
override fun getVariables(entity: LivingEntity): List<MoLangConfigVariable> {
|
||||
return listOf(
|
||||
condition,
|
||||
movesIntoWater,
|
||||
@@ -59,22 +61,23 @@ class MoveIntoFluidTaskConfig : SingleTaskConfig {
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
if (!condition.resolveBoolean(behaviourConfigurationContext.runtime)) return null
|
||||
runtime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
if (!condition.resolveBoolean()) return null
|
||||
behaviourConfigurationContext.addMemories(
|
||||
MemoryModuleType.WALK_TARGET,
|
||||
CobblemonMemories.PATH_COOLDOWN
|
||||
)
|
||||
val movesIntoWater = this@MoveIntoFluidTaskConfig.movesIntoWater.resolveBoolean(behaviourConfigurationContext.runtime)
|
||||
val movesIntoLava = movesIntoLava.resolveBoolean(behaviourConfigurationContext.runtime)
|
||||
val speedModifier = speedModifier.resolveFloat(behaviourConfigurationContext.runtime)
|
||||
val horizontalSearchRange = horizontalSearchRange.resolveInt(behaviourConfigurationContext.runtime)
|
||||
val verticalSearchRange = verticalSearchRange.resolveInt(behaviourConfigurationContext.runtime)
|
||||
val movesIntoWater = this@MoveIntoFluidTaskConfig.movesIntoWater.resolveBoolean()
|
||||
val movesIntoLava = movesIntoLava.resolveBoolean()
|
||||
val speedModifier = speedModifier.resolveFloat()
|
||||
val horizontalSearchRange = horizontalSearchRange.resolveInt()
|
||||
val verticalSearchRange = verticalSearchRange.resolveInt()
|
||||
return BehaviorBuilder.create {
|
||||
it.group(
|
||||
it.absent(MemoryModuleType.WALK_TARGET),
|
||||
it.absent(CobblemonMemories.PATH_COOLDOWN)
|
||||
).apply(it) { walkTarget, pathCooldown ->
|
||||
Trigger { _, entity, _ ->
|
||||
Trigger { world, entity, _ ->
|
||||
val isInWater = entity.isInWater
|
||||
val isInLava = entity.isInLava
|
||||
// If it's already in a place it wants to be, then we're fine.
|
||||
|
||||
+1
-1
@@ -21,7 +21,7 @@ class MoveToAttackTargetTaskConfig : SingleTaskConfig {
|
||||
val speedMultiplier = numberVariable(SharedEntityVariables.ATTACKING_CATEGORY, "attacking_movement_speed", 0.5).asExpressible()
|
||||
val closeEnoughDistance: ExpressionOrEntityVariable = Either.left("0".asExpression())
|
||||
|
||||
override fun getVariables(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext) = listOf(
|
||||
override fun getVariables(entity: LivingEntity) = listOf(
|
||||
speedMultiplier,
|
||||
closeEnoughDistance
|
||||
).asVariables()
|
||||
|
||||
-58
@@ -1,58 +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.ai.config.task
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonMemories
|
||||
import com.cobblemon.mod.common.CobblemonSensors
|
||||
import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
|
||||
import com.cobblemon.mod.common.api.ai.ExpressionOrEntityVariable
|
||||
import com.cobblemon.mod.common.api.ai.WrapperLivingEntityTask
|
||||
import com.cobblemon.mod.common.api.ai.asVariables
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.entity.pokemon.ai.tasks.MoveToItemTask
|
||||
import com.cobblemon.mod.common.util.asExpression
|
||||
import com.mojang.datafixers.util.Either
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
|
||||
class MoveToItemTaskConfig : SingleTaskConfig {
|
||||
val condition: ExpressionOrEntityVariable = Either.left("true".asExpression())
|
||||
var speedMultiplier: ExpressionOrEntityVariable = Either.left("0.6".asExpression())
|
||||
var maxDistance: ExpressionOrEntityVariable = Either.left("7.0".asExpression())
|
||||
|
||||
override fun getVariables(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext) = listOf(
|
||||
condition,
|
||||
speedMultiplier,
|
||||
maxDistance
|
||||
).asVariables()
|
||||
|
||||
override fun createTask(
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
behaviourConfigurationContext.addMemories(
|
||||
MemoryModuleType.NEAREST_VISIBLE_WANTED_ITEM,
|
||||
MemoryModuleType.WALK_TARGET,
|
||||
MemoryModuleType.LOOK_TARGET,
|
||||
CobblemonMemories.TIME_TRYING_TO_REACH_WANTED_ITEM,
|
||||
CobblemonMemories.DISABLE_WALK_TO_WANTED_ITEM)
|
||||
behaviourConfigurationContext.addSensors(CobblemonSensors.POKEMON_NEARBY_WANTED_ITEM)
|
||||
|
||||
|
||||
return WrapperLivingEntityTask(
|
||||
MoveToItemTask.create(
|
||||
condition = condition.asExpression(),
|
||||
speedMultiplier = speedMultiplier.asExpression(),
|
||||
maxDistance = maxDistance.asExpression()
|
||||
),
|
||||
PokemonEntity::class.java
|
||||
)
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -27,7 +27,7 @@ class MoveToOwnerTaskConfig : SingleTaskConfig {
|
||||
var teleportDistance: ExpressionOrEntityVariable = Either.left("24.0".asExpression())
|
||||
var maxDistance: ExpressionOrEntityVariable = Either.left("14.0".asExpression())
|
||||
|
||||
override fun getVariables(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext) = listOf(
|
||||
override fun getVariables(entity: LivingEntity) = listOf(
|
||||
condition,
|
||||
completionRange,
|
||||
speedMultiplier,
|
||||
|
||||
-36
@@ -1,36 +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.ai.config.task
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonMemories
|
||||
import com.cobblemon.mod.common.CobblemonSensors
|
||||
import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
|
||||
import com.cobblemon.mod.common.api.npc.configuration.MoLangConfigVariable
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.entity.pokemon.ai.tasks.MoveToSweetBerryBushTask
|
||||
import net.minecraft.util.valueproviders.UniformInt
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
|
||||
class MoveToSweetBerryBushTaskConfig : SingleTaskConfig {
|
||||
override fun getVariables(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext) = emptyList<MoLangConfigVariable>()
|
||||
override fun createTask(
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
if (entity !is PokemonEntity) {
|
||||
return null
|
||||
}
|
||||
behaviourConfigurationContext.addMemories(CobblemonMemories.NEARBY_SWEET_BERRY_BUSH, CobblemonMemories.DISABLE_WALK_TO_BERRY_BUSH,
|
||||
CobblemonMemories.TIME_TRYING_TO_REACH_BERRY_BUSH, MemoryModuleType.WALK_TARGET, MemoryModuleType.LOOK_TARGET)
|
||||
behaviourConfigurationContext.addSensors(CobblemonSensors.NEARBY_SWEET_BERRY_BUSH)
|
||||
return MoveToSweetBerryBushTask.create(UniformInt.of(0, 10), 0.6f)
|
||||
}
|
||||
}
|
||||
-87
@@ -1,87 +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.ai.config.task
|
||||
|
||||
import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
|
||||
import com.cobblemon.mod.common.api.ai.ExpressionOrEntityVariable
|
||||
import com.cobblemon.mod.common.api.ai.asVariables
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMostSpecificMoLangValue
|
||||
import com.cobblemon.mod.common.entity.EntityCallbacks
|
||||
import com.cobblemon.mod.common.entity.MoLangScriptingEntity
|
||||
import com.cobblemon.mod.common.util.asExpression
|
||||
import com.mojang.datafixers.util.Either
|
||||
import net.minecraft.server.level.ServerLevel
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.Behavior
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
import net.minecraft.world.entity.ai.memory.MemoryStatus
|
||||
import net.minecraft.world.entity.ai.sensing.SensorType
|
||||
|
||||
/**
|
||||
* Frequently checks a diff on the visibility of entities around the given entity so EntityCallbacks can be triggered.
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since August 7th, 2025
|
||||
*/
|
||||
class NotifyAboutEntityVisibilityTaskConfig : SingleTaskConfig {
|
||||
val ticksBetweenChecks: ExpressionOrEntityVariable = Either.left("20".asExpression())
|
||||
|
||||
override fun getVariables(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext) = listOf(ticksBetweenChecks).asVariables()
|
||||
override fun createTask(
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
if (entity !is MoLangScriptingEntity) {
|
||||
return null
|
||||
}
|
||||
|
||||
val ticksBetweenChecks = ticksBetweenChecks.resolveInt(behaviourConfigurationContext.runtime)
|
||||
|
||||
behaviourConfigurationContext.addMemories(MemoryModuleType.NEAREST_LIVING_ENTITIES)
|
||||
behaviourConfigurationContext.addSensors(SensorType.NEAREST_LIVING_ENTITIES)
|
||||
|
||||
return object : Behavior<LivingEntity>(mapOf(MemoryModuleType.NEAREST_LIVING_ENTITIES to MemoryStatus.VALUE_PRESENT), Int.MAX_VALUE) {
|
||||
override fun canStillUse(level: ServerLevel, entity: LivingEntity, gameTime: Long) = true
|
||||
override fun checkExtraStartConditions(level: ServerLevel, owner: LivingEntity) = true
|
||||
|
||||
// Buffer of known entities
|
||||
val knownEntities = mutableListOf<LivingEntity>()
|
||||
override fun tick(level: ServerLevel, owner: LivingEntity, gameTime: Long) {
|
||||
if (gameTime % ticksBetweenChecks != 0L) {
|
||||
return
|
||||
}
|
||||
|
||||
val visibleEntities = owner.getBrain().getMemory(MemoryModuleType.NEAREST_LIVING_ENTITIES)
|
||||
.orElse(emptyList<LivingEntity>())
|
||||
.filter { it.isAlive }
|
||||
|
||||
val newEntities = visibleEntities.filterNot { it in knownEntities }
|
||||
val removedEntities = knownEntities.filterNot { it in visibleEntities }
|
||||
|
||||
newEntities.forEach {
|
||||
entity.callbacks.process(
|
||||
type = EntityCallbacks.SAW_ENTITY,
|
||||
functions = mapOf("other_entity" to { _ -> it.asMostSpecificMoLangValue() })
|
||||
)
|
||||
}
|
||||
|
||||
removedEntities.forEach {
|
||||
entity.callbacks.process(
|
||||
type = EntityCallbacks.LOST_ENTITY,
|
||||
functions = mapOf("other_entity" to { _ -> it.asMostSpecificMoLangValue() })
|
||||
)
|
||||
}
|
||||
|
||||
knownEntities.clear()
|
||||
knownEntities.addAll(visibleEntities)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+3
-2
@@ -38,10 +38,11 @@ class OneOfTaskConfig : SingleTaskConfig {
|
||||
val condition: ExpressionOrEntityVariable = Either.left("true".asExpression())
|
||||
val options = mutableListOf<OneOfTaskOption>()
|
||||
|
||||
override fun getVariables(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext) = options.flatMap { it.task.getVariables(entity, behaviourConfigurationContext) }
|
||||
override fun getVariables(entity: LivingEntity) = options.flatMap { it.task.getVariables(entity) }
|
||||
|
||||
override fun createTask(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext): BehaviorControl<in LivingEntity>? {
|
||||
if (!condition.resolveBoolean(behaviourConfigurationContext.runtime)) return null
|
||||
runtime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
if (!condition.resolveBoolean()) return null
|
||||
return RunOne(options.map { it.task.createTasks(entity, behaviourConfigurationContext).first() toDF it.weight })
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -22,7 +22,7 @@ class PathToBeeHiveTaskConfig : SingleTaskConfig {
|
||||
|
||||
val condition = booleanVariable(HONEY, "can_add_honey", true).asExpressible()
|
||||
|
||||
override fun getVariables(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext) = listOf(
|
||||
override fun getVariables(entity: LivingEntity) = listOf(
|
||||
condition,
|
||||
).asVariables()
|
||||
|
||||
@@ -33,7 +33,7 @@ class PathToBeeHiveTaskConfig : SingleTaskConfig {
|
||||
if (entity !is PokemonEntity) {
|
||||
return null
|
||||
}
|
||||
if (!checkCondition(behaviourConfigurationContext.runtime, condition)) {
|
||||
if (!checkCondition(entity, condition)) {
|
||||
return null
|
||||
}
|
||||
return PathToBeeHiveTask.create()
|
||||
|
||||
+2
-3
@@ -8,7 +8,6 @@
|
||||
|
||||
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.CobblemonSensors
|
||||
import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
|
||||
@@ -25,7 +24,7 @@ class PathToFlowerTaskConfig : SingleTaskConfig {
|
||||
|
||||
val condition = booleanVariable(POLLINATE, "can_pollinate", true).asExpressible()
|
||||
|
||||
override fun getVariables(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext) = listOf(
|
||||
override fun getVariables(entity: LivingEntity) = listOf(
|
||||
condition
|
||||
).asVariables()
|
||||
|
||||
@@ -37,7 +36,7 @@ class PathToFlowerTaskConfig : SingleTaskConfig {
|
||||
return null
|
||||
}
|
||||
|
||||
if (!checkCondition(behaviourConfigurationContext.runtime, condition)) {
|
||||
if (!checkCondition(entity, condition)) {
|
||||
return null
|
||||
}
|
||||
behaviourConfigurationContext.addMemories(
|
||||
|
||||
-49
@@ -1,49 +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.ai.config.task
|
||||
|
||||
import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
|
||||
import com.cobblemon.mod.common.api.ai.ExpressionOrEntityVariable
|
||||
import com.cobblemon.mod.common.api.ai.WrapperLivingEntityTask
|
||||
import com.cobblemon.mod.common.api.ai.asVariables
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.entity.pokemon.ai.tasks.PickUpItemTask
|
||||
import com.cobblemon.mod.common.util.asExpression
|
||||
import com.mojang.datafixers.util.Either
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
|
||||
class PickUpItemTaskConfig : SingleTaskConfig {
|
||||
val condition: ExpressionOrEntityVariable = Either.left("true".asExpression())
|
||||
var maxReach: ExpressionOrEntityVariable = Either.left("1.0".asExpression())
|
||||
|
||||
override fun getVariables(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext) = listOf(
|
||||
condition,
|
||||
maxReach
|
||||
).asVariables()
|
||||
|
||||
override fun createTask(
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
behaviourConfigurationContext.addMemories(
|
||||
MemoryModuleType.WALK_TARGET,
|
||||
MemoryModuleType.LOOK_TARGET,
|
||||
MemoryModuleType.NEAREST_VISIBLE_WANTED_ITEM
|
||||
)
|
||||
return WrapperLivingEntityTask(
|
||||
PickUpItemTask.create(
|
||||
condition = condition.asExpression(),
|
||||
maxReach = maxReach.asExpression()
|
||||
),
|
||||
PokemonEntity::class.java
|
||||
)
|
||||
}
|
||||
}
|
||||
+2
-3
@@ -8,7 +8,6 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.ai.config.task
|
||||
|
||||
import com.bedrockk.molang.runtime.MoLangRuntime
|
||||
import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
|
||||
import com.cobblemon.mod.common.api.ai.asVariables
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
@@ -23,7 +22,7 @@ class PlaceHoneyInHiveTaskConfig : SingleTaskConfig {
|
||||
|
||||
val condition = booleanVariable(HONEY, "can_add_honey", true).asExpressible()
|
||||
|
||||
override fun getVariables(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext) = listOf(
|
||||
override fun getVariables(entity: LivingEntity) = listOf(
|
||||
condition
|
||||
).asVariables()
|
||||
|
||||
@@ -34,7 +33,7 @@ class PlaceHoneyInHiveTaskConfig : SingleTaskConfig {
|
||||
if (entity !is PokemonEntity) {
|
||||
return null
|
||||
}
|
||||
if (!checkCondition(behaviourConfigurationContext.runtime, condition)) {
|
||||
if (!checkCondition(entity, condition)) {
|
||||
return null
|
||||
}
|
||||
return PlaceHoneyInHiveTask.create()
|
||||
|
||||
+1
-1
@@ -20,7 +20,7 @@ import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
import net.minecraft.world.phys.Vec3
|
||||
|
||||
class PointToSpawnTaskConfig : SingleTaskConfig {
|
||||
override fun getVariables(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext) = emptyList<MoLangConfigVariable>()
|
||||
override fun getVariables(entity: LivingEntity) = emptyList<MoLangConfigVariable>()
|
||||
override fun createTask(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext): BehaviorControl<in LivingEntity>? {
|
||||
behaviourConfigurationContext.addMemories(MemoryModuleType.LOOK_TARGET, MemoryModuleType.WALK_TARGET)
|
||||
return BehaviorBuilder.create {
|
||||
|
||||
+2
-2
@@ -34,7 +34,7 @@ class PollinateFlowerTaskConfig : SingleTaskConfig {
|
||||
val condition = booleanVariable(POLLINATE, "can_pollinate", true).asExpressible()
|
||||
val durationTicks: ExpressionOrEntityVariable = Either.left("30".asExpression())
|
||||
|
||||
override fun getVariables(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext) = listOf(
|
||||
override fun getVariables(entity: LivingEntity) = listOf(
|
||||
condition
|
||||
).asVariables()
|
||||
|
||||
@@ -45,7 +45,7 @@ class PollinateFlowerTaskConfig : SingleTaskConfig {
|
||||
if (entity !is PokemonEntity) {
|
||||
return null
|
||||
}
|
||||
if (!checkCondition(behaviourConfigurationContext.runtime, condition)) {
|
||||
if (!checkCondition(entity, condition)) {
|
||||
return null
|
||||
}
|
||||
|
||||
|
||||
@@ -162,11 +162,11 @@ on the entity type and this piggy-backs off the Minecraft list of aggressive mob
|
||||
The 'calm_down' type creates a task that will make the entity calm down when it is no longer being hurt and is far from hostiles and its attacker.
|
||||
- `condition`: A MoLang expression (with `q.entity` as the entity) that determines if this entire task should exist on the entity or not. This runs at the time of entity creation, not on tick.
|
||||
|
||||
### walk_away_from_avoid_target
|
||||
The 'flee_attacker' type creates a task that will make the entity flee from its avoid target.
|
||||
### flee_attacker
|
||||
The 'flee_attacker' type creates a task that will make the entity flee from its attacker when it is hurt.
|
||||
- `condition`: A MoLang expression (with `q.entity` as the entity) that determines if this entire task should exist on the entity or not. This runs at the time of entity creation, not on tick.
|
||||
- `speedMultiplier`: A MoLang expression that determines the speed multiplier for fleeing from the avoid target. Defaults to 0.5 which is an elevated speed to usual.
|
||||
- `desiredDistance`: A MoLang expression that determines the distance from the target that the entity should try to maintain. Defaults to 9.
|
||||
- `speedMultiplier`: A MoLang expression that determines the speed multiplier for fleeing from the attacker. Defaults to 0.5 which is an elevated speed to usual.
|
||||
- `desiredDistance`: A MoLang expression that determines the distance from the attacker that the entity should try to maintain. Defaults to 9.
|
||||
|
||||
### flee_nearest_hostile
|
||||
The 'flee_nearest_hostile' type creates a task that will make the entity flee from the nearest hostile entity when it is hurt.
|
||||
|
||||
+3
-2
@@ -42,12 +42,13 @@ class RandomTaskConfig : TaskConfig {
|
||||
val condition: ExpressionOrEntityVariable = Either.left("true".asExpression())
|
||||
val choices = mutableListOf<RandomTaskChoice>()
|
||||
|
||||
override fun getVariables(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext) = choices.flatMap { it.task.getVariables(entity, behaviourConfigurationContext) } + listOf(condition).asVariables()
|
||||
override fun getVariables(entity: LivingEntity) = choices.flatMap { it.task.getVariables(entity) } + listOf(condition).asVariables()
|
||||
override fun createTasks(
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
): List<BehaviorControl<in LivingEntity>> {
|
||||
if (!condition.resolveBoolean(behaviourConfigurationContext.runtime)) return emptyList()
|
||||
runtime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
if (!condition.resolveBoolean()) return emptyList()
|
||||
val task = choices.weightedSelection { it.weight }?.task ?: throw IllegalStateException("No tasks to choose from in random_task config")
|
||||
return task.createTasks(entity, behaviourConfigurationContext)
|
||||
}
|
||||
|
||||
@@ -15,7 +15,6 @@ import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMostSpecificMoLangV
|
||||
import com.cobblemon.mod.common.api.npc.configuration.MoLangConfigVariable
|
||||
import com.cobblemon.mod.common.api.scripting.CobblemonScripts
|
||||
import com.cobblemon.mod.common.util.asIdentifierDefaultingNamespace
|
||||
import com.cobblemon.mod.common.util.mainThreadRuntime
|
||||
import com.cobblemon.mod.common.util.withQueryValue
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
@@ -43,7 +42,7 @@ class RunScript : SingleTaskConfig {
|
||||
val memories = emptySet<MemoryModuleType<*>>()
|
||||
val sensors = emptySet<SensorType<*>>()
|
||||
|
||||
override fun getVariables(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext) = listOf(script).asVariables() + variables
|
||||
override fun getVariables(entity: LivingEntity) = listOf(script).asVariables() + variables
|
||||
|
||||
override fun createTask(
|
||||
entity: LivingEntity,
|
||||
@@ -55,10 +54,10 @@ class RunScript : SingleTaskConfig {
|
||||
it.registered(MemoryModuleType.LOOK_TARGET) // I think I need to have at least something here?
|
||||
).apply(it) { _ ->
|
||||
Trigger { world, entity, _ ->
|
||||
mainThreadRuntime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
runtime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
return@Trigger CobblemonScripts.run(
|
||||
identifier = script.resolveString(mainThreadRuntime).asIdentifierDefaultingNamespace(),
|
||||
runtime = mainThreadRuntime
|
||||
identifier = script.resolveString().asIdentifierDefaultingNamespace(),
|
||||
runtime = runtime
|
||||
) == DoubleValue.ONE
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -17,7 +17,7 @@ import net.minecraft.world.entity.ai.behavior.DoNothing
|
||||
interface SingleTaskConfig : TaskConfig {
|
||||
companion object {
|
||||
fun nothing() = object : SingleTaskConfig {
|
||||
override fun getVariables(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext) = emptyList<MoLangConfigVariable>()
|
||||
override fun getVariables(entity: LivingEntity) = emptyList<MoLangConfigVariable>()
|
||||
override fun createTask(
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
|
||||
+1
-1
@@ -20,7 +20,7 @@ import net.minecraft.world.entity.ai.behavior.declarative.Trigger
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
|
||||
class SleepIfOnTrainerBedTaskConfig : SingleTaskConfig {
|
||||
override fun getVariables(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext): List<MoLangConfigVariable> = emptyList()
|
||||
override fun getVariables(entity: LivingEntity): List<MoLangConfigVariable> = emptyList()
|
||||
override fun createTask(
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
|
||||
+6
-3
@@ -12,7 +12,9 @@ import com.cobblemon.mod.common.CobblemonMemories
|
||||
import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
|
||||
import com.cobblemon.mod.common.api.ai.WrapperLivingEntityTask
|
||||
import com.cobblemon.mod.common.api.ai.asVariables
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMostSpecificMoLangValue
|
||||
import com.cobblemon.mod.common.entity.ai.StayAfloatTask
|
||||
import com.cobblemon.mod.common.util.withQueryValue
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.PathfinderMob
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
@@ -21,12 +23,13 @@ class StayAfloatTaskConfig : SingleTaskConfig {
|
||||
val condition = booleanVariable(SharedEntityVariables.MOVEMENT_CATEGORY, "can_float", true).asExpressible()
|
||||
val chance = numberVariable(SharedEntityVariables.MOVEMENT_CATEGORY, "float_chance", 0.8F).asExpressible()
|
||||
|
||||
override fun getVariables(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext) = listOf(condition, chance).asVariables()
|
||||
override fun getVariables(entity: LivingEntity) = listOf(condition, chance).asVariables()
|
||||
override fun createTask(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext): BehaviorControl<LivingEntity>? {
|
||||
if (!condition.resolveBoolean(behaviourConfigurationContext.runtime)) return null
|
||||
runtime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
if (!condition.resolveBoolean()) return null
|
||||
behaviourConfigurationContext.addMemories(CobblemonMemories.POKEMON_BATTLE)
|
||||
return WrapperLivingEntityTask(
|
||||
StayAfloatTask(chance.resolveFloat(behaviourConfigurationContext.runtime)),
|
||||
StayAfloatTask(chance.resolveFloat()),
|
||||
PathfinderMob::class.java
|
||||
)
|
||||
}
|
||||
|
||||
+5
-5
@@ -15,7 +15,6 @@ 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.setup
|
||||
import com.cobblemon.mod.common.api.npc.configuration.MoLangConfigVariable
|
||||
import com.cobblemon.mod.common.util.mainThreadRuntime
|
||||
import com.cobblemon.mod.common.util.resolveBoolean
|
||||
import com.cobblemon.mod.common.util.withQueryValue
|
||||
import java.util.function.Predicate
|
||||
@@ -33,17 +32,18 @@ import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
* @since June 23rd, 2025
|
||||
*/
|
||||
class StopAttackingIfTargetInvalidTaskConfig : SingleTaskConfig {
|
||||
override fun getVariables(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext) = emptyList<MoLangConfigVariable>()
|
||||
override fun getVariables(entity: LivingEntity) = emptyList<MoLangConfigVariable>()
|
||||
override fun createTask(
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
): BehaviorControl<in LivingEntity> {
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
val runtime = MoLangRuntime().setup()
|
||||
behaviourConfigurationContext.addMemories(CobblemonMemories.ATTACK_TARGET_DATA, MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE)
|
||||
return StopAttackingIfTargetInvalid.create<Mob>(
|
||||
Predicate { target ->
|
||||
val targetData = entity.brain.getMemory(CobblemonMemories.ATTACK_TARGET_DATA).orElse(null) ?: return@Predicate false
|
||||
mainThreadRuntime.withQueryValue("entity", target.asMostSpecificMoLangValue())
|
||||
return@Predicate !mainThreadRuntime.resolveBoolean(targetData.shouldContinue)
|
||||
runtime.withQueryValue("entity", target.asMostSpecificMoLangValue())
|
||||
return@Predicate !runtime.resolveBoolean(targetData.shouldContinue)
|
||||
}
|
||||
).wrapped()
|
||||
}
|
||||
|
||||
+3
-2
@@ -20,12 +20,13 @@ import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
class StopBeingAngryIfAttackerDeadTaskConfig : SingleTaskConfig {
|
||||
val condition = booleanVariable(SharedEntityVariables.ATTACKING_CATEGORY, "stop_being_angry_if_attacker_dead", true).asExpressible()
|
||||
|
||||
override fun getVariables(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext) = listOf(condition).asVariables()
|
||||
override fun getVariables(entity: LivingEntity) = listOf(condition).asVariables()
|
||||
override fun createTask(
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
if (!condition.resolveBoolean(behaviourConfigurationContext.runtime)) return null
|
||||
runtime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
if (!condition.resolveBoolean()) return null
|
||||
behaviourConfigurationContext.addMemories(MemoryModuleType.ANGRY_AT)
|
||||
return StopBeingAngryIfTargetDead.create()
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user