mirror of
https://gitlab.com/cable-mc/cobblemon.git
synced 2026-10-21 06:36:25 -04:00
Compare commits
374
Commits
1.7.1
...
pokemodel_items
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
925f4ebed5 | ||
|
|
8b79963129 | ||
|
|
3a533a6d9c | ||
|
|
0dbcf2539b | ||
|
|
6d9f865099 | ||
|
|
5d2fa8427a | ||
|
|
8f8b2627f7 | ||
|
|
4ad0686b03 | ||
|
|
a56ffe1742 | ||
|
|
6d1570302d | ||
|
|
811e9d3352 | ||
|
|
e610aa18d7 | ||
|
|
42ecd3e813 | ||
|
|
1299b8fee8 | ||
|
|
a12cf17cfa | ||
|
|
74faca60f2 | ||
|
|
6420176787 | ||
|
|
6ee81fe2ab | ||
|
|
96f4f988f8 | ||
|
|
4ccfbbcb37 | ||
|
|
ed0aa83013 | ||
|
|
b94394f8d1 | ||
|
|
b16687c132 | ||
|
|
56767b3e31 | ||
|
|
67eb3e1046 | ||
|
|
952ea8d3b7 | ||
|
|
cc764ff9db | ||
|
|
2e1f8af700 | ||
|
|
6c6a8e4679 | ||
|
|
9e9a22eb14 | ||
|
|
32bfaf152d | ||
|
|
d1b947b264 | ||
|
|
6122fb6107 | ||
|
|
14c7ee3216 | ||
|
|
1a00ae7fb8 | ||
|
|
36b3cbe3b8 | ||
|
|
49686a1670 | ||
|
|
2354888a73 | ||
|
|
f64065d54f | ||
|
|
005ab0ca74 | ||
|
|
c13307e931 | ||
|
|
bd21a6e1ca | ||
|
|
94ea15b9c5 | ||
|
|
bc6c9def56 | ||
|
|
9ca6a2e461 | ||
|
|
f7560a12ad | ||
|
|
8bc1767917 | ||
|
|
8b29d3a533 | ||
|
|
de1248b97e | ||
|
|
a654225ed5 | ||
|
|
2d18113e27 | ||
|
|
cdadc6fa67 | ||
|
|
ff7ef1b67e | ||
|
|
d91c819700 | ||
|
|
259e1d05cb | ||
|
|
549b88a4c2 | ||
|
|
68b60e7d50 | ||
|
|
a7787707f2 | ||
|
|
539097e681 | ||
|
|
8b70a4124d | ||
|
|
7e8b000311 | ||
|
|
00c86b89cb | ||
|
|
b2c9d96829 | ||
|
|
8ea5ea6804 | ||
|
|
1305e8a11d | ||
|
|
909cd8a6eb | ||
|
|
d60abdc940 | ||
|
|
ec8e6f58c8 | ||
|
|
12967e4813 | ||
|
|
d754cc69fe | ||
|
|
a2b54643fe | ||
|
|
896c195dd9 | ||
|
|
206bfacba0 | ||
|
|
b6ffbd1ed8 | ||
|
|
829900fb58 | ||
|
|
be3066f7b2 | ||
|
|
fb56ab5865 | ||
|
|
a3f02a8a7c | ||
|
|
6c2757b94b | ||
|
|
139ef56fdf | ||
|
|
d3e473ff85 | ||
|
|
fdebc5987e | ||
|
|
caeeb756fe | ||
|
|
67b5e5c6a8 | ||
|
|
720eef5e75 | ||
|
|
ebc7f67655 | ||
|
|
3c508c5bd1 | ||
|
|
c7052d295c | ||
|
|
9193e9a372 | ||
|
|
f6244cbe12 | ||
|
|
5743a04db7 | ||
|
|
439a5077c2 | ||
|
|
a8a028bb7a | ||
|
|
984e10a780 | ||
|
|
ad0571a782 | ||
|
|
a18581ae1c | ||
|
|
177ad70172 | ||
|
|
98fb731270 | ||
|
|
a98dbcf267 | ||
|
|
62e9294c8a | ||
|
|
314bd19dc6 | ||
|
|
c0344f5604 | ||
|
|
2f8a9f207c | ||
|
|
8c1416514c | ||
|
|
575c33612d | ||
|
|
889d193ad1 | ||
|
|
57ef37099e | ||
|
|
d7d311764d | ||
|
|
d7fb65d23b | ||
|
|
3e4449aed1 | ||
|
|
55aa50654c | ||
|
|
489170cf00 | ||
|
|
930eb42e76 | ||
|
|
87d76e8788 | ||
|
|
6d8bf59eee | ||
|
|
a8f431868a | ||
|
|
0c6e355c6b | ||
|
|
a2f6ab0ea4 | ||
|
|
719a56e7c3 | ||
|
|
bd4397ec55 | ||
|
|
d5e3781fc5 | ||
|
|
776ab05ac1 | ||
|
|
0da5d27851 | ||
|
|
48b28bc509 | ||
|
|
5547326798 | ||
|
|
bcf730a07f | ||
|
|
8be1e78fee | ||
|
|
c463c99b0f | ||
|
|
255829a9f8 | ||
|
|
46758b7ab0 | ||
|
|
aebcf42df8 | ||
|
|
2268640dbc | ||
|
|
bf3739c598 | ||
|
|
9c4ae189a1 | ||
|
|
502a314a6c | ||
|
|
ca1ea6385d | ||
|
|
9749acbb0c | ||
|
|
81d4e4ded1 | ||
|
|
3e5ab4328b | ||
|
|
d1993574f6 | ||
|
|
2b531ec32f | ||
|
|
a9985bbea8 | ||
|
|
8d00da2c57 | ||
|
|
f4d866537a | ||
|
|
e9f942687f | ||
|
|
d67d73351d | ||
|
|
74d3ce793d | ||
|
|
3223c8dfeb | ||
|
|
a84a897e84 | ||
|
|
92bf3ba2a2 | ||
|
|
84f79c89c5 | ||
|
|
248967256b | ||
|
|
ea19721998 | ||
|
|
e9408db7a1 | ||
|
|
15ab84297d | ||
|
|
94cfb23e66 | ||
|
|
2fbffa5b66 | ||
|
|
108b769928 | ||
|
|
3db39547f0 | ||
|
|
c4688c5db9 | ||
|
|
b0385fc37f | ||
|
|
e491e7de81 | ||
|
|
f7974767d1 | ||
|
|
d41e89ddbd | ||
|
|
37293d396a | ||
|
|
d598335112 | ||
|
|
a30ca92f0a | ||
|
|
dd5ec25345 | ||
|
|
e3f3f4e1b7 | ||
|
|
004890d050 | ||
|
|
e690a0ed92 | ||
|
|
1e240d879f | ||
|
|
5f52625b05 | ||
|
|
10746bea10 | ||
|
|
af1f607994 | ||
|
|
db9cefc8ba | ||
|
|
c467f9cad2 | ||
|
|
5f7fa85b58 | ||
|
|
eb3ffdfbd4 | ||
|
|
c7e512bc32 | ||
|
|
6889cb7936 | ||
|
|
b4af502997 | ||
|
|
9bffdf8df4 | ||
|
|
8dbdd78c86 | ||
|
|
e6812891b5 | ||
|
|
6a3c98ed1c | ||
|
|
991ec7cc1a | ||
|
|
e59f4e7891 | ||
|
|
a481bde4f5 | ||
|
|
787faf38e7 | ||
|
|
9a42c82a37 | ||
|
|
654d0f8975 | ||
|
|
66b3c4a4c6 | ||
|
|
2fc2f24dee | ||
|
|
0988411e13 | ||
|
|
b39fadcde8 | ||
|
|
8221386767 | ||
|
|
311a3e1005 | ||
|
|
aeb6bddba6 | ||
|
|
e11d1cb77c | ||
|
|
774e62bb4b | ||
|
|
716ab4fb95 | ||
|
|
766625bf31 | ||
|
|
14cde609c6 | ||
|
|
da6ac4b8d6 | ||
|
|
43ef224444 | ||
|
|
d65d23ad02 | ||
|
|
e32b540deb | ||
|
|
f416567005 | ||
|
|
1daf931a49 | ||
|
|
6bcbc58b0a | ||
|
|
a1218f6c1e | ||
|
|
b1eb21150b | ||
|
|
56d4a18474 | ||
|
|
f13b6ddde7 | ||
|
|
c3d119c197 | ||
|
|
eb7527c26c | ||
|
|
b6bc03d2b7 | ||
|
|
029a338aaf | ||
|
|
b3f794ddaa | ||
|
|
1c95686bf9 | ||
|
|
55b1e7c672 | ||
|
|
e532fbf2ae | ||
|
|
c7348d3dba | ||
|
|
b978bbe60e | ||
|
|
31c492c032 | ||
|
|
85a2142319 | ||
|
|
83e3d65918 | ||
|
|
9b053bef90 | ||
|
|
76211e81ff | ||
|
|
2cace9d153 | ||
|
|
33ad8ca12b | ||
|
|
8cce2c59b9 | ||
|
|
bdcb8da6b7 | ||
|
|
d0cfae8713 | ||
|
|
693b53704d | ||
|
|
3c46e3b5b9 | ||
|
|
5dec5ed008 | ||
|
|
22a479633e | ||
|
|
1d93df56ae | ||
|
|
136d47bd2f | ||
|
|
8ded0af5e9 | ||
|
|
36462b0a85 | ||
|
|
8a447a2487 | ||
|
|
bdc2c4d9de | ||
|
|
8d9a7d67b5 | ||
|
|
e1d9b2780a | ||
|
|
fafee79da9 | ||
|
|
71c6c12656 | ||
|
|
4e07128c80 | ||
|
|
df8640ce48 | ||
|
|
59e0a6369d | ||
|
|
8913252b79 | ||
|
|
f7bedc9866 | ||
|
|
e47529c10a | ||
|
|
3e6c6c21a6 | ||
|
|
d4f13b9435 | ||
|
|
e7b60abe2d | ||
|
|
85da2bd0cc | ||
|
|
b7af57f6e1 | ||
|
|
ca5b7e1aec | ||
|
|
2ec81679e4 | ||
|
|
08c048f4ba | ||
|
|
6589279339 | ||
|
|
4465e47f2e | ||
|
|
570d42df7a | ||
|
|
044e83449d | ||
|
|
6617558e71 | ||
|
|
eff410b714 | ||
|
|
482a7d9493 | ||
|
|
430891971c | ||
|
|
d88f2d80a3 | ||
|
|
2a3d74bd85 | ||
|
|
de94986156 | ||
|
|
f8afcb6a8f | ||
|
|
3c0cf1dc5b | ||
|
|
8225898a66 | ||
|
|
49faf60ea1 | ||
|
|
71bd4fb610 | ||
|
|
509feae420 | ||
|
|
5045a95cd0 | ||
|
|
07dfc89f63 | ||
|
|
34b6a3cc47 | ||
|
|
98fd61ec29 | ||
|
|
e1e545dd05 | ||
|
|
c403103018 | ||
|
|
d6a1d3f2bd | ||
|
|
87edf2bfd6 | ||
|
|
7711535a26 | ||
|
|
f65f6fd2c9 | ||
|
|
a4e144854d | ||
|
|
d6f7cd4b83 | ||
|
|
36cf258410 | ||
|
|
89df2a01e2 | ||
|
|
0a930cb54f | ||
|
|
2448fec2c4 | ||
|
|
ea2071b644 | ||
|
|
bae0d77699 | ||
|
|
f5f5cb19bc | ||
|
|
9aa7c65279 | ||
|
|
8f4071e181 | ||
|
|
9c4470bc51 | ||
|
|
c785480c32 | ||
|
|
4a50700bb9 | ||
|
|
0ad2ff552b | ||
|
|
44c5d4ea2e | ||
|
|
46661908e0 | ||
|
|
01372f2850 | ||
|
|
204ce8f003 | ||
|
|
784ddcb19a | ||
|
|
11d7cbfa46 | ||
|
|
f3325caaea | ||
|
|
123c348f73 | ||
|
|
29aae87f01 | ||
|
|
9f6ad98acb | ||
|
|
cecd291566 | ||
|
|
2f9d6a9f83 | ||
|
|
1e9ccbddcb | ||
|
|
9b5a381436 | ||
|
|
ed5bd7e899 | ||
|
|
587a90bb70 | ||
|
|
f883578046 | ||
|
|
b5d348eba6 | ||
|
|
fce389edfd | ||
|
|
b6954b4e07 | ||
|
|
f28a16c7cc | ||
|
|
230071a773 | ||
|
|
63534a242c | ||
|
|
1afb574aec | ||
|
|
ac9adb03cd | ||
|
|
f3a22b19b3 | ||
|
|
572e77c4f5 | ||
|
|
889a012932 | ||
|
|
eca4c6cd4c | ||
|
|
b570a6ec8b | ||
|
|
1f1c302bc9 | ||
|
|
adc1fa0063 | ||
|
|
ddc3a781a0 | ||
|
|
9eb3281c6f | ||
|
|
0cd5804e67 | ||
|
|
7000d0d82a | ||
|
|
b7695e55ea | ||
|
|
bea3ebe62b | ||
|
|
73cf736077 | ||
|
|
d31f8f0eff | ||
|
|
88dca4d7b1 | ||
|
|
27db85ee32 | ||
|
|
5e3561eba5 | ||
|
|
9dfa8a323e | ||
|
|
15c0d86996 | ||
|
|
0fbb5e7d95 | ||
|
|
5e8d27779c | ||
|
|
a4fabcd45d | ||
|
|
5259b8c93d | ||
|
|
397c2decbf | ||
|
|
12b6e7e49c | ||
|
|
242c1b01af | ||
|
|
ee76e19b85 | ||
|
|
2aac6cc9e7 | ||
|
|
3faa305f09 | ||
|
|
d1bbf5f079 | ||
|
|
52fa646420 | ||
|
|
f7c47d46cf | ||
|
|
e82c361bcb | ||
|
|
fa6d8e0f08 | ||
|
|
7eea6c8b49 | ||
|
|
c537ca438b | ||
|
|
d5cea9b9ad | ||
|
|
6c2494b7ab | ||
|
|
a5ab523ac1 | ||
|
|
847ae12ad5 | ||
|
|
cece9e051b | ||
|
|
02141ccd3e | ||
|
|
1dc3acc47d |
+5
-1
@@ -5,12 +5,16 @@
|
||||
- Dog Pokémon (Growlithe, Arcanine, etc.) intimidate Skeletons.
|
||||
- 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.
|
||||
- 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.
|
||||
|
||||
### Developer
|
||||
- baseScale in NPCs has been removed from classes and presets, and in the entity it is replaced with hitboxScale and renderScale.
|
||||
|
||||
### MoLang & Datapacks
|
||||
- Added a `behaviours` datapack folder which motivates the Behaviour Editor screen on NPCs and Pokémon.
|
||||
- Added many default behaviours.
|
||||
- Added very many behaviours to choose from.
|
||||
- Removed many NPC presets that now exist as behaviours. This is a breaking change if you are using NPCs with these presets.
|
||||
- NPCs with these presets should be modified to instead list under `"behaviours"` all the equivalent behaviours.
|
||||
+7
-1
@@ -4,10 +4,16 @@
|
||||
- The button on the right allows for changing the box wallpaper.
|
||||
- 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.
|
||||
- improved filter by Name, now is available search by exact names or partial matches, for example "cha" will show Charmander, Charmeleon and Charizard among others that match.
|
||||
- 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.
|
||||
|
||||
### Developer
|
||||
- Added `RenamePCBoxEvent.Pre` and `RenamePCBoxEvent.Post` events to prevent players from renaming a box or changing their input.
|
||||
|
||||
+17
-7
@@ -20,9 +20,8 @@
|
||||
- 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.
|
||||
- Added lang keys for all moves and abilities up to Generation 9.
|
||||
- Fixed Moon Ball moon phase logic to actually work correctly
|
||||
- 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.
|
||||
- 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 modification to Minecraft Creative Inventory search to account for item names that contain `poké` when input contains `poke`.
|
||||
@@ -33,6 +32,7 @@
|
||||
- Added `/pctake <player> <box> <slot>` command that takes a specific Pokémon from a player's PC. Removes the pokemon if target is self or ran from the server.
|
||||
- Added Hyper Training items (IV Modification) as well as some additional candy items to do so (Health Candy, Sickly Candy)
|
||||
- Added Galarica Nut Bushes
|
||||
- Added functionality to Everstone when held by a Pokémon; suppresses evolution notification and hides evolve button in summary interface.
|
||||
|
||||
### Pokémon Added
|
||||
|
||||
@@ -226,6 +226,9 @@
|
||||
- Saccharine Leaves Age 1 or higher will now show Yellow particles when broken
|
||||
- Destroying a Saccharine Honey Log will now drop a Saccharine Log in stead of nothing
|
||||
- Reworked some compost chances
|
||||
- Updated interaction interface to include 4 more option spaces
|
||||
- Made lecterns that hold a Pokédex emit light.
|
||||
- Updated light levels for active PC, Pasture, Healing Machine, and Data Monitor.
|
||||
|
||||
### Fixes
|
||||
- Fixed game crashing when removing national pokedex using datapacks
|
||||
@@ -280,12 +283,17 @@
|
||||
- Fixed Cobblemon crashing if it tries to load a bedrock model not meant for cobblemon (example: Qlipoth Awakening)
|
||||
- Fixed Berries (and thus mulches) not being plantable on Farmers delight rich soil farmland
|
||||
- Fixed wild Pokémon vanishing when third party mods try to tame them the "vanilla" way
|
||||
- Fixed Pokemon not being able to path over skulk veins, pressure plates, fence gates, signs, lanterns, chains, and many other short blocks.
|
||||
- Fixed some cases in which Pokemon could not path over fence posts situations.
|
||||
- Fixed Pokémon not being able to path over skulk veins, pressure plates, fence gates, signs, lanterns, chains, and many other short blocks.
|
||||
- Fixed some cases in which Pokémon could not path over fence posts situations.
|
||||
- Fixed flyers not being able to do vertical takeoff if surrounded by blocks.
|
||||
- Fixed swimming Pokemon attempting to swim up through solid blocks.
|
||||
- Fixed Pokemon surface swimming diving downward a block for the duration of the swim.
|
||||
- Fixed swimming Pokémon attempting to swim up through solid blocks.
|
||||
- Fixed Pokémon surface swimming diving downward a block for the duration of the swim.
|
||||
- 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 a crash due to a ConcurrentModificationException that could occur during world generation.
|
||||
- Fixed Moon Ball moon phase logic to actually work correctly
|
||||
- Fixed recoil eyes on Shellder & Cloyster.
|
||||
- Fixed Shroomish spinning at lightning speed when fainting (no longer allowed to let it rip.)
|
||||
- Fixed Quaxly's animations showing hidden wing sets
|
||||
@@ -324,7 +332,9 @@
|
||||
- Added `Pokemon#hyperTrainIV()` and `IVs#setHyperTrainedIV(Stat, Int)`.
|
||||
- Added `HyperTrainedIvEvent.Pre` and `HyperTrainedIvEvent.Post`.
|
||||
- Added a `hoverText` option to PartySelectCallback, to display a tooltip on hovering over a Pokémon in the selection screen.
|
||||
|
||||
- `PokemonEntity` instances spawned into the world now appropriately finalize the spawn for mod compatibility.
|
||||
- Added PokedexManager.obtain as a replacement for .catch which is not a friendly function name in Java.
|
||||
|
||||
### 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
|
||||
|
||||
@@ -11,6 +11,7 @@ package com.cobblemon.mod.common.compat;
|
||||
import com.cobblemon.mod.common.CobblemonEntities;
|
||||
import com.cobblemon.mod.common.client.render.layer.PokemonOnShoulderRenderer;
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity;
|
||||
import com.cobblemon.mod.common.item.PokedexItem;
|
||||
import com.cobblemon.mod.common.pokemon.FormData;
|
||||
import com.cobblemon.mod.common.pokemon.lighthing.LightingData;
|
||||
import dev.lambdaurora.lambdynlights.LambDynLights;
|
||||
@@ -36,20 +37,20 @@ public class LambDynamicLightsCompat {
|
||||
public static void hookCompat() {
|
||||
// Pokémon entities
|
||||
DynamicLightHandlers.registerDynamicLightHandler(
|
||||
CobblemonEntities.POKEMON,
|
||||
DynamicLightHandler.makeHandler(
|
||||
LambDynamicLightsCompat::resolvedPokemonLightLevel,
|
||||
pokemon -> false
|
||||
)
|
||||
CobblemonEntities.POKEMON,
|
||||
DynamicLightHandler.makeHandler(
|
||||
LambDynamicLightsCompat::resolvedPokemonLightLevel,
|
||||
pokemon -> false
|
||||
)
|
||||
);
|
||||
|
||||
// Shouldered Pokémon
|
||||
DynamicLightHandlers.registerDynamicLightHandler(
|
||||
EntityType.PLAYER,
|
||||
DynamicLightHandler.makeHandler(
|
||||
LambDynamicLightsCompat::resolvedShoulderLightLevel,
|
||||
player -> false
|
||||
)
|
||||
EntityType.PLAYER,
|
||||
DynamicLightHandler.makeHandler(
|
||||
LambDynamicLightsCompat::resolvedPlayerLightLevel,
|
||||
player -> false
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -63,11 +64,13 @@ public class LambDynamicLightsCompat {
|
||||
return Math.max(itemLightLevel, formLightLevel);
|
||||
}
|
||||
|
||||
private static int resolvedShoulderLightLevel(Player player) {
|
||||
private static int resolvedPlayerLightLevel(Player player) {
|
||||
var underwater = !player.level().getFluidState(BlockPos.containing(player.getX(), player.getEyeY(), player.getZ())).isEmpty();
|
||||
final int leftLightLevel = extractShoulderLightLevel(PokemonOnShoulderRenderer.shoulderDataFrom(player.getShoulderEntityLeft()), underwater);
|
||||
final int rightLightLevel = extractShoulderLightLevel(PokemonOnShoulderRenderer.shoulderDataFrom(player.getShoulderEntityRight()), underwater);
|
||||
return Math.max(leftLightLevel, rightLightLevel);
|
||||
final int leftShoulderLightLevel = extractShoulderLightLevel(PokemonOnShoulderRenderer.shoulderDataFrom(player.getShoulderEntityLeft()), underwater);
|
||||
final int rightShoulderLightLevel = extractShoulderLightLevel(PokemonOnShoulderRenderer.shoulderDataFrom(player.getShoulderEntityRight()), underwater);
|
||||
final int itemLightLevel = customHeldItemLightLevel(player.getMainHandItem(), player.getOffhandItem());
|
||||
|
||||
return Math.max(itemLightLevel, Math.max(leftShoulderLightLevel, rightShoulderLightLevel));
|
||||
}
|
||||
|
||||
private static Optional<Integer> extractFormLightLevel(@NotNull FormData form, boolean underwater) {
|
||||
@@ -83,14 +86,17 @@ public class LambDynamicLightsCompat {
|
||||
}
|
||||
|
||||
ItemStack item = shoulderData.getShownItem();
|
||||
int itemLightLevel = item.isEmpty()?0:LambDynLights.getLuminanceFromItemStack(item, underwater);
|
||||
int itemLightLevel = item.isEmpty() ? 0 :LambDynLights.getLuminanceFromItemStack(item, underwater);
|
||||
int formLightLevel = extractFormLightLevel(shoulderData.getForm(), underwater).orElse(0);
|
||||
|
||||
return Math.max(itemLightLevel, formLightLevel);
|
||||
}
|
||||
|
||||
private static int customHeldItemLightLevel(ItemStack mainhand, ItemStack offhand) {
|
||||
return (mainhand.getItem() instanceof PokedexItem || offhand.getItem() instanceof PokedexItem) ? 13 : 0;
|
||||
}
|
||||
|
||||
private static boolean liquidGlowModeSupport(@NotNull LightingData.LiquidGlowMode liquidGlowMode, boolean underwater) {
|
||||
return underwater ? liquidGlowMode.getGlowsUnderwater() : liquidGlowMode.getGlowsInLand();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -12,14 +12,12 @@ import com.cobblemon.mod.common.block.SaccharineLeafBlock;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
|
||||
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.Desc;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.ModifyVariable;
|
||||
import org.spongepowered.asm.mixin.injection.Slice;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
|
||||
|
||||
@@ -42,8 +40,9 @@ public abstract class BeeEntityMixin {
|
||||
if (block instanceof SaccharineLeafBlock) {
|
||||
|
||||
int age = blockState.getValue(SaccharineLeafBlock.Companion.getAGE());
|
||||
boolean waterlogged = blockState.getValue(BlockStateProperties.WATERLOGGED);
|
||||
|
||||
if (age < 2) {
|
||||
if (age < 2 && !waterlogged) {
|
||||
this.cobblemon$result = blockState.setValue(SaccharineLeafBlock.Companion.getAGE(), age + 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* 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.client.multiplayer.ClientLevel;
|
||||
import net.minecraft.client.multiplayer.ClientPacketListener;
|
||||
import net.minecraft.network.protocol.game.ClientboundSetPassengersPacket;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
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.callback.CallbackInfo;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Objects;
|
||||
|
||||
@Mixin(ClientPacketListener.class)
|
||||
public class ClientPacketListenerMixin {
|
||||
|
||||
@Shadow private ClientLevel level;
|
||||
|
||||
@Inject(method = "handleSetEntityPassengersPacket", at = @At(value = "INVOKE_ASSIGN", target = "Lnet/minecraft/world/entity/Entity;hasIndirectPassenger(Lnet/minecraft/world/entity/Entity;)Z", shift = At.Shift.BEFORE), cancellable = true)
|
||||
private void cobblemon$handlePokemonPassengers(ClientboundSetPassengersPacket packet, CallbackInfo ci) {
|
||||
Entity entity = this.level.getEntity(packet.getVehicle());
|
||||
if (entity instanceof PokemonEntity pokemon) {
|
||||
var passengers = new ArrayList<Entity>();
|
||||
for (int passenger : packet.getPassengers()) {
|
||||
passengers.add(this.level.getEntity(passenger));
|
||||
}
|
||||
Arrays
|
||||
.stream(pokemon.getOccupiedSeats())
|
||||
.filter(x -> !passengers.contains(x))
|
||||
.filter(Objects::nonNull)
|
||||
.forEach(Entity::stopRiding);
|
||||
|
||||
var occupiedSeats = Arrays.asList(pokemon.getOccupiedSeats());
|
||||
passengers.stream()
|
||||
.filter(x -> !occupiedSeats.contains(x))
|
||||
.filter(Objects::nonNull)
|
||||
.forEach(x -> x.startRiding(pokemon, true));
|
||||
ci.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+22
-11
@@ -9,20 +9,19 @@
|
||||
package com.cobblemon.mod.common.mixin;
|
||||
|
||||
import com.cobblemon.mod.common.client.CobblemonClient;
|
||||
import com.cobblemon.mod.common.client.render.MatrixWrapper;
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.PosableModel;
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.PosableState;
|
||||
import com.cobblemon.mod.common.entity.PosableEntity;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.mojang.blaze3d.vertex.VertexConsumer;
|
||||
import net.minecraft.client.renderer.LevelRenderer;
|
||||
import net.minecraft.client.renderer.MultiBufferSource;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.client.renderer.entity.EntityRenderDispatcher;
|
||||
import net.minecraft.client.renderer.entity.EntityRenderer;
|
||||
import net.minecraft.client.resources.PlayerSkin;
|
||||
import net.minecraft.server.packs.resources.ResourceManager;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.phys.AABB;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import org.joml.Vector3f;
|
||||
import org.spongepowered.asm.mixin.Debug;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
@@ -30,11 +29,6 @@ import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
import java.util.Map;
|
||||
import net.minecraft.client.renderer.entity.EntityRenderDispatcher;
|
||||
import net.minecraft.client.renderer.entity.EntityRenderer;
|
||||
import net.minecraft.client.resources.PlayerSkin;
|
||||
import net.minecraft.server.packs.resources.ResourceManager;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
|
||||
@Mixin(EntityRenderDispatcher.class)
|
||||
public class EntityRenderDispatcherMixin {
|
||||
@@ -77,6 +71,23 @@ public class EntityRenderDispatcherMixin {
|
||||
0F,
|
||||
1F
|
||||
);
|
||||
|
||||
/*if (locator.contains("middle")){
|
||||
PoseStack.Pose pose = poseStack.last();
|
||||
Vector3f vec = matrix.getMatrix().getRotation(new AxisAngle4f()).transform(new Vector3f(0, 0, -1));
|
||||
buffer.addVertex(pose, pos.toVector3f()).setColor(0xffff00ff).setNormal(pose, vec.x, vec.y, vec.z); //Forward, pink
|
||||
buffer.addVertex(pose, (float)(pos.x() + vec.x), (float)(pos.y() + vec.y), (float)(pos.z() + vec.z)).setColor(0xffff00ff).setNormal(pose, vec.x, vec.y, vec.z);
|
||||
|
||||
vec = matrix.getMatrix().getRotation(new AxisAngle4f()).transform(new Vector3f(0, 1, 0));
|
||||
buffer.addVertex(pose, pos.toVector3f()).setColor(0xffffff00).setNormal(pose, vec.x, vec.y, vec.z); //Up, yellow
|
||||
buffer.addVertex(pose, (float)(pos.x() + vec.x), (float)(pos.y() + vec.y), (float)(pos.z() + vec.z)).setColor(0xffffff00).setNormal(pose, vec.x, vec.y, vec.z);
|
||||
|
||||
vec = matrix.getMatrix().getRotation(new AxisAngle4f()).transform(new Vector3f(-1, 0, 0));
|
||||
buffer.addVertex(pose, pos.toVector3f()).setColor(0xff00ffff).setNormal(pose, vec.x, vec.y, vec.z); //Left, cyan
|
||||
buffer.addVertex(pose, (float)(pos.x() + vec.x), (float)(pos.y() + vec.y), (float)(pos.z() + vec.z)).setColor(0xff00ffff).setNormal(pose, vec.x, vec.y, vec.z);
|
||||
}*/
|
||||
|
||||
|
||||
poseStack.popPose();
|
||||
});
|
||||
|
||||
|
||||
@@ -119,14 +119,12 @@ public abstract class LocalPlayerMixin extends AbstractClientPlayer implements O
|
||||
public HitResult pick(double hitDistance, float partialTicks, boolean hitFluids) {
|
||||
Entity vehicle = this.getVehicle();
|
||||
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());
|
||||
String locatorName = delegate.getSeatLocator(this);
|
||||
MatrixWrapper locator = delegate.getLocatorStates().get(locatorName);
|
||||
|
||||
if (locator == null) {
|
||||
super.pick(hitDistance, partialTicks, hitFluids);
|
||||
return super.pick(hitDistance, partialTicks, hitFluids);
|
||||
}
|
||||
|
||||
Vec3 locatorOffset = new Vec3(locator.getMatrix().getTranslation(new Vector3f()));
|
||||
@@ -138,7 +136,7 @@ public abstract class LocalPlayerMixin extends AbstractClientPlayer implements O
|
||||
|
||||
if (Minecraft.getInstance().options.getCameraType() == CameraType.FIRST_PERSON) {
|
||||
PosableModel model = VaryingModelRepository.INSTANCE.getPoser(pokemonEntity.getPokemon().getSpecies().getResourceIdentifier(), new FloatingState());
|
||||
offset.add(cobblemon$getFirstPersonOffset(model, seat));
|
||||
offset.add(cobblemon$getFirstPersonOffset(model, locatorName));
|
||||
}
|
||||
|
||||
Matrix3f orientation = controller.isActive() && controller.getOrientation() != null ? controller.getOrientation() : new Matrix3f();
|
||||
@@ -160,11 +158,11 @@ public abstract class LocalPlayerMixin extends AbstractClientPlayer implements O
|
||||
}
|
||||
|
||||
@Unique
|
||||
private static @NotNull Vector3f cobblemon$getFirstPersonOffset(PosableModel model, Seat seat) {
|
||||
private static @NotNull Vector3f cobblemon$getFirstPersonOffset(PosableModel model, String locatorName) {
|
||||
Map<String, Vec3> cameraOffsets = model.getFirstPersonCameraOffset();
|
||||
|
||||
if (cameraOffsets.containsKey(seat.getLocator())) {
|
||||
return cameraOffsets.get(seat.getLocator()).toVector3f();
|
||||
if (cameraOffsets.containsKey(locatorName)) {
|
||||
return cameraOffsets.get(locatorName).toVector3f();
|
||||
} else {
|
||||
return new Vector3f(0f, 0f, 0f);
|
||||
}
|
||||
|
||||
@@ -30,7 +30,6 @@ 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.CallbackInfo;
|
||||
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
|
||||
|
||||
@Mixin(MouseHandler.class)
|
||||
public abstract class MouseHandlerMixin {
|
||||
@@ -121,11 +120,12 @@ public abstract class MouseHandlerMixin {
|
||||
if (usageContext.getScanningGuiOpen()) {
|
||||
this.smoothTurnY.reset();
|
||||
this.smoothTurnX.reset();
|
||||
var defaultSensitivity = this.minecraft.options.sensitivity().get() * 0.6000000238418579 + 0.20000000298023224;
|
||||
var defaultSensitivity = this.minecraft.options.sensitivity().get() * 0.6 + 0.2;
|
||||
var spyglassSensitivity = Math.pow(defaultSensitivity, 3);
|
||||
var lookSensitivity = spyglassSensitivity * 8.0;
|
||||
var sensitivity = Mth.lerp(usageContext.getFovMultiplier(), spyglassSensitivity, lookSensitivity);
|
||||
player.turn(this.accumulatedDX * sensitivity, (this.accumulatedDY * sensitivity));
|
||||
var yRotationFlip = this.minecraft.options.invertYMouse().get() ? -1 : 1;
|
||||
player.turn(this.accumulatedDX * sensitivity, (this.accumulatedDY * sensitivity * yRotationFlip));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
+72
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* 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.client.snapshots;
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonBuildDetails;
|
||||
import com.cobblemon.mod.common.client.gui.snapshots.SnapshotWarningScreen;
|
||||
import com.cobblemon.mod.common.client.snapshots.SnapshotAcknowledgementData;
|
||||
import com.cobblemon.mod.common.client.snapshots.SnapshotAcknowledgementReader;
|
||||
import kotlin.Unit;
|
||||
import net.minecraft.SharedConstants;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.screens.Screen;
|
||||
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.CallbackInfo;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
@Mixin(Minecraft.class)
|
||||
public final class SnapshotWarningMixin {
|
||||
|
||||
@Unique
|
||||
private final Pattern VERSION = Pattern.compile("^(?<major>\\d+)\\.(?<minor>\\d+)\\.(?<patch>\\d+)$");
|
||||
|
||||
@Inject(method = "addInitialScreens", at = @At("TAIL"))
|
||||
public void cobblemon$addSnapshotWarningScreen(List<Function<Runnable, Screen>> output, CallbackInfo callback) {
|
||||
if (CobblemonBuildDetails.SNAPSHOT && !this.cobblemon$isAcknowledged() && !SharedConstants.IS_RUNNING_IN_IDE) {
|
||||
output.add((runnable) -> new SnapshotWarningScreen((acknowledgement, dsa) -> {
|
||||
if (acknowledgement == SnapshotWarningScreen.Acknowledgement.NO) {
|
||||
Minecraft.getInstance().stop();
|
||||
return Unit.INSTANCE;
|
||||
}
|
||||
|
||||
SnapshotAcknowledgementReader.INSTANCE.write(new SnapshotAcknowledgementData(CobblemonBuildDetails.VERSION, dsa));
|
||||
|
||||
runnable.run();
|
||||
return Unit.INSTANCE;
|
||||
}));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Unique
|
||||
@SuppressWarnings("ResultOfMethodCallIgnored")
|
||||
private boolean cobblemon$isAcknowledged() {
|
||||
SnapshotAcknowledgementData data = SnapshotAcknowledgementReader.INSTANCE.read();
|
||||
if (data == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Matcher current = VERSION.matcher(CobblemonBuildDetails.VERSION);
|
||||
current.find();
|
||||
|
||||
Matcher when = VERSION.matcher(data.getVersion());
|
||||
when.find();
|
||||
|
||||
boolean alert = current.group("minor").compareTo(when.group("minor")) > 0 || current.group("major").compareTo(when.group("major")) > 0;
|
||||
return !alert && data.getDontShowAgain();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -25,6 +25,8 @@ import com.cobblemon.mod.common.util.adapters.ExpressionAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.ExpressionLikeAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.ExpressionOrEntityVariableAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.IdentifierAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.MemoryModuleTypeAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.SensorTypeAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.TaskConfigAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.TranslatedTextAdapter
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
@@ -39,6 +41,8 @@ import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.server.packs.PackType
|
||||
import net.minecraft.server.packs.resources.ResourceManager
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
import net.minecraft.world.entity.ai.sensing.SensorType
|
||||
import net.minecraft.world.entity.schedule.Activity
|
||||
|
||||
object CobblemonBehaviours : JsonDataRegistry<CobblemonBehaviour> {
|
||||
@@ -47,6 +51,8 @@ object CobblemonBehaviours : JsonDataRegistry<CobblemonBehaviour> {
|
||||
.registerTypeAdapter(Activity::class.java, ActivityAdapter)
|
||||
.registerTypeAdapter(Expression::class.java, ExpressionAdapter)
|
||||
.registerTypeAdapter(ExpressionLike::class.java, ExpressionLikeAdapter)
|
||||
.registerTypeAdapter(MemoryModuleType::class.java, MemoryModuleTypeAdapter)
|
||||
.registerTypeAdapter(SensorType::class.java, SensorTypeAdapter)
|
||||
.registerTypeAdapter(BehaviourConfig::class.java, BehaviourConfigAdapter)
|
||||
.registerTypeAdapter(TaskConfig::class.java, TaskConfigAdapter)
|
||||
.registerTypeAdapter(
|
||||
|
||||
@@ -34,13 +34,10 @@ import net.minecraft.resources.ResourceKey
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.util.valueproviders.UniformInt
|
||||
import net.minecraft.world.effect.MobEffects
|
||||
import net.minecraft.world.entity.Entity
|
||||
import net.minecraft.world.entity.EntityType
|
||||
import net.minecraft.world.level.BlockGetter
|
||||
import net.minecraft.world.level.Level
|
||||
import net.minecraft.world.level.block.*
|
||||
import net.minecraft.world.level.block.state.BlockBehaviour
|
||||
import net.minecraft.world.level.block.state.BlockBehaviour.Properties
|
||||
import net.minecraft.world.level.block.state.BlockState
|
||||
import net.minecraft.world.level.block.state.properties.BlockSetType
|
||||
import net.minecraft.world.level.block.state.properties.BlockStateProperties.LIT
|
||||
@@ -179,7 +176,7 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
|
||||
@JvmField
|
||||
val SACCHARINE_LOG = this.create("saccharine_log", SaccharineLogBlock(BlockBehaviour.Properties.of().mapColor(MapColor.COLOR_BLUE).instrument(NoteBlockInstrument.BASS).strength(2.0F).sound(SoundType.WOOD).ignitedByLava()))
|
||||
@JvmField
|
||||
val SACCHARINE_HONEY_LOG = this.create("saccharine_honey_log", SaccharineHoneyLogBlock(BlockBehaviour.Properties.of().mapColor(MapColor.COLOR_BLUE).instrument(NoteBlockInstrument.BASS).strength(2.0F).sound(SoundType.WOOD).ignitedByLava()))
|
||||
val SACCHARINE_LOG_SLATHERED = this.create("saccharine_log_slathered", SaccharineLogSlatheredBlock(BlockBehaviour.Properties.of().mapColor(MapColor.COLOR_BLUE).instrument(NoteBlockInstrument.BASS).strength(2.0F).sound(SoundType.WOOD).ignitedByLava()))
|
||||
|
||||
@JvmField
|
||||
val STRIPPED_SACCHARINE_LOG = this.create("stripped_saccharine_log", RotatedPillarBlock(BlockBehaviour.Properties.of().mapColor(MapColor.COLOR_LIGHT_BLUE).instrument(NoteBlockInstrument.BASS).strength(2.0F).sound(SoundType.WOOD).ignitedByLava())) //log("stripped_saccharine_log")
|
||||
@@ -208,7 +205,7 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
|
||||
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)))
|
||||
|
||||
@JvmField
|
||||
val SACCHARINE_BUTTON = this.create("saccharine_button", BlocksInvoker.createWoodenButtonBlock(BlockSetType.OAK))
|
||||
@JvmField
|
||||
val SACCHARINE_PRESSURE_PLATE = this.create("saccharine_pressure_plate", PressurePlateBlockInvoker.`cobblemon$create`(SACCHARINE_BLOCK_SET_TYPE, BlockBehaviour.Properties.of().mapColor(SACCHARINE_PLANKS.defaultMapColor()).instrument(NoteBlockInstrument.BASS).noCollission().strength(0.5f).sound(SoundType.WOOD)))
|
||||
@@ -477,20 +474,20 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
|
||||
val GIMMIGHOUL_CHEST = create("gimmighoul_chest", GildedChestBlock(BlockBehaviour.Properties.ofFullCopy(Blocks.CHEST).noOcclusion().sound(CobblemonSounds.GILDED_CHEST_SOUNDS), GildedChestBlock.Type.FAKE))
|
||||
|
||||
@JvmField
|
||||
val MONITOR = create("monitor", MonitorBlock(BlockBehaviour.Properties.of().mapColor(MapColor.METAL).sound(SoundType.METAL).pushReaction(PushReaction.BLOCK).requiresCorrectToolForDrops().strength(5.0F, 6.0F).lightLevel { if (it.getValue(MonitorBlock.SCREEN) != MonitorBlock.MonitorScreen.OFF) 15 else 0 }))
|
||||
val MONITOR = create("monitor", MonitorBlock(BlockBehaviour.Properties.of().mapColor(MapColor.METAL).sound(SoundType.METAL).pushReaction(PushReaction.BLOCK).requiresCorrectToolForDrops().strength(5.0F, 6.0F).lightLevel { if (it.getValue(MonitorBlock.SCREEN) != MonitorBlock.MonitorScreen.OFF) 13 else 0 }))
|
||||
@JvmField
|
||||
val FOSSIL_ANALYZER = create("fossil_analyzer", FossilAnalyzerBlock(BlockBehaviour.Properties.of().mapColor(MapColor.METAL).sound(SoundType.METAL).pushReaction(PushReaction.BLOCK).requiresCorrectToolForDrops().strength(5.0F, 6.0F).noOcclusion()))
|
||||
@JvmField
|
||||
val RESTORATION_TANK = create("restoration_tank", RestorationTankBlock(BlockBehaviour.Properties.of().mapColor(MapColor.METAL).sound(SoundType.GLASS).pushReaction(PushReaction.BLOCK).requiresCorrectToolForDrops().strength(5.0F, 6.0F).noOcclusion()))
|
||||
|
||||
@JvmField
|
||||
val HEALING_MACHINE = create("healing_machine", HealingMachineBlock(BlockBehaviour.Properties.of().mapColor(MapColor.METAL).sound(SoundType.METAL).pushReaction(PushReaction.BLOCK).strength(2f).noOcclusion().lightLevel { if (it.getValue(HealingMachineBlock.CHARGE_LEVEL) >= HealingMachineBlock.MAX_CHARGE_LEVEL) 7 else 2 }))
|
||||
val HEALING_MACHINE = create("healing_machine", HealingMachineBlock(BlockBehaviour.Properties.of().mapColor(MapColor.METAL).sound(SoundType.METAL).pushReaction(PushReaction.BLOCK).strength(2f).noOcclusion().lightLevel { if (it.getValue(HealingMachineBlock.CHARGE_LEVEL) >= HealingMachineBlock.MAX_CHARGE_LEVEL) 12 else 5 }))
|
||||
|
||||
@JvmField
|
||||
val PC = create("pc", PCBlock(BlockBehaviour.Properties.of().mapColor(MapColor.METAL).sound(SoundType.METAL).pushReaction(PushReaction.BLOCK).strength(2F).noOcclusion().lightLevel { if ((it.getValue(PCBlock.ON) as Boolean) && (it.getValue(PCBlock.PART) == PCBlock.PCPart.TOP)) 10 else 0 }))
|
||||
val PC = create("pc", PCBlock(BlockBehaviour.Properties.of().mapColor(MapColor.METAL).sound(SoundType.METAL).pushReaction(PushReaction.BLOCK).strength(2F).noOcclusion().lightLevel { if ((it.getValue(PCBlock.ON) as Boolean) && (it.getValue(PCBlock.PART) == PCBlock.PCPart.TOP)) 13 else 0 }))
|
||||
|
||||
@JvmField
|
||||
val LECTERN = create("lectern", LecternBlock(BlockBehaviour.Properties.of().mapColor(MapColor.WOOD).instrument(NoteBlockInstrument.BASS).sound(SoundType.WOOD).strength(2.5F).ignitedByLava()))
|
||||
val LECTERN = create("lectern", LecternBlock(BlockBehaviour.Properties.of().mapColor(MapColor.WOOD).instrument(NoteBlockInstrument.BASS).sound(SoundType.WOOD).strength(2.5F).ignitedByLava().lightLevel { if (it.getValue(LecternBlock.EMIT_LIGHT) as Boolean) 13 else 0 }))
|
||||
|
||||
@JvmField
|
||||
val DISPLAY_CASE = create("display_case", DisplayCaseBlock(BlockBehaviour.Properties.of().sound(CobblemonSounds.DISPLAY_CASE_SOUNDS).noOcclusion().pushReaction(PushReaction.BLOCK).mapColor(MapColor.STONE).strength(0.3F).requiresCorrectToolForDrops()))
|
||||
@@ -499,7 +496,7 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
|
||||
val INCENSE_SWEET = create("incense_sweet", SweetIncenseBlock(BlockBehaviour.Properties.of().sound(CobblemonSounds.DISPLAY_CASE_SOUNDS).noOcclusion().pushReaction(PushReaction.BLOCK).mapColor(MapColor.STONE).strength(0.3f)))
|
||||
|
||||
@JvmField
|
||||
val PASTURE = create("pasture", PastureBlock(BlockBehaviour.Properties.of().mapColor(MapColor.COLOR_BROWN).sound(SoundType.WOOD).strength(2F).noOcclusion().pushReaction(PushReaction.BLOCK).lightLevel { if ((it.getValue(PastureBlock.ON) as Boolean) && (it.getValue(PastureBlock.PART) == PastureBlock.PasturePart.TOP)) 10 else 0 }))
|
||||
val PASTURE = create("pasture", PastureBlock(BlockBehaviour.Properties.of().mapColor(MapColor.COLOR_BROWN).sound(SoundType.WOOD).strength(2F).noOcclusion().pushReaction(PushReaction.BLOCK).lightLevel { if ((it.getValue(PastureBlock.ON) as Boolean) && (it.getValue(PastureBlock.PART) == PastureBlock.PasturePart.TOP)) 13 else 0 }))
|
||||
|
||||
val RED_MINT = create("red_mint", MintBlock(MintType.RED, BlockBehaviour.Properties.of().mapColor(MapColor.COLOR_RED).noCollission().randomTicks().instabreak().sound(CobblemonSounds.MINT_SOUNDS).pushReaction(PushReaction.DESTROY)))
|
||||
@JvmField
|
||||
@@ -523,7 +520,7 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
|
||||
val HEARTY_GRAINS = this.create("hearty_grains", HeartyGrainsBlock(BlockBehaviour.Properties.of().pushReaction(PushReaction.DESTROY).ignitedByLava().mapColor(MapColor.PLANT).noCollission().randomTicks().instabreak().sound(CobblemonSounds.VIVICHOKE_SOUNDS)))
|
||||
|
||||
@JvmField
|
||||
val GALARICA_NUT_BUSH = this.create("galarica_nut_bush", NutBushBlock(Properties.of().mapColor(MapColor.PLANT).randomTicks().noCollission().sound(SoundType.SWEET_BERRY_BUSH).pushReaction(PushReaction.DESTROY)))
|
||||
val GALARICA_NUT_BUSH = this.create("galarica_nut_bush", NutBushBlock(BlockBehaviour.Properties.of().mapColor(MapColor.PLANT).randomTicks().noCollission().sound(SoundType.SWEET_BERRY_BUSH).pushReaction(PushReaction.DESTROY)))
|
||||
|
||||
@JvmField
|
||||
val POTTED_RED_APRICORN_SAPLING = this.create("potted_red_apricorn_sapling", BlocksInvoker.createFlowerPotBlock(RED_APRICORN_SAPLING))
|
||||
@@ -545,9 +542,9 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
|
||||
@JvmField
|
||||
val HEARTY_GRAIN_BALE = this.create("hearty_grain_bale", BaleBlock(BlockBehaviour.Properties.of().mapColor(MapColor.PLANT).instrument(NoteBlockInstrument.BANJO).strength(0.5F).sound(SoundType.GRASS)))
|
||||
@JvmField
|
||||
val TATAMI_BLOCK = this.create("tatami_block", HorizontalRotationalBlock(BlockBehaviour.Properties.of().ignitedByLava().mapColor(MapColor.PLANT).strength(0.1F).sound(SoundType.GRASS)))
|
||||
val TATAMI_BLOCK = this.create("tatami_block", HorizontalRotationalBlock(BlockBehaviour.Properties.of().ignitedByLava().mapColor(MapColor.PLANT).strength(0.1F).sound(SoundType.MOSS_CARPET)))
|
||||
@JvmField
|
||||
val TATAMI_MAT = this.create("tatami_mat", HorizontalRotationCarpetBlock(BlockBehaviour.Properties.of().ignitedByLava().mapColor(MapColor.PLANT).strength(0.1F).sound(SoundType.GRASS)))
|
||||
val TATAMI_MAT = this.create("tatami_mat", HorizontalRotationCarpetBlock(BlockBehaviour.Properties.of().ignitedByLava().mapColor(MapColor.PLANT).strength(0.1F).sound(SoundType.MOSS_CARPET)))
|
||||
|
||||
/**
|
||||
* Returns a map of all the blocks that can be stripped with an axe in the format of input - output.
|
||||
@@ -559,11 +556,9 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
|
||||
APRICORN_LOG to STRIPPED_APRICORN_LOG,
|
||||
SACCHARINE_WOOD to STRIPPED_SACCHARINE_WOOD,
|
||||
SACCHARINE_LOG to STRIPPED_SACCHARINE_LOG,
|
||||
SACCHARINE_HONEY_LOG to STRIPPED_SACCHARINE_LOG
|
||||
SACCHARINE_LOG_SLATHERED to STRIPPED_SACCHARINE_LOG
|
||||
)
|
||||
|
||||
|
||||
|
||||
private fun apricornBlock(name: String, apricorn: Apricorn): ApricornBlock = this.create(name, ApricornBlock(BlockBehaviour.Properties.of().mapColor(apricorn.mapColor()).randomTicks().strength(Blocks.OAK_LOG.defaultDestroyTime(), Blocks.OAK_LOG.explosionResistance).sound(SoundType.WOOD).noOcclusion(), apricorn))
|
||||
|
||||
private fun tumblestoneBlock(name: String, stage: Int, height: Int, xzOffset: Int, nextStage: Block?) : Block {
|
||||
@@ -663,7 +658,19 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
|
||||
Triple(APRICORN_FENCE, 5, 20),
|
||||
Triple(APRICORN_FENCE_GATE, 5, 20),
|
||||
Triple(APRICORN_SLAB, 5, 20),
|
||||
Triple(APRICORN_STAIRS, 5, 20)
|
||||
Triple(APRICORN_STAIRS, 5, 20),
|
||||
Triple(SACCHARINE_LOG, 5, 5),
|
||||
Triple(SACCHARINE_LOG_SLATHERED, 5, 5),
|
||||
Triple(STRIPPED_SACCHARINE_LOG, 5, 5),
|
||||
Triple(SACCHARINE_WOOD, 5, 5),
|
||||
Triple(STRIPPED_SACCHARINE_WOOD, 5, 5),
|
||||
Triple(SACCHARINE_PLANKS, 5, 20),
|
||||
Triple(SACCHARINE_LEAVES, 30, 60),
|
||||
Triple(SACCHARINE_FENCE, 5, 20),
|
||||
Triple(SACCHARINE_FENCE_GATE, 5, 20),
|
||||
Triple(SACCHARINE_SLAB, 5, 20),
|
||||
Triple(SACCHARINE_STAIRS, 5, 20)
|
||||
|
||||
).onEach{ data -> setFlammable(data.first, data.second, data.third) }
|
||||
}
|
||||
|
||||
|
||||
@@ -310,7 +310,7 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
@JvmField
|
||||
val SACCHARINE_LOG = blockItem("saccharine_log", CobblemonBlocks.SACCHARINE_LOG)
|
||||
@JvmField
|
||||
val SACCHARINE_HONEY_LOG = blockItem("saccharine_honey_log", CobblemonBlocks.SACCHARINE_HONEY_LOG)
|
||||
val SACCHARINE_LOG_SLATHERED = blockItem("saccharine_log_slathered", CobblemonBlocks.SACCHARINE_LOG_SLATHERED)
|
||||
@JvmField
|
||||
val STRIPPED_SACCHARINE_LOG = blockItem("stripped_saccharine_log", CobblemonBlocks.STRIPPED_SACCHARINE_LOG)
|
||||
@JvmField
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
package com.cobblemon.mod.common
|
||||
|
||||
import com.cobblemon.mod.common.api.ai.CobblemonAttackTargetData
|
||||
import com.cobblemon.mod.common.api.dialogue.ActiveDialogue
|
||||
import com.cobblemon.mod.common.api.moves.animations.ActionEffectContext
|
||||
import com.mojang.serialization.Codec
|
||||
@@ -46,6 +47,7 @@ object CobblemonMemories {
|
||||
val HERD_LEADER = register<String>("herd_leader", PrimitiveCodec.STRING)
|
||||
/** 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.
|
||||
|
||||
fun <U> register(id: String, codec: Codec<U>): MemoryModuleType<U> {
|
||||
val memoryModule = MemoryModuleType(Optional.of(codec))
|
||||
|
||||
@@ -36,6 +36,7 @@ import com.cobblemon.mod.common.client.net.pasture.ClosePastureHandler
|
||||
import com.cobblemon.mod.common.client.net.pasture.OpenPastureHandler
|
||||
import com.cobblemon.mod.common.client.net.pasture.PokemonPasturedHandler
|
||||
import com.cobblemon.mod.common.client.net.pasture.PokemonUnpasturedHandler
|
||||
import com.cobblemon.mod.common.client.net.pasture.UpdatePastureConflictFlagHandler
|
||||
import com.cobblemon.mod.common.client.net.pokedex.ServerConfirmedRegisterHandler
|
||||
import com.cobblemon.mod.common.client.net.pokemon.update.ClientboundUpdateRidingStateHandler
|
||||
import com.cobblemon.mod.common.client.net.pokemon.update.PokemonUpdatePacketHandler
|
||||
@@ -85,6 +86,7 @@ import com.cobblemon.mod.common.net.messages.client.pasture.ClosePasturePacket
|
||||
import com.cobblemon.mod.common.net.messages.client.pasture.OpenPasturePacket
|
||||
import com.cobblemon.mod.common.net.messages.client.pasture.PokemonPasturedPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.pasture.PokemonUnpasturedPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.pasture.UpdatePastureConflictFlagPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.pokedex.ServerConfirmedRegisterPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.pokemon.update.*
|
||||
import com.cobblemon.mod.common.net.messages.client.pokemon.update.evolution.AddEvolutionPacket
|
||||
@@ -140,6 +142,7 @@ import com.cobblemon.mod.common.net.messages.server.battle.BattleTeamRequestPack
|
||||
import com.cobblemon.mod.common.net.messages.server.battle.BattleTeamResponsePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.battle.RemoveSpectatorPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.battle.SpectateBattlePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.behaviour.DamageOnCollisionPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.behaviour.SetEntityBehaviourPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.block.AdjustBlockEntityViewerCountPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.callback.move.MoveSelectCancelledPacket
|
||||
@@ -155,6 +158,7 @@ import com.cobblemon.mod.common.net.messages.server.dialogue.InputToDialoguePack
|
||||
import com.cobblemon.mod.common.net.messages.server.npc.SaveNPCPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.orientation.ServerboundUpdateOrientationPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.pasture.PasturePokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.pasture.SetPastureConflictPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.pasture.UnpastureAllPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.pasture.UnpasturePokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.pokedex.scanner.FinishScanningPacket
|
||||
@@ -166,6 +170,7 @@ import com.cobblemon.mod.common.net.messages.server.pokemon.update.SetActiveMark
|
||||
import com.cobblemon.mod.common.net.messages.server.pokemon.update.SetMarkingsPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.pokemon.update.ServerboundUpdateRidingStatePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.pokemon.update.evolution.AcceptEvolutionPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.riding.DismountPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.starter.RequestStarterScreenPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.storage.SwapPCPartyPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.storage.party.MovePartyPokemonPacket
|
||||
@@ -187,6 +192,7 @@ import com.cobblemon.mod.common.net.serverhandling.battle.SpectateBattleHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.battle.TeamLeaveHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.battle.TeamRequestHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.battle.TeamRequestResponseHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.behaviour.DamageOnCollisionPacketHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.behaviour.SetEntityBehaviourHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.block.AdjustBlockEntityViewerCountHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.callback.move.MoveSelectCancelledHandler
|
||||
@@ -203,6 +209,7 @@ import com.cobblemon.mod.common.net.serverhandling.evolution.AcceptEvolutionHand
|
||||
import com.cobblemon.mod.common.net.serverhandling.npc.SaveNPCHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.orientation.OrientationPacketHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.pasture.PasturePokemonHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.pasture.SetPastureConflictHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.pasture.UnpastureAllPokemonHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.pasture.UnpasturePokemonHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.pokedex.scanner.FinishScanningHandler
|
||||
@@ -213,6 +220,7 @@ import com.cobblemon.mod.common.net.serverhandling.pokemon.update.SetNicknameHan
|
||||
import com.cobblemon.mod.common.net.serverhandling.pokemon.update.SetActiveMarkHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.pokemon.update.SetMarkingsHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.pokemon.update.ServerboundUpdateRidingStateHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.riding.DismountPokemonPacketHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.starter.RequestStarterScreenHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.starter.SelectStarterPacketHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.storage.BenchMoveHandler
|
||||
@@ -418,6 +426,7 @@ object CobblemonNetwork {
|
||||
list.add(PacketRegisterInfo(ClosePasturePacket.ID, ClosePasturePacket::decode, ClosePastureHandler))
|
||||
list.add(PacketRegisterInfo(PokemonPasturedPacket.ID, PokemonPasturedPacket::decode, PokemonPasturedHandler))
|
||||
list.add(PacketRegisterInfo(PokemonUnpasturedPacket.ID, PokemonUnpasturedPacket::decode, PokemonUnpasturedHandler))
|
||||
list.add(PacketRegisterInfo(UpdatePastureConflictFlagPacket.ID, UpdatePastureConflictFlagPacket::decode, UpdatePastureConflictFlagHandler))
|
||||
|
||||
// Orientation
|
||||
list.add(PacketRegisterInfo(ClientboundUpdateOrientationPacket.ID, ClientboundUpdateOrientationPacket::decode, S2CUpdateOrientationHandler))
|
||||
@@ -528,6 +537,8 @@ object CobblemonNetwork {
|
||||
list.add(PacketRegisterInfo(PasturePokemonPacket.ID, PasturePokemonPacket::decode, PasturePokemonHandler))
|
||||
list.add(PacketRegisterInfo(UnpasturePokemonPacket.ID, UnpasturePokemonPacket::decode, UnpasturePokemonHandler))
|
||||
list.add(PacketRegisterInfo(UnpastureAllPokemonPacket.ID, UnpastureAllPokemonPacket::decode, UnpastureAllPokemonHandler))
|
||||
list.add(PacketRegisterInfo(SetPastureConflictPacket.ID, SetPastureConflictPacket::decode, SetPastureConflictHandler))
|
||||
|
||||
|
||||
// Block entity
|
||||
list.add(PacketRegisterInfo(AdjustBlockEntityViewerCountPacket.ID, AdjustBlockEntityViewerCountPacket::decode, AdjustBlockEntityViewerCountHandler))
|
||||
@@ -556,12 +567,14 @@ 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(DismountPokemonPacket.ID, DismountPokemonPacket::decode, DismountPokemonPacketHandler))
|
||||
|
||||
// Cooking
|
||||
list.add(PacketRegisterInfo(ToggleCookingPotLidPacket.ID, ToggleCookingPotLidPacket::decode, ToggleCookingPotLidHandler))
|
||||
|
||||
// Behaviour Packets
|
||||
list.add(PacketRegisterInfo(SetEntityBehaviourPacket.ID, SetEntityBehaviourPacket::decode, SetEntityBehaviourHandler))
|
||||
list.add(PacketRegisterInfo(DamageOnCollisionPacket.ID, DamageOnCollisionPacket::decode, DamageOnCollisionPacketHandler))
|
||||
|
||||
return list
|
||||
}
|
||||
|
||||
@@ -24,23 +24,18 @@ object CobblemonPoiTypes: PlatformRegistry<Registry<PoiType>, ResourceKey<Regist
|
||||
override val resourceKey: ResourceKey<Registry<PoiType>> = Registries.POINT_OF_INTEREST_TYPE
|
||||
|
||||
@JvmField
|
||||
val NURSE_KEY: ResourceKey<PoiType> = createKey("nurse")
|
||||
val NURSE_KEY = createKey("nurse", CobblemonBlocks.HEALING_MACHINE, 1, 1)
|
||||
@JvmField
|
||||
val NURSE = create(NURSE_KEY.location().path, PoiType(getBlockStates(CobblemonBlocks.HEALING_MACHINE), 1, 1))
|
||||
val LURE_CAKE_KEY = createKey("lure_cake", CobblemonBlocks.LURE_CAKE, 0, 1)
|
||||
@JvmField
|
||||
val LURE_CAKE_KEY: ResourceKey<PoiType> = createKey("lure_cake")
|
||||
val SACCHARINE_LOG_SLATHERED_KEY = createKey("saccharine_log_slathered", CobblemonBlocks.SACCHARINE_LOG_SLATHERED, 0, 1)
|
||||
@JvmField
|
||||
val LURE_CAKE = create(LURE_CAKE_KEY.location().path, PoiType(getBlockStates(CobblemonBlocks.LURE_CAKE), 0, 1))
|
||||
@JvmField
|
||||
val SACCHARINE_HONEY_LOG_KEY: ResourceKey<PoiType> = createKey("saccharine_honey_log")
|
||||
@JvmField
|
||||
val SACCHARINE_HONEY_LOG = create(SACCHARINE_HONEY_LOG_KEY.location().path, PoiType(getBlockStates(CobblemonBlocks.SACCHARINE_HONEY_LOG), 0, 1))
|
||||
@JvmField
|
||||
val INCENSE_SWEET_KEY: ResourceKey<PoiType> = createKey("incense_sweet")
|
||||
@JvmField
|
||||
val INCENSE_SWEET = create(INCENSE_SWEET_KEY.location().path, PoiType(getBlockStates(CobblemonBlocks.INCENSE_SWEET), 0, 1))
|
||||
val INCENSE_SWEET_KEY = createKey("incense_sweet", CobblemonBlocks.INCENSE_SWEET, 0, 1)
|
||||
|
||||
private fun createKey(string: String): ResourceKey<PoiType> = ResourceKey.create(Registries.POINT_OF_INTEREST_TYPE, cobblemonResource(string))
|
||||
private fun createKey(string: String, block: Block, maxTickets: Int, validRange: Int ): ResourceKey<PoiType> =
|
||||
ResourceKey.create(Registries.POINT_OF_INTEREST_TYPE, cobblemonResource(string)).also { resourceKey ->
|
||||
create(resourceKey.location().path, PoiType(getBlockStates(block), maxTickets, validRange))
|
||||
}
|
||||
|
||||
private fun getBlockStates(block: Block): Set<BlockState> = ImmutableSet.copyOf(block.stateDefinition.possibleStates)
|
||||
}
|
||||
}
|
||||
|
||||
+26
-2
@@ -10,8 +10,11 @@ package com.cobblemon.mod.common.api.ai
|
||||
|
||||
import com.cobblemon.mod.common.api.ai.config.BehaviourConfig
|
||||
import com.cobblemon.mod.common.entity.MoLangScriptingEntity
|
||||
import com.mojang.serialization.Dynamic
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
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
|
||||
|
||||
@@ -22,13 +25,30 @@ class BehaviourConfigurationContext {
|
||||
var coreActivities = setOf(Activity.CORE)
|
||||
val activities = mutableListOf<ActivityConfigurationContext>()
|
||||
val schedule = Schedule.EMPTY
|
||||
val memories = mutableSetOf<MemoryModuleType<*>>()
|
||||
val sensors = mutableSetOf<SensorType<*>>()
|
||||
|
||||
fun getOrCreateActivity(activity: Activity): ActivityConfigurationContext {
|
||||
return activities.firstOrNull { it.activity == activity } ?: ActivityConfigurationContext(activity).also(activities::add)
|
||||
}
|
||||
|
||||
fun apply(entity: LivingEntity, behaviourConfigs: List<BehaviourConfig>) {
|
||||
val brain = entity.brain
|
||||
fun addMemories(vararg memory: MemoryModuleType<*>) {
|
||||
memories.addAll(memory)
|
||||
}
|
||||
|
||||
fun addMemories(memories: Collection<MemoryModuleType<*>>) {
|
||||
this.memories.addAll(memories)
|
||||
}
|
||||
|
||||
fun addSensors(vararg sensor: SensorType<*>) {
|
||||
sensors.addAll(sensor)
|
||||
}
|
||||
|
||||
fun addSensors(sensors: Collection<SensorType<*>>) {
|
||||
this.sensors.addAll(sensors)
|
||||
}
|
||||
|
||||
fun apply(entity: LivingEntity, behaviourConfigs: List<BehaviourConfig>, dynamic: Dynamic<*>) {
|
||||
|
||||
if (entity is MoLangScriptingEntity) {
|
||||
entity.registerVariables(behaviourConfigs.flatMap { it.getVariables(entity) })
|
||||
@@ -38,7 +58,11 @@ class BehaviourConfigurationContext {
|
||||
// Setup the brain config
|
||||
behaviourConfigs.forEach { it.configure(entity, this) }
|
||||
|
||||
var brain = entity.brain
|
||||
// Apply the brain config
|
||||
if (entity is MoLangScriptingEntity) {
|
||||
brain = entity.assignNewBrainWithMemoriesAndSensors(dynamic, memories, sensors)
|
||||
}
|
||||
activities.forEach { it.apply(entity) }
|
||||
brain.setCoreActivities(coreActivities)
|
||||
brain.setDefaultActivity(defaultActivity)
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.ai
|
||||
|
||||
import com.bedrockk.molang.Expression
|
||||
import com.cobblemon.mod.common.util.asExpression
|
||||
|
||||
/**
|
||||
* This is used in the AI system to store optional additional information about the attack target,
|
||||
* mainly things like when to give up pursuit, what sort of attacks are permitted, whatever. It's
|
||||
* a temporary memory, same as ATTACK_TARGET, so relogs will clear it and that's why it has no codec.
|
||||
*
|
||||
* To help you get a sense of a use case, imagine a Pidgeotto has an AI task that says it should hunt
|
||||
* Magikarp that are close to the surface. Once they've found one and chosen them as the attack target,
|
||||
* they should give up the target if the Magikarp goes too deep, but if it's attacking an entity because
|
||||
* they attacked its owner, it shouldn't give up on the target for that reason. To address this, when
|
||||
* hunting Magikarp, the Pidgeotto will set this memory to a CobblemonAttackTargetData with some
|
||||
* [Expression] that encourages the entity to give up the target if the Magikarp goes too deep.
|
||||
*
|
||||
* To make this work, any transition from the FIGHT activity will erase this memory.
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since June 23rd, 2025
|
||||
*/
|
||||
class CobblemonAttackTargetData(
|
||||
/** An expression that returns false when the target is no longer worth attacking. */
|
||||
val shouldContinue: Expression = "true".asExpression()
|
||||
)
|
||||
@@ -15,6 +15,11 @@ import kotlin.jvm.optionals.getOrNull
|
||||
|
||||
typealias ExpressionOrEntityVariable = Either<Expression, MoLangConfigVariable>
|
||||
|
||||
/**
|
||||
* In the case of [ExpressionOrEntityVariable] the right side is the only one that requires visibility for a user,
|
||||
* this function is a shorthand for finding all of the values in the list that have something to show the user to
|
||||
* potentially edit.
|
||||
*/
|
||||
fun List<ExpressionOrEntityVariable>.asVariables() = mapNotNull { it.right().getOrNull() }
|
||||
|
||||
|
||||
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.ai.config
|
||||
|
||||
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.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
|
||||
|
||||
/**
|
||||
* Does nothing except conditionally add some memories and sensors to the brain of the entity.
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since June 27th, 2025
|
||||
*/
|
||||
class AddMemoriesAndSensorsConfig : BehaviourConfig {
|
||||
val condition: ExpressionOrEntityVariable = Either.left("true".asExpression())
|
||||
val memories: Set<MemoryModuleType<*>> = emptySet()
|
||||
val sensors: Set<SensorType<*>> = mutableSetOf()
|
||||
|
||||
override fun getVariables(entity: LivingEntity) = listOf(condition).asVariables()
|
||||
override fun configure(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext) {
|
||||
if (!checkCondition(entity, condition)) return
|
||||
behaviourConfigurationContext.addMemories(memories)
|
||||
behaviourConfigurationContext.addSensors(sensors)
|
||||
}
|
||||
}
|
||||
@@ -23,8 +23,8 @@ class AddTasksToActivity : BehaviourConfig {
|
||||
val activities = mutableListOf<Activity>()
|
||||
val condition: ExpressionOrEntityVariable = Either.left("true".asExpression())
|
||||
val tasksByPriority = mutableMapOf<Int, List<TaskConfig>>()
|
||||
override fun getVariables(entity: LivingEntity) = tasksByPriority.values.flatten().flatMap { it.getVariables(entity) } + 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(entity, condition)) return
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ class ApplyBehaviours : BehaviourConfig {
|
||||
var condition: ExpressionOrEntityVariable = Either.left("true".asExpression())
|
||||
@SerializedName("behaviours", alternate = ["behaviors"])
|
||||
val behaviours = mutableListOf<ResourceLocation>()
|
||||
|
||||
override fun getVariables(entity: LivingEntity): List<MoLangConfigVariable> {
|
||||
return if (checkCondition(entity, condition)) {
|
||||
behaviours.flatMap {
|
||||
|
||||
@@ -44,6 +44,7 @@ interface BehaviourConfig {
|
||||
cobblemonResource("set_core_activities") to SetCoreActivities::class.java,
|
||||
cobblemonResource("add_variables") to AddVariablesConfig::class.java,
|
||||
cobblemonResource("set_variables") to SetVariablesConfig::class.java,
|
||||
cobblemonResource("add_memories_and_sensors") to AddMemoriesAndSensorsConfig::class.java,
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
+10
-4
@@ -21,19 +21,25 @@ 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 {
|
||||
var condition: ExpressionOrEntityVariable = Either.left("true".asExpression())
|
||||
val variables: List<MoLangConfigVariable> = emptyList()
|
||||
val script: ExpressionLike = "0".asExpressionLike()
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
+15
-6
@@ -14,6 +14,7 @@ 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.MoLangFunctions.addStandardFunctions
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMostSpecificMoLangValue
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.setup
|
||||
@@ -21,34 +22,42 @@ 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.asExpressionLike
|
||||
import com.cobblemon.mod.common.util.asExpression
|
||||
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.resolveBoolean
|
||||
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
|
||||
|
||||
class ScriptBehaviourConfig : BehaviourConfig {
|
||||
val condition = "true".asExpressionLike()
|
||||
val condition: ExpressionOrEntityVariable = Either.left("true".asExpression())
|
||||
val script = cobblemonResource("dummy")
|
||||
val variables = mutableListOf<MoLangConfigVariable>()
|
||||
val memories = emptySet<MemoryModuleType<*>>()
|
||||
val sensors = emptySet<SensorType<*>>()
|
||||
|
||||
override fun getVariables(entity: LivingEntity) = variables
|
||||
|
||||
override fun configure(entity: LivingEntity, context: BehaviourConfigurationContext) {
|
||||
override fun configure(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext) {
|
||||
if (!checkCondition(entity, condition)) return
|
||||
val runtime = MoLangRuntime().setup()
|
||||
runtime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
if (!runtime.resolveBoolean(condition)) return
|
||||
|
||||
val struct = createBrainStruct(entity, context)
|
||||
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))
|
||||
}
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ import net.minecraft.world.entity.schedule.Activity
|
||||
|
||||
class SetDefaultActivity : BehaviourConfig {
|
||||
val activity: Activity = Activity.IDLE
|
||||
|
||||
override fun getVariables(entity: LivingEntity) = emptyList<MoLangConfigVariable>()
|
||||
override fun configure(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext) {
|
||||
behaviourConfigurationContext.defaultActivity = activity
|
||||
|
||||
@@ -23,7 +23,6 @@ class SetVariablesConfig : BehaviourConfig {
|
||||
var variableValues = mutableMapOf<String, ExpressionLike>()
|
||||
|
||||
override fun getVariables(entity: LivingEntity) = emptyList<MoLangConfigVariable>()
|
||||
|
||||
override fun configure(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext) {
|
||||
val runtime = MoLangRuntime().setup()
|
||||
runtime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
|
||||
+1
-2
@@ -15,8 +15,6 @@ import com.cobblemon.mod.common.api.ai.asVariables
|
||||
import com.cobblemon.mod.common.api.ai.config.task.WanderTaskConfig.Companion.WANDER
|
||||
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.entity.pokemon.ai.PokemonMoveControl
|
||||
import com.cobblemon.mod.common.util.asExpression
|
||||
import com.cobblemon.mod.common.util.resolveFloat
|
||||
import com.cobblemon.mod.common.util.withQueryValue
|
||||
@@ -50,6 +48,7 @@ class AirWanderTaskConfig : SingleTaskConfig {
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
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)
|
||||
|
||||
return BehaviorBuilder.create {
|
||||
|
||||
+2
-9
@@ -10,9 +10,7 @@ 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
|
||||
@@ -23,19 +21,14 @@ class AllOfTaskConfig : TaskConfig {
|
||||
val condition: ExpressionOrEntityVariable = Either.left("true".asExpression())
|
||||
val tasks: List<TaskConfig> = emptyList()
|
||||
|
||||
override fun getVariables(entity: LivingEntity): List<MoLangConfigVariable> {
|
||||
return if (checkCondition(entity, condition))
|
||||
tasks.flatMap { it.getVariables(entity) } + listOf(condition).asVariables()
|
||||
else
|
||||
listOf(condition).asVariables()
|
||||
}
|
||||
|
||||
override fun getVariables(entity: LivingEntity) = tasks.flatMap { it.getVariables(entity) }
|
||||
override fun createTasks(
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
): List<BehaviorControl<in LivingEntity>> {
|
||||
runtime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
if (!condition.resolveBoolean()) return emptyList()
|
||||
|
||||
return tasks.flatMap { it.createTasks(entity, behaviourConfigurationContext) }
|
||||
}
|
||||
}
|
||||
+5
-8
@@ -8,24 +8,21 @@
|
||||
|
||||
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.ai.AttackAngryAtTask
|
||||
import com.cobblemon.mod.common.util.withQueryValue
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
|
||||
class AttackAngryAtTaskConfig : SingleTaskConfig {
|
||||
val condition = booleanVariable(SharedEntityVariables.ATTACKING_CATEGORY, "should_attack_angry_at", true).asExpressible()
|
||||
override fun getVariables(entity: LivingEntity) = listOf(condition).asVariables()
|
||||
|
||||
override fun getVariables(entity: LivingEntity) = emptyList<MoLangConfigVariable>()
|
||||
override fun createTask(
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
runtime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
if (!condition.resolveBoolean()) return null
|
||||
behaviourConfigurationContext.addMemories(MemoryModuleType.ANGRY_AT, MemoryModuleType.ATTACK_TARGET, CobblemonMemories.POKEMON_SLEEPING)
|
||||
return AttackAngryAtTask.create()
|
||||
}
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* 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.npc.configuration.MoLangConfigVariable
|
||||
import com.cobblemon.mod.common.entity.pokemon.ai.tasks.AttackHostileMobsTask
|
||||
import com.mojang.serialization.Codec
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
|
||||
class AttackHostileMobsTaskConfig : SingleTaskConfig {
|
||||
override fun getVariables(entity: LivingEntity): List<MoLangConfigVariable> {
|
||||
return emptyList<MoLangConfigVariable>()
|
||||
}
|
||||
|
||||
override fun createTask(
|
||||
entity: LivingEntity,
|
||||
brainConfigurationContext: BehaviourConfigurationContext
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
return AttackHostileMobsTask.create()
|
||||
}
|
||||
|
||||
companion object {
|
||||
val CODEC: Codec<AttackHostileMobsTaskConfig> = Codec.unit(AttackHostileMobsTaskConfig())
|
||||
}
|
||||
}
|
||||
+10
-1
@@ -12,22 +12,31 @@ 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
|
||||
import net.minecraft.world.entity.ai.behavior.VillagerCalmDown
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
import net.minecraft.world.entity.ai.sensing.SensorType
|
||||
|
||||
class CalmDownTaskConfig : SingleTaskConfig {
|
||||
var condition: ExpressionOrEntityVariable = Either.left("true".asExpression())
|
||||
override fun getVariables(entity: LivingEntity) = listOf(condition).asVariables()
|
||||
override fun getVariables(entity: LivingEntity) = emptyList<MoLangConfigVariable>()
|
||||
override fun createTask(
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
runtime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
if (!condition.resolveBoolean()) return null
|
||||
behaviourConfigurationContext.addMemories(
|
||||
MemoryModuleType.HURT_BY,
|
||||
MemoryModuleType.HURT_BY_ENTITY,
|
||||
MemoryModuleType.NEAREST_HOSTILE,
|
||||
)
|
||||
behaviourConfigurationContext.addSensors(SensorType.VILLAGER_HOSTILES)
|
||||
return VillagerCalmDown.create()
|
||||
}
|
||||
}
|
||||
+15
-2
@@ -24,6 +24,7 @@ import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
import net.minecraft.world.entity.ai.behavior.declarative.BehaviorBuilder
|
||||
import net.minecraft.world.entity.ai.behavior.declarative.Trigger
|
||||
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.
|
||||
@@ -44,6 +45,12 @@ class CountFollowersTaskConfig : SingleTaskConfig {
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
runtime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
val checkTicksValue = checkTicks.resolveInt()
|
||||
behaviourConfigurationContext.addMemories(
|
||||
MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES,
|
||||
CobblemonMemories.HERD_SIZE,
|
||||
CobblemonMemories.HERD_LEADER
|
||||
)
|
||||
behaviourConfigurationContext.addSensors(SensorType.NEAREST_LIVING_ENTITIES)
|
||||
return BehaviorBuilder.create { instance ->
|
||||
instance.group(
|
||||
instance.present(MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES),
|
||||
@@ -55,9 +62,15 @@ class CountFollowersTaskConfig : SingleTaskConfig {
|
||||
}
|
||||
val myUUID = entity.uuid.toString()
|
||||
val followersCount = instance.get(nearbyEntities).findAll {
|
||||
it is PokemonEntity && it.brain.getMemory(CobblemonMemories.HERD_LEADER).getOrNull() == myUUID
|
||||
it is PokemonEntity
|
||||
&& it.brain.hasMemoryValue(CobblemonMemories.HERD_LEADER)
|
||||
&& it.brain.getMemory(CobblemonMemories.HERD_LEADER).getOrNull() == myUUID
|
||||
}.count()
|
||||
herdCount.set(followersCount)
|
||||
if (followersCount == 0) {
|
||||
herdCount.erase()
|
||||
} else {
|
||||
herdCount.set(followersCount)
|
||||
}
|
||||
return@Trigger true
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -23,7 +23,7 @@ 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) = listOf(condition, minDurationTicks, maxDurationTicks).asVariables()
|
||||
override fun getVariables(entity: LivingEntity) = listOf(minDurationTicks, maxDurationTicks).asVariables()
|
||||
|
||||
override fun createTask(
|
||||
entity: LivingEntity,
|
||||
|
||||
+4
@@ -8,6 +8,7 @@
|
||||
|
||||
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
|
||||
import com.cobblemon.mod.common.api.ai.asVariables
|
||||
@@ -16,6 +17,7 @@ import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.entity.pokemon.ai.tasks.EatGrassTask
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
|
||||
class EatGrassTaskConfig : SingleTaskConfig {
|
||||
companion object {
|
||||
@@ -47,6 +49,8 @@ class EatGrassTaskConfig : SingleTaskConfig {
|
||||
return null
|
||||
}
|
||||
|
||||
behaviourConfigurationContext.addMemories(MemoryModuleType.WALK_TARGET, CobblemonMemories.RECENTLY_ATE_GRASS)
|
||||
|
||||
return WrapperLivingEntityTask(
|
||||
EatGrassTask(
|
||||
chance,
|
||||
|
||||
+13
-1
@@ -9,6 +9,7 @@
|
||||
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.asVariables
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMostSpecificMoLangValue
|
||||
@@ -21,6 +22,7 @@ import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
import net.minecraft.world.entity.ai.behavior.declarative.BehaviorBuilder
|
||||
import net.minecraft.world.entity.ai.behavior.declarative.Trigger
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
import net.minecraft.world.entity.ai.sensing.SensorType
|
||||
|
||||
class ExitBattleWhenHurtTaskConfig : SingleTaskConfig {
|
||||
var condition = booleanVariable(SharedEntityVariables.BATTLING_CATEGORY, "exit_battle_when_hurt", true).asExpressible()
|
||||
@@ -36,10 +38,19 @@ class ExitBattleWhenHurtTaskConfig : SingleTaskConfig {
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
runtime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
val includePassiveDamage = includePassiveDamage.resolveBoolean()
|
||||
if (!condition.resolveBoolean()) return null
|
||||
|
||||
val includePassiveDamage = includePassiveDamage.resolveBoolean()
|
||||
|
||||
behaviourConfigurationContext.addMemories(
|
||||
MemoryModuleType.HURT_BY,
|
||||
MemoryModuleType.HURT_BY_ENTITY
|
||||
)
|
||||
behaviourConfigurationContext.addSensors(SensorType.HURT_BY)
|
||||
|
||||
if (entity is NPCEntity) {
|
||||
behaviourConfigurationContext.addMemories(CobblemonMemories.NPC_BATTLING)
|
||||
behaviourConfigurationContext.addSensors(CobblemonSensors.NPC_BATTLING)
|
||||
fun cancelNPCBattles(npcEntity: NPCEntity): Boolean {
|
||||
val battles = npcEntity.battleIds.mapNotNull(BattleRegistry::getBattle)
|
||||
battles.forEach { it.end() }
|
||||
@@ -58,6 +69,7 @@ class ExitBattleWhenHurtTaskConfig : SingleTaskConfig {
|
||||
}
|
||||
}
|
||||
} else if (entity is PokemonEntity) {
|
||||
behaviourConfigurationContext.addMemories(CobblemonMemories.POKEMON_BATTLE)
|
||||
fun cancelPokemonBattle(pokemonEntity: PokemonEntity): Boolean {
|
||||
val battle = BattleRegistry.getBattle(pokemonEntity.battleId ?: return false)
|
||||
battle?.end()
|
||||
|
||||
+4
@@ -43,6 +43,10 @@ class FindAirTaskConfig : SingleTaskConfig {
|
||||
if (entity !is PathfinderMob) {
|
||||
return null
|
||||
}
|
||||
behaviourConfigurationContext.addMemories(
|
||||
MemoryModuleType.WALK_TARGET,
|
||||
CobblemonMemories.PATH_COOLDOWN
|
||||
)
|
||||
return BehaviorBuilder.create {
|
||||
it.group(
|
||||
it.absent(MemoryModuleType.WALK_TARGET),
|
||||
|
||||
+66
-22
@@ -16,6 +16,7 @@ import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMostSpecificMoLangV
|
||||
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
|
||||
@@ -24,8 +25,58 @@ import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
import net.minecraft.world.entity.ai.behavior.declarative.BehaviorBuilder
|
||||
import net.minecraft.world.entity.ai.behavior.declarative.Trigger
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
import net.minecraft.world.entity.ai.memory.NearestVisibleLivingEntities
|
||||
import net.minecraft.world.entity.ai.sensing.SensorType
|
||||
|
||||
class FindHerdLeaderTaskConfig : SingleTaskConfig {
|
||||
companion object {
|
||||
/**
|
||||
* Logic used to choose the best herd leader from nearby visible entities.
|
||||
*
|
||||
* - Higher tier leaders are always preferred.
|
||||
* - Same-tier leaders that are closer are preferred except for when they're the same tier as the current leader.
|
||||
* - We don't want to exceed the target's herd size limit.
|
||||
* - We don't want to choose a leader that is themselves following a leader.
|
||||
* - Some leader definitions allow lower-level Pokémon to lead them.
|
||||
* - Leaders just have to not be in a party - pastured and wild Pokémon can mingle.
|
||||
*/
|
||||
fun getBestHerdLeader(
|
||||
currentLeader: Pair<PokemonEntity, ToleratedHerdLeader>?,
|
||||
nearbyEntities: NearestVisibleLivingEntities,
|
||||
entity: PokemonEntity
|
||||
): PokemonEntity? {
|
||||
var bestLeader: PokemonEntity? = null
|
||||
val (currentLeaderEntity, currentLeaderDefinition) = currentLeader ?: Pair(null, null)
|
||||
var bestTier = currentLeaderDefinition?.tier?.let { it + 1 } ?: 0 // Only upgrade to a higher tier leader
|
||||
var bestDistance = Float.MAX_VALUE
|
||||
nearbyEntities.findAll {
|
||||
it is PokemonEntity &&
|
||||
it != currentLeader &&
|
||||
it.pokemon.storeCoordinates.get()?.store !is PartyStore &&
|
||||
it.getHerdSize() < it.behaviour.herd.maxSize
|
||||
}.forEach { possibleLeader ->
|
||||
possibleLeader as PokemonEntity
|
||||
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 (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 && !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 = matchingHerdLeader.tier
|
||||
}
|
||||
}
|
||||
return bestLeader ?: currentLeaderEntity
|
||||
}
|
||||
}
|
||||
|
||||
// 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())
|
||||
|
||||
@@ -41,40 +92,33 @@ class FindHerdLeaderTaskConfig : SingleTaskConfig {
|
||||
return null
|
||||
}
|
||||
|
||||
behaviourConfigurationContext.addMemories(
|
||||
MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES,
|
||||
CobblemonMemories.HERD_LEADER,
|
||||
MemoryModuleType.WALK_TARGET
|
||||
)
|
||||
behaviourConfigurationContext.addSensors(SensorType.NEAREST_LIVING_ENTITIES)
|
||||
runtime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
val checkTicksValue = checkTicks.resolveInt()
|
||||
return BehaviorBuilder.create { instance ->
|
||||
instance.group(
|
||||
instance.present(MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES),
|
||||
instance.absent(CobblemonMemories.HERD_LEADER),
|
||||
instance.absent(MemoryModuleType.WALK_TARGET)
|
||||
).apply(instance) { nearbyEntities, herdLeader, _ ->
|
||||
instance.absent(CobblemonMemories.HERD_LEADER)
|
||||
).apply(instance) { nearbyEntities, herdLeader ->
|
||||
Trigger { world, entity, _ ->
|
||||
if (world.gameTime % checkTicksValue != 0L) {
|
||||
return@Trigger false
|
||||
}
|
||||
|
||||
entity as PokemonEntity
|
||||
val toleratedLeaders = entity.behaviour.herd.toleratedLeaders
|
||||
val nearbyLeaders = instance.get(nearbyEntities).findAll {
|
||||
it is PokemonEntity &&
|
||||
it.pokemon.storeCoordinates.get()?.store !is PartyStore &&
|
||||
it.exposedSpecies.resourceIdentifier in toleratedLeaders &&
|
||||
!it.brain.hasMemoryValue(CobblemonMemories.HERD_LEADER) &&
|
||||
it.pokemon.level >= entity.pokemon.level
|
||||
}.toList()
|
||||
val bestLeader = getBestHerdLeader(
|
||||
currentLeader = null,
|
||||
nearbyEntities = instance.get(nearbyEntities),
|
||||
entity = entity
|
||||
) ?: return@Trigger false
|
||||
|
||||
if (nearbyLeaders.isEmpty()) {
|
||||
return@Trigger false
|
||||
}
|
||||
|
||||
val leader = nearbyLeaders
|
||||
.filterIsInstance<PokemonEntity>()
|
||||
.filter { it.getHerdSize() < entity.behaviour.herd.maxSize }
|
||||
.maxByOrNull { it.pokemon.level }
|
||||
?: return@Trigger false
|
||||
|
||||
herdLeader.set(leader.uuid.toString())
|
||||
herdLeader.set(bestLeader.uuid.toString())
|
||||
bestLeader.brain.eraseMemory(CobblemonMemories.HERD_LEADER)
|
||||
return@Trigger true
|
||||
}
|
||||
}
|
||||
|
||||
+10
@@ -8,6 +8,8 @@
|
||||
|
||||
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
|
||||
@@ -18,6 +20,7 @@ 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 FindRestingPlaceTaskConfig : SingleTaskConfig {
|
||||
val horizontalSearchDistance: ExpressionOrEntityVariable = Either.left("16".asExpression())
|
||||
@@ -28,6 +31,13 @@ class FindRestingPlaceTaskConfig : SingleTaskConfig {
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
behaviourConfigurationContext.addMemories(
|
||||
CobblemonMemories.PATH_COOLDOWN,
|
||||
CobblemonMemories.POKEMON_DROWSY,
|
||||
MemoryModuleType.WALK_TARGET
|
||||
)
|
||||
behaviourConfigurationContext.addSensors(CobblemonSensors.POKEMON_DROWSY)
|
||||
|
||||
return WrapperLivingEntityTask(
|
||||
FindRestingPlaceTask.create(horizontalSearchDistance.resolveInt(), verticalSearchDistance.resolveInt()),
|
||||
PokemonEntity::class.java
|
||||
|
||||
+5
@@ -20,6 +20,7 @@ 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 {
|
||||
var condition = booleanVariable(SharedEntityVariables.FEAR_CATEGORY, "flee_attacker", true).asExpressible()
|
||||
@@ -38,6 +39,10 @@ class FleeAttackerTaskConfig : SingleTaskConfig {
|
||||
): 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)
|
||||
|
||||
val speedMultiplier = speedMultiplier.resolveFloat()
|
||||
val desiredDistance = desiredDistance.resolveInt()
|
||||
return WrapperLivingEntityTask(
|
||||
|
||||
+3
@@ -20,6 +20,7 @@ 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 FleeNearestHostileTaskConfig : SingleTaskConfig {
|
||||
var condition = booleanVariable(SharedEntityVariables.FEAR_CATEGORY, "flee_nearest_hostile", true).asExpressible()
|
||||
@@ -34,6 +35,8 @@ class FleeNearestHostileTaskConfig : SingleTaskConfig {
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
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()
|
||||
val desiredDistance = desiredDistance.resolveInt()
|
||||
return WrapperLivingEntityTask(
|
||||
|
||||
+3
-1
@@ -23,6 +23,7 @@ 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
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
|
||||
class FlyInCirclesTaskConfig : SingleTaskConfig {
|
||||
val poseTypes: Set<PoseType> = setOf(
|
||||
@@ -31,7 +32,7 @@ class FlyInCirclesTaskConfig : SingleTaskConfig {
|
||||
)
|
||||
|
||||
val minAngularVelocityDegrees = numberVariable(WANDER, "min_fly_circling_angular_velocity", 0.0).asExpressible()
|
||||
val maxAngularVelocityDegrees = numberVariable(WANDER, "max_fly_circling_angular_velocity", 2.0).asExpressible()
|
||||
val maxAngularVelocityDegrees = numberVariable(WANDER, "max_fly_circling_angular_velocity", 1.0).asExpressible()
|
||||
val speed = numberVariable(WANDER, "fly_circling_speed", 0.6).asExpressible()
|
||||
val verticalSpeed: ExpressionOrEntityVariable = Either.left("0.0".asExpression())
|
||||
val minDurationTicks: ExpressionOrEntityVariable = Either.left("60".asExpression())
|
||||
@@ -55,6 +56,7 @@ class FlyInCirclesTaskConfig : SingleTaskConfig {
|
||||
if (entity !is PokemonEntity) {
|
||||
return null
|
||||
}
|
||||
behaviourConfigurationContext.addMemories(MemoryModuleType.WALK_TARGET, MemoryModuleType.PATH)
|
||||
runtime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
return CircleAroundTask(
|
||||
poseTypes = poseTypes,
|
||||
|
||||
+8
-1
@@ -8,6 +8,7 @@
|
||||
|
||||
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
|
||||
@@ -15,16 +16,22 @@ import com.cobblemon.mod.common.entity.ai.FollowHerdLeaderTask
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
|
||||
class FollowHerdLeaderTaskConfig : SingleTaskConfig {
|
||||
override fun getVariables(entity: LivingEntity): List<MoLangConfigVariable> {
|
||||
return listOf() // TODO add tooFar and closeEnough variables
|
||||
return listOf()
|
||||
}
|
||||
|
||||
override fun createTask(
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
if (entity !is PokemonEntity) {
|
||||
return null
|
||||
}
|
||||
|
||||
behaviourConfigurationContext.addMemories(CobblemonMemories.HERD_LEADER, MemoryModuleType.WALK_TARGET)
|
||||
return FollowHerdLeaderTask().wrapped<PokemonEntity>()
|
||||
}
|
||||
}
|
||||
+2
@@ -20,6 +20,7 @@ import com.mojang.datafixers.util.Either
|
||||
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.memory.MemoryModuleType
|
||||
|
||||
class FollowWalkTargetTaskConfig : SingleTaskConfig {
|
||||
val condition: ExpressionOrEntityVariable = Either.left("true".asExpression())
|
||||
@@ -30,6 +31,7 @@ class FollowWalkTargetTaskConfig : SingleTaskConfig {
|
||||
|
||||
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(), maxRunTicks.resolveInt()),
|
||||
PathfinderMob::class.java
|
||||
|
||||
+7
@@ -16,6 +16,8 @@ import com.cobblemon.mod.common.entity.ai.GetAngryAtAttackerTask
|
||||
import com.cobblemon.mod.common.util.withQueryValue
|
||||
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
|
||||
|
||||
class GetAngryAtAttackerTaskConfig : SingleTaskConfig {
|
||||
companion object {
|
||||
@@ -32,6 +34,11 @@ class GetAngryAtAttackerTaskConfig : SingleTaskConfig {
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
runtime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
if (!condition.resolveBoolean()) return null
|
||||
behaviourConfigurationContext.addMemories(
|
||||
MemoryModuleType.HURT_BY_ENTITY,
|
||||
MemoryModuleType.ANGRY_AT,
|
||||
)
|
||||
behaviourConfigurationContext.addSensors(SensorType.HURT_BY)
|
||||
return GetAngryAtAttackerTask.create()
|
||||
}
|
||||
}
|
||||
+10
-1
@@ -8,6 +8,8 @@
|
||||
|
||||
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.asVariables
|
||||
@@ -18,6 +20,8 @@ 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
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
import net.minecraft.world.entity.ai.sensing.SensorType
|
||||
|
||||
class GoToHealingMachineTaskConfig : SingleTaskConfig {
|
||||
val condition = booleanVariable(SELF_HEALING, USE_HEALING_MACHINES, true).asExpressible()
|
||||
@@ -39,7 +43,12 @@ class GoToHealingMachineTaskConfig : SingleTaskConfig {
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
runtime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
if (!condition.resolveBoolean()) return null
|
||||
|
||||
behaviourConfigurationContext.addMemories(
|
||||
MemoryModuleType.WALK_TARGET,
|
||||
MemoryModuleType.LOOK_TARGET,
|
||||
CobblemonMemories.NPC_BATTLING
|
||||
)
|
||||
behaviourConfigurationContext.addSensors(CobblemonSensors.NPC_BATTLING)
|
||||
return GoToHealingMachineTask.create(
|
||||
horizontalSearchRange = horizontalSearchRange.asExpression(),
|
||||
verticalSearchRange = verticalSearchRange.asExpression(),
|
||||
|
||||
+9
-3
@@ -12,6 +12,7 @@ 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.npc.configuration.MoLangConfigVariable
|
||||
import com.cobblemon.mod.common.entity.OmniPathingEntity
|
||||
import com.cobblemon.mod.common.util.closestPosition
|
||||
import kotlin.math.ceil
|
||||
import kotlin.math.floor
|
||||
@@ -43,7 +44,10 @@ class GoToLandTaskConfig : SingleTaskConfig {
|
||||
if (entity !is PathfinderMob) {
|
||||
return null
|
||||
}
|
||||
|
||||
behaviourConfigurationContext.addMemories(
|
||||
MemoryModuleType.WALK_TARGET,
|
||||
CobblemonMemories.PATH_COOLDOWN
|
||||
)
|
||||
return BehaviorBuilder.create {
|
||||
it.group(
|
||||
it.absent(MemoryModuleType.WALK_TARGET),
|
||||
@@ -56,6 +60,8 @@ class GoToLandTaskConfig : SingleTaskConfig {
|
||||
|
||||
entity as PathfinderMob
|
||||
|
||||
val walkSpeedValue = walkSpeed.resolveFloat()
|
||||
|
||||
val iterable = BlockPos.betweenClosed(
|
||||
Mth.floor(entity.x - 8.0),
|
||||
entity.blockY,
|
||||
@@ -71,7 +77,7 @@ class GoToLandTaskConfig : SingleTaskConfig {
|
||||
isSafeLandPosAround(entity.level() as ServerLevel, it, entity)
|
||||
} ?: return@Trigger false
|
||||
|
||||
walkTarget.set(WalkTarget(blockPos.above(), 0.35F, 1))
|
||||
walkTarget.set(WalkTarget(blockPos.above(), walkSpeedValue, 0))
|
||||
return@Trigger true
|
||||
}
|
||||
}
|
||||
@@ -82,7 +88,7 @@ class GoToLandTaskConfig : SingleTaskConfig {
|
||||
val blockState = world.getBlockState(pos)
|
||||
|
||||
val isFluid = world.getFluidState(pos.above()).isEmpty.not()
|
||||
val solidBelow = blockState.isSolid
|
||||
val solidBelow = blockState.isSolid || (mob is OmniPathingEntity && mob.canFly())
|
||||
|
||||
if (isFluid || !solidBelow) {
|
||||
return false
|
||||
|
||||
+12
@@ -8,6 +8,8 @@
|
||||
|
||||
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.WrapperLivingEntityTask
|
||||
import com.cobblemon.mod.common.api.npc.configuration.MoLangConfigVariable
|
||||
@@ -15,6 +17,7 @@ import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.entity.pokemon.ai.tasks.GoToSleepTask
|
||||
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 {
|
||||
override fun getVariables(entity: LivingEntity) = emptyList<MoLangConfigVariable>()
|
||||
@@ -22,6 +25,15 @@ class GoToSleepTaskConfig : SingleTaskConfig {
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
if (entity !is PokemonEntity) {
|
||||
return null
|
||||
}
|
||||
behaviourConfigurationContext.addMemories(
|
||||
MemoryModuleType.WALK_TARGET,
|
||||
CobblemonMemories.POKEMON_DROWSY,
|
||||
CobblemonMemories.POKEMON_SLEEPING
|
||||
)
|
||||
behaviourConfigurationContext.addSensors(CobblemonSensors.POKEMON_DROWSY)
|
||||
return WrapperLivingEntityTask(GoToSleepTask.create(), PokemonEntity::class.java)
|
||||
}
|
||||
}
|
||||
+67
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* 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.bedrockk.molang.Expression
|
||||
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.api.npc.configuration.MoLangConfigVariable
|
||||
import com.cobblemon.mod.common.util.asExpression
|
||||
import com.cobblemon.mod.common.util.resolveBoolean
|
||||
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
|
||||
import net.minecraft.world.entity.ai.behavior.declarative.BehaviorBuilder
|
||||
import net.minecraft.world.entity.ai.behavior.declarative.Trigger
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
import net.minecraft.world.entity.ai.sensing.SensorType
|
||||
|
||||
/**
|
||||
* Immediately gets angry at the nearest visible entity that matches the [entityCondition] and is within the [range].
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since June 23rd, 2025
|
||||
*/
|
||||
class HateEntityTaskConfig : SingleTaskConfig {
|
||||
val entityCondition: Expression = "true".asExpression()
|
||||
val range: ExpressionOrEntityVariable = Either.left("24".asExpression())
|
||||
|
||||
override fun getVariables(entity: LivingEntity) = emptyList<MoLangConfigVariable>()
|
||||
override fun createTask(
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
val range = range.resolveFloat()
|
||||
behaviourConfigurationContext.addMemories(
|
||||
MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES,
|
||||
MemoryModuleType.ANGRY_AT
|
||||
)
|
||||
behaviourConfigurationContext.addSensors(SensorType.NEAREST_LIVING_ENTITIES)
|
||||
return BehaviorBuilder.create { instance ->
|
||||
instance.group(
|
||||
instance.present(MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES),
|
||||
instance.registered(MemoryModuleType.ANGRY_AT)
|
||||
).apply(instance) { entities, angryAt ->
|
||||
Trigger { world, entity, _ ->
|
||||
val target = instance.get(entities).findClosest {
|
||||
runtime.withQueryValue("entity", it.asMostSpecificMoLangValue())
|
||||
return@findClosest runtime.resolveBoolean(entityCondition)
|
||||
}.orElse(null)
|
||||
|
||||
if (target != null && target.distanceTo(entity) <= range) {
|
||||
angryAt.set(target.uuid)
|
||||
}
|
||||
return@Trigger true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+5
@@ -8,6 +8,8 @@
|
||||
|
||||
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.asVariables
|
||||
@@ -20,6 +22,7 @@ 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
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
|
||||
class HealUsingHealingMachineTaskConfig : SingleTaskConfig {
|
||||
val condition = booleanVariable(SELF_HEALING, USE_HEALING_MACHINES, true).asExpressible()
|
||||
@@ -34,6 +37,8 @@ class HealUsingHealingMachineTaskConfig : SingleTaskConfig {
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
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())
|
||||
}
|
||||
}
|
||||
+8
@@ -8,6 +8,8 @@
|
||||
|
||||
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.asVariables
|
||||
@@ -18,6 +20,7 @@ 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
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
|
||||
class LookAtBattlingPokemonTaskConfig : SingleTaskConfig {
|
||||
companion object {
|
||||
@@ -40,6 +43,11 @@ class LookAtBattlingPokemonTaskConfig : SingleTaskConfig {
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
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(),
|
||||
maxDurationTicks = maxDurationTicks.resolveInt()
|
||||
|
||||
+4
@@ -16,6 +16,8 @@ import com.cobblemon.mod.common.util.withQueryValue
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
import net.minecraft.world.entity.ai.behavior.SetEntityLookTarget
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
import net.minecraft.world.entity.ai.sensing.SensorType
|
||||
|
||||
class LookAtEntitiesTaskConfig : SingleTaskConfig {
|
||||
companion object {
|
||||
@@ -36,6 +38,8 @@ class LookAtEntitiesTaskConfig : SingleTaskConfig {
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
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())
|
||||
}
|
||||
}
|
||||
+5
-1
@@ -8,15 +8,19 @@
|
||||
|
||||
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.npc.configuration.MoLangConfigVariable
|
||||
import com.cobblemon.mod.common.entity.npc.ai.LookAtSpeakerTask
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
|
||||
class LookAtSpeakerTaskConfig : SingleTaskConfig {
|
||||
override fun getVariables(entity: LivingEntity) = emptyList<MoLangConfigVariable>()
|
||||
override fun createTask(
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
) = LookAtSpeakerTask.create()
|
||||
) = LookAtSpeakerTask.create().also {
|
||||
behaviourConfigurationContext.addMemories(MemoryModuleType.LOOK_TARGET, CobblemonMemories.DIALOGUES)
|
||||
}
|
||||
}
|
||||
+2
@@ -20,6 +20,7 @@ import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.Mob
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
import net.minecraft.world.entity.ai.behavior.LookAtTargetSink
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
|
||||
class LookAtTargetTaskConfig : SingleTaskConfig {
|
||||
val condition: ExpressionOrEntityVariable = Either.left("true".asExpression())
|
||||
@@ -38,6 +39,7 @@ class LookAtTargetTaskConfig : SingleTaskConfig {
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
runtime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
if (!condition.resolveBoolean()) return null
|
||||
behaviourConfigurationContext.addMemories(MemoryModuleType.LOOK_TARGET)
|
||||
return WrapperLivingEntityTask(LookAtTargetSink(minDurationTicks.resolveInt(), maxDurationTicks.resolveInt()), Mob::class.java)
|
||||
}
|
||||
}
|
||||
+11
-1
@@ -8,6 +8,7 @@
|
||||
|
||||
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
|
||||
import com.cobblemon.mod.common.api.npc.configuration.MoLangConfigVariable
|
||||
@@ -15,13 +16,22 @@ import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.entity.pokemon.ai.tasks.LookAtTargetedBattlePokemonTask
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
|
||||
class LookAtTargetedBattlePokemonTaskConfig : SingleTaskConfig {
|
||||
override fun getVariables(entity: LivingEntity) = emptyList<MoLangConfigVariable>()
|
||||
override fun createTask(
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
): BehaviorControl<in LivingEntity> {
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
if (entity !is PokemonEntity) {
|
||||
return null
|
||||
}
|
||||
behaviourConfigurationContext.addMemories(
|
||||
CobblemonMemories.POKEMON_BATTLE,
|
||||
CobblemonMemories.TARGETED_BATTLE_POKEMON,
|
||||
MemoryModuleType.LOOK_TARGET,
|
||||
)
|
||||
return WrapperLivingEntityTask(LookAtTargetedBattlePokemonTask.create(), PokemonEntity::class.java)
|
||||
}
|
||||
}
|
||||
+4
-1
@@ -13,6 +13,7 @@ import com.cobblemon.mod.common.api.ai.asVariables
|
||||
import com.cobblemon.mod.common.api.ai.config.task.SharedEntityVariables.LOOKING_CATEGORY
|
||||
import com.cobblemon.mod.common.entity.ai.LookInDirectionTask
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
|
||||
class LookInDirectionTaskConfig : SingleTaskConfig {
|
||||
var condition = booleanVariable(LOOKING_CATEGORY, "locked_rotation", true).asExpressible()
|
||||
@@ -32,5 +33,7 @@ class LookInDirectionTaskConfig : SingleTaskConfig {
|
||||
shouldLock = condition.asExpression(),
|
||||
yaw = yaw.asExpression(),
|
||||
pitch = pitch.asExpression()
|
||||
)
|
||||
).also {
|
||||
behaviourConfigurationContext.addMemories(MemoryModuleType.LOOK_TARGET)
|
||||
}
|
||||
}
|
||||
+19
-19
@@ -14,7 +14,6 @@ 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.util.asExpression
|
||||
import com.cobblemon.mod.common.util.withQueryValue
|
||||
@@ -25,6 +24,7 @@ import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
import net.minecraft.world.entity.ai.behavior.declarative.BehaviorBuilder
|
||||
import net.minecraft.world.entity.ai.behavior.declarative.Trigger
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
import net.minecraft.world.entity.ai.sensing.SensorType
|
||||
|
||||
/**
|
||||
* Task that looks around for a better herd leader or gives up on a leader
|
||||
@@ -48,6 +48,11 @@ class MaintainHerdLeaderTaskConfig : SingleTaskConfig {
|
||||
if (entity !is PokemonEntity) {
|
||||
return null
|
||||
}
|
||||
behaviourConfigurationContext.addMemories(
|
||||
CobblemonMemories.HERD_LEADER,
|
||||
MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES,
|
||||
)
|
||||
behaviourConfigurationContext.addSensors(SensorType.NEAREST_LIVING_ENTITIES)
|
||||
runtime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
val checkTicks = checkTicks.resolveInt()
|
||||
return BehaviorBuilder.create { instance ->
|
||||
@@ -62,26 +67,22 @@ class MaintainHerdLeaderTaskConfig : SingleTaskConfig {
|
||||
}
|
||||
|
||||
val leader = instance.get(herdLeader).let(UUID::fromString).let(world::getEntity) as? PokemonEntity
|
||||
if (leader == null) {
|
||||
val currentLeaderDefinition = leader?.let { leader ->
|
||||
entity.behaviour.herd.toleratedLeaders.find { it.pokemon.matches(leader) }
|
||||
}
|
||||
if (leader == null || currentLeaderDefinition == null) {
|
||||
entity.brain.eraseMemory(CobblemonMemories.HERD_LEADER)
|
||||
return@Trigger true // No leader, so we erase the memory
|
||||
} else if (leader.brain.hasMemoryValue(CobblemonMemories.HERD_LEADER)) {
|
||||
entity.brain.eraseMemory(CobblemonMemories.HERD_LEADER)
|
||||
return@Trigger true
|
||||
} else if (leader.exposedSpecies.resourceIdentifier !in entity.behaviour.herd.toleratedLeaders) {
|
||||
// Zoroark getting exposed then herd members pausing and saying "hey wait a minute"
|
||||
entity.brain.eraseMemory(CobblemonMemories.HERD_LEADER)
|
||||
} else {
|
||||
val bestSurroundingLeader = instance.get(nearbyEntities).findAll {
|
||||
it is PokemonEntity &&
|
||||
it != leader &&
|
||||
it.pokemon.storeCoordinates.get()?.store !is PartyStore &&
|
||||
it.exposedSpecies.resourceIdentifier in entity.behaviour.herd.toleratedLeaders &&
|
||||
!it.brain.hasMemoryValue(CobblemonMemories.HERD_LEADER) &&
|
||||
it.pokemon.level > leader.pokemon.level // Has to be a superior leader to the existing one
|
||||
}.maxByOrNull { (it as PokemonEntity).pokemon.level } as? PokemonEntity
|
||||
if (bestSurroundingLeader != null) {
|
||||
entity.brain.setMemory(CobblemonMemories.HERD_LEADER, bestSurroundingLeader.uuid.toString())
|
||||
val bestLeader = FindHerdLeaderTaskConfig.getBestHerdLeader(
|
||||
currentLeader = (leader to currentLeaderDefinition),
|
||||
nearbyEntities = instance.get(nearbyEntities),
|
||||
entity = entity
|
||||
)
|
||||
|
||||
if (bestLeader != null && bestLeader != leader) {
|
||||
bestLeader.brain.eraseMemory(CobblemonMemories.HERD_LEADER)
|
||||
entity.brain.setMemory(CobblemonMemories.HERD_LEADER, bestLeader.uuid.toString())
|
||||
}
|
||||
}
|
||||
return@Trigger true
|
||||
@@ -89,5 +90,4 @@ class MaintainHerdLeaderTaskConfig : SingleTaskConfig {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+5
-10
@@ -8,22 +8,16 @@
|
||||
|
||||
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
|
||||
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.npc.ai.MeleeAttackTask
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.entity.pokemon.ai.tasks.BattleFlightTask
|
||||
import com.cobblemon.mod.common.util.withQueryValue
|
||||
import com.cobblemon.mod.common.entity.pokemon.ai.tasks.ManageFlightInBattleTask
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
|
||||
class BattleFlightTaskConfig : SingleTaskConfig {
|
||||
|
||||
class ManageFlightInBattleTaskConfig : SingleTaskConfig {
|
||||
override fun getVariables(entity: LivingEntity) = emptyList<MoLangConfigVariable>()
|
||||
|
||||
override fun createTask(
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
@@ -31,6 +25,7 @@ class BattleFlightTaskConfig : SingleTaskConfig {
|
||||
if (entity !is PokemonEntity) {
|
||||
return null
|
||||
}
|
||||
return BattleFlightTask.create()
|
||||
behaviourConfigurationContext.addMemories(CobblemonMemories.POKEMON_BATTLE)
|
||||
return ManageFlightInBattleTask.create()
|
||||
}
|
||||
}
|
||||
+6
-2
@@ -15,11 +15,12 @@ import com.cobblemon.mod.common.entity.npc.ai.MeleeAttackTask
|
||||
import com.cobblemon.mod.common.util.withQueryValue
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
|
||||
class MeleeAttackTaskConfig : SingleTaskConfig {
|
||||
val condition = booleanVariable(SharedEntityVariables.ATTACKING_CATEGORY, "attacks_melee", true).asExpressible()
|
||||
val range = numberVariable(SharedEntityVariables.ATTACKING_CATEGORY, "melee_range", 1.5F).asExpressible()
|
||||
val cooldownTicks = numberVariable(SharedEntityVariables.ATTACKING_CATEGORY, "melee_cooldown", 30).asExpressible()
|
||||
val cooldownTicks = numberVariable(SharedEntityVariables.ATTACKING_CATEGORY, "melee_cooldown", 20).asExpressible()
|
||||
|
||||
override fun getVariables(entity: LivingEntity) = listOf(
|
||||
condition,
|
||||
@@ -33,7 +34,10 @@ class MeleeAttackTaskConfig : SingleTaskConfig {
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
runtime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
if (!condition.resolveBoolean()) return null
|
||||
|
||||
behaviourConfigurationContext.addMemories(
|
||||
MemoryModuleType.ATTACK_TARGET,
|
||||
MemoryModuleType.ATTACK_COOLING_DOWN
|
||||
)
|
||||
return MeleeAttackTask.create(
|
||||
range = range.asExpression(),
|
||||
cooldownTicks = cooldownTicks.asExpression()
|
||||
|
||||
+4
@@ -63,6 +63,10 @@ class MoveIntoFluidTaskConfig : SingleTaskConfig {
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
runtime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
if (!condition.resolveBoolean()) return null
|
||||
behaviourConfigurationContext.addMemories(
|
||||
MemoryModuleType.WALK_TARGET,
|
||||
CobblemonMemories.PATH_COOLDOWN
|
||||
)
|
||||
val movesIntoWater = this@MoveIntoFluidTaskConfig.movesIntoWater.resolveBoolean()
|
||||
val movesIntoLava = movesIntoLava.resolveBoolean()
|
||||
val speedModifier = speedModifier.resolveFloat()
|
||||
|
||||
+8
-2
@@ -15,10 +15,11 @@ import com.cobblemon.mod.common.entity.ai.MoveToAttackTargetTask
|
||||
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.memory.MemoryModuleType
|
||||
|
||||
class MoveToAttackTargetTaskConfig : SingleTaskConfig {
|
||||
val speedMultiplier = numberVariable(SharedEntityVariables.ATTACKING_CATEGORY, "attacking_movement_speed", 0.5).asExpressible()
|
||||
val closeEnoughDistance: ExpressionOrEntityVariable = Either.left("1".asExpression())
|
||||
val closeEnoughDistance: ExpressionOrEntityVariable = Either.left("0".asExpression())
|
||||
|
||||
override fun getVariables(entity: LivingEntity) = listOf(
|
||||
speedMultiplier,
|
||||
@@ -31,5 +32,10 @@ class MoveToAttackTargetTaskConfig : SingleTaskConfig {
|
||||
) = MoveToAttackTargetTask.create(
|
||||
speedMultiplier = speedMultiplier.asExpression(),
|
||||
closeEnoughDistance = closeEnoughDistance.asExpression()
|
||||
)
|
||||
).also {
|
||||
behaviourConfigurationContext.addMemories(
|
||||
MemoryModuleType.ATTACK_TARGET,
|
||||
MemoryModuleType.WALK_TARGET
|
||||
)
|
||||
}
|
||||
}
|
||||
+5
@@ -18,6 +18,7 @@ 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 MoveToOwnerTaskConfig : SingleTaskConfig {
|
||||
val condition: ExpressionOrEntityVariable = Either.left("true".asExpression())
|
||||
@@ -38,6 +39,10 @@ class MoveToOwnerTaskConfig : SingleTaskConfig {
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
behaviourConfigurationContext.addMemories(
|
||||
MemoryModuleType.WALK_TARGET,
|
||||
MemoryModuleType.LOOK_TARGET
|
||||
)
|
||||
return WrapperLivingEntityTask(
|
||||
MoveToOwnerTask.create(
|
||||
condition = condition.asExpression(),
|
||||
|
||||
+5
-5
@@ -9,12 +9,12 @@
|
||||
package com.cobblemon.mod.common.api.ai.config.task
|
||||
|
||||
import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
|
||||
import com.cobblemon.mod.common.api.molang.ExpressionLike
|
||||
import com.cobblemon.mod.common.api.ai.ExpressionOrEntityVariable
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMostSpecificMoLangValue
|
||||
import com.cobblemon.mod.common.util.asExpressionLike
|
||||
import com.cobblemon.mod.common.util.resolveBoolean
|
||||
import com.cobblemon.mod.common.util.asExpression
|
||||
import com.cobblemon.mod.common.util.toDF
|
||||
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
|
||||
import net.minecraft.world.entity.ai.behavior.RunOne
|
||||
@@ -35,14 +35,14 @@ class OneOfTaskConfig : SingleTaskConfig {
|
||||
val task: TaskConfig = SingleTaskConfig.nothing()
|
||||
}
|
||||
|
||||
val condition: ExpressionLike = "true".asExpressionLike()
|
||||
val condition: ExpressionOrEntityVariable = Either.left("true".asExpression())
|
||||
val options = mutableListOf<OneOfTaskOption>()
|
||||
|
||||
override fun getVariables(entity: LivingEntity) = options.flatMap { it.task.getVariables(entity) }
|
||||
|
||||
override fun createTask(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext): BehaviorControl<in LivingEntity>? {
|
||||
runtime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
if (!runtime.resolveBoolean(condition)) return null
|
||||
if (!condition.resolveBoolean()) return null
|
||||
return RunOne(options.map { it.task.createTasks(entity, behaviourConfigurationContext).first() toDF it.weight })
|
||||
}
|
||||
}
|
||||
+1
@@ -22,6 +22,7 @@ import net.minecraft.world.phys.Vec3
|
||||
class PointToSpawnTaskConfig : SingleTaskConfig {
|
||||
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 {
|
||||
it.group(
|
||||
it.registered(MemoryModuleType.LOOK_TARGET),
|
||||
|
||||
@@ -188,7 +188,7 @@ The 'look_in_direction' type creates a task that will make the entity look in a
|
||||
### move_to_owner
|
||||
The 'move_to_owner' type creates a task that will make the entity move to its owner. This will only work for entities that
|
||||
can be owned, like Pokémon.
|
||||
- `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.
|
||||
- `condition`: A MoLang expression (with `q.entity` as the entity) that determines if the entity should move to its owner this tick. Defaults to true.
|
||||
- `completionRange`: A MoLang expression that determines the distance from the owner that the entity needs to be for the path to be considered complete. Defaults to 4.
|
||||
- `speedMultiplier`: A MoLang expression that determines the speed multiplier for moving to the owner. Defaults to 0.4 which is slightly above the normal walk speed.
|
||||
- `teleportDistance`: A MoLang expression that determines the distance from the owner the entity must be before it resorts to teleporting. A value of -1 will cause it to never teleport. Defaults to 24.
|
||||
|
||||
+7
-4
@@ -9,12 +9,16 @@
|
||||
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.ExpressionLike
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMostSpecificMoLangValue
|
||||
import com.cobblemon.mod.common.util.asExpression
|
||||
import com.cobblemon.mod.common.util.asExpressionLike
|
||||
import com.cobblemon.mod.common.util.resolveBoolean
|
||||
import com.cobblemon.mod.common.util.weightedSelection
|
||||
import com.cobblemon.mod.common.util.withQueryValue
|
||||
import com.mojang.datafixers.util.Either
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
|
||||
@@ -35,17 +39,16 @@ class RandomTaskConfig : TaskConfig {
|
||||
val task: TaskConfig = SingleTaskConfig.nothing()
|
||||
}
|
||||
|
||||
val condition: ExpressionLike = "true".asExpressionLike()
|
||||
val condition: ExpressionOrEntityVariable = Either.left("true".asExpression())
|
||||
val choices = mutableListOf<RandomTaskChoice>()
|
||||
|
||||
override fun getVariables(entity: LivingEntity) = choices.flatMap { it.task.getVariables(entity) }
|
||||
|
||||
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>> {
|
||||
runtime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
if (!runtime.resolveBoolean(condition)) return emptyList()
|
||||
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)
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
import net.minecraft.world.entity.ai.behavior.declarative.BehaviorBuilder
|
||||
import net.minecraft.world.entity.ai.behavior.declarative.Trigger
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
import net.minecraft.world.entity.ai.sensing.SensorType
|
||||
|
||||
/**
|
||||
* Runs a registered MoLang script (from the molang datapack folder) each tick.
|
||||
@@ -38,6 +39,8 @@ class RunScript : SingleTaskConfig {
|
||||
|
||||
val script = stringVariable(SCRIPT_CATEGORY, "script", "cobblemon:dummy_script").asExpressible()
|
||||
val variables = mutableListOf<MoLangConfigVariable>()
|
||||
val memories = emptySet<MemoryModuleType<*>>()
|
||||
val sensors = emptySet<SensorType<*>>()
|
||||
|
||||
override fun getVariables(entity: LivingEntity) = listOf(script).asVariables() + variables
|
||||
|
||||
@@ -45,6 +48,8 @@ class RunScript : SingleTaskConfig {
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
): BehaviorControl<in LivingEntity>? = BehaviorBuilder.create {
|
||||
behaviourConfigurationContext.addMemories(memories + MemoryModuleType.LOOK_TARGET)
|
||||
behaviourConfigurationContext.addSensors(sensors)
|
||||
it.group(
|
||||
it.registered(MemoryModuleType.LOOK_TARGET) // I think I need to have at least something here?
|
||||
).apply(it) { _ ->
|
||||
|
||||
+4
@@ -25,6 +25,10 @@ class SleepIfOnTrainerBedTaskConfig : SingleTaskConfig {
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
): BehaviorControl<in LivingEntity> {
|
||||
behaviourConfigurationContext.addMemories(
|
||||
MemoryModuleType.WALK_TARGET,
|
||||
CobblemonMemories.POKEMON_SLEEPING
|
||||
)
|
||||
return BehaviorBuilder.create {
|
||||
it.group(
|
||||
it.registered(MemoryModuleType.WALK_TARGET),
|
||||
|
||||
+3
-5
@@ -8,6 +8,7 @@
|
||||
|
||||
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
|
||||
import com.cobblemon.mod.common.api.ai.asVariables
|
||||
@@ -22,14 +23,11 @@ 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) = listOf(
|
||||
condition,
|
||||
chance
|
||||
).asVariables()
|
||||
|
||||
override fun getVariables(entity: LivingEntity) = listOf(condition, chance).asVariables()
|
||||
override fun createTask(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext): BehaviorControl<LivingEntity>? {
|
||||
runtime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
if (!condition.resolveBoolean()) return null
|
||||
behaviourConfigurationContext.addMemories(CobblemonMemories.POKEMON_BATTLE)
|
||||
return WrapperLivingEntityTask(
|
||||
StayAfloatTask(chance.resolveFloat()),
|
||||
PathfinderMob::class.java
|
||||
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* 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.bedrockk.molang.runtime.MoLangRuntime
|
||||
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.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.resolveBoolean
|
||||
import com.cobblemon.mod.common.util.withQueryValue
|
||||
import java.util.function.Predicate
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.Mob
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
import net.minecraft.world.entity.ai.behavior.StopAttackingIfTargetInvalid
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
|
||||
/**
|
||||
* A task config wrapping around vanilla's [StopAttackingIfTargetInvalid] that supports the optional ATTACK_TARGET_DATA
|
||||
* memory to determine if the target is still valid for attacking.
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since June 23rd, 2025
|
||||
*/
|
||||
class StopAttackingIfTargetInvalidTaskConfig : SingleTaskConfig {
|
||||
override fun getVariables(entity: LivingEntity) = emptyList<MoLangConfigVariable>()
|
||||
override fun createTask(
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
): 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
|
||||
runtime.withQueryValue("entity", target.asMostSpecificMoLangValue())
|
||||
return@Predicate !runtime.resolveBoolean(targetData.shouldContinue)
|
||||
}
|
||||
).wrapped()
|
||||
}
|
||||
}
|
||||
+2
-1
@@ -15,18 +15,19 @@ import com.cobblemon.mod.common.util.withQueryValue
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
import net.minecraft.world.entity.ai.behavior.StopBeingAngryIfTargetDead
|
||||
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) = listOf(condition).asVariables()
|
||||
|
||||
override fun createTask(
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
runtime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
if (!condition.resolveBoolean()) return null
|
||||
behaviourConfigurationContext.addMemories(MemoryModuleType.ANGRY_AT)
|
||||
return StopBeingAngryIfTargetDead.create()
|
||||
}
|
||||
}
|
||||
+2
@@ -29,5 +29,7 @@ class SwitchFromActionEffectTaskConfig : SingleTaskConfig {
|
||||
return@Trigger true
|
||||
}
|
||||
}
|
||||
}.also {
|
||||
behaviourConfigurationContext.addMemories(CobblemonMemories.ACTIVE_ACTION_EFFECT)
|
||||
}
|
||||
}
|
||||
+2
@@ -29,5 +29,7 @@ class SwitchFromChattingTaskConfig : SingleTaskConfig {
|
||||
return@Trigger true
|
||||
}
|
||||
}
|
||||
}.also {
|
||||
behaviourConfigurationContext.addMemories(CobblemonMemories.DIALOGUES)
|
||||
}
|
||||
}
|
||||
+4
@@ -8,6 +8,7 @@
|
||||
|
||||
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.npc.configuration.MoLangConfigVariable
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
@@ -25,9 +26,12 @@ class SwitchFromFightTaskConfig : SingleTaskConfig {
|
||||
it.absent(MemoryModuleType.ATTACK_TARGET)
|
||||
).apply(it) { _ ->
|
||||
Trigger { level, entity, _ ->
|
||||
entity.brain.eraseMemory(CobblemonMemories.ATTACK_TARGET_DATA)
|
||||
entity.brain.updateActivityFromSchedule(level.dayTime, level.gameTime)
|
||||
return@Trigger true
|
||||
}
|
||||
}
|
||||
}.also {
|
||||
behaviourConfigurationContext.addMemories(MemoryModuleType.ATTACK_TARGET)
|
||||
}
|
||||
}
|
||||
+1
@@ -22,6 +22,7 @@ class SwitchFromHerdTaskConfig : SingleTaskConfig {
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
behaviourConfigurationContext.addMemories(CobblemonMemories.HERD_LEADER)
|
||||
return BehaviorBuilder.create {
|
||||
it.group(
|
||||
it.absent(CobblemonMemories.HERD_LEADER)
|
||||
|
||||
+1
@@ -22,6 +22,7 @@ class SwitchFromNPCBattleTaskConfig : SingleTaskConfig {
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
behaviourConfigurationContext.addMemories(CobblemonMemories.NPC_BATTLING)
|
||||
return BehaviorBuilder.create {
|
||||
it.group(it.absent(CobblemonMemories.NPC_BATTLING)).apply(it) { _ ->
|
||||
Trigger { level, entity, _ ->
|
||||
|
||||
+1
@@ -22,6 +22,7 @@ class SwitchFromPokemonBattleTaskConfig : SingleTaskConfig {
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
behaviourConfigurationContext.addMemories(CobblemonMemories.POKEMON_BATTLE)
|
||||
return BehaviorBuilder.create {
|
||||
it.group(it.absent(CobblemonMemories.POKEMON_BATTLE)).apply(it) { _ ->
|
||||
Trigger { level, entity, _ ->
|
||||
|
||||
+1
@@ -29,6 +29,7 @@ class SwitchFromSleepOnTrainerBedTaskConfig : SingleTaskConfig {
|
||||
return null
|
||||
}
|
||||
|
||||
behaviourConfigurationContext.addMemories(CobblemonMemories.POKEMON_SLEEPING)
|
||||
return BehaviorBuilder.create {
|
||||
it.group(
|
||||
it.registered(CobblemonMemories.POKEMON_SLEEPING)
|
||||
|
||||
+1
@@ -23,6 +23,7 @@ class SwitchToActionEffectTaskConfig : SingleTaskConfig {
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
behaviourConfigurationContext.addMemories(CobblemonMemories.ACTIVE_ACTION_EFFECT)
|
||||
return BehaviorBuilder.create {
|
||||
it.group(
|
||||
it.absent(CobblemonMemories.ACTIVE_ACTION_EFFECT)
|
||||
|
||||
+3
-4
@@ -24,11 +24,10 @@ class SwitchToChattingTaskConfig : SingleTaskConfig {
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
) = BehaviorBuilder.create {
|
||||
it.group(
|
||||
it.present(CobblemonMemories.DIALOGUES),
|
||||
it.registered(MemoryModuleType.WALK_TARGET)
|
||||
).apply(it) { _, walkTarget ->
|
||||
it.present(CobblemonMemories.DIALOGUES)
|
||||
).apply(it) { _ ->
|
||||
Trigger { world, entity, _ ->
|
||||
walkTarget.erase()
|
||||
entity.brain.eraseMemory(MemoryModuleType.WALK_TARGET) // it may not even have this memory but clear it if it got it
|
||||
entity.brain.setActiveActivityIfPossible(CobblemonActivities.NPC_CHATTING)
|
||||
return@Trigger true
|
||||
}
|
||||
|
||||
+2
@@ -40,5 +40,7 @@ class SwitchToFightTaskConfig : SingleTaskConfig {
|
||||
return@Trigger true
|
||||
}
|
||||
}
|
||||
}.also {
|
||||
behaviourConfigurationContext.addMemories(MemoryModuleType.ATTACK_TARGET)
|
||||
}
|
||||
}
|
||||
+1
@@ -23,6 +23,7 @@ class SwitchToHerdTaskConfig : SingleTaskConfig {
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
behaviourConfigurationContext.addMemories(CobblemonMemories.HERD_LEADER)
|
||||
return BehaviorBuilder.create {
|
||||
it.group(
|
||||
it.present(CobblemonMemories.HERD_LEADER)
|
||||
|
||||
+7
-1
@@ -8,16 +8,22 @@
|
||||
|
||||
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.npc.ai.SwitchToBattleTask
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
|
||||
class SwitchToNPCBattleTaskConfig : SingleTaskConfig {
|
||||
override fun getVariables(entity: LivingEntity) = emptyList<MoLangConfigVariable>()
|
||||
override fun createTask(
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
): BehaviorControl<in LivingEntity> = SwitchToBattleTask.create()
|
||||
): BehaviorControl<in LivingEntity> = SwitchToBattleTask.create().also {
|
||||
behaviourConfigurationContext.addMemories(CobblemonMemories.NPC_BATTLING)
|
||||
behaviourConfigurationContext.addSensors(CobblemonSensors.NPC_BATTLING)
|
||||
}
|
||||
}
|
||||
+3
@@ -18,6 +18,7 @@ import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
import net.minecraft.world.entity.ai.behavior.declarative.BehaviorBuilder
|
||||
import net.minecraft.world.entity.ai.behavior.declarative.Trigger
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
import net.minecraft.world.entity.ai.sensing.SensorType
|
||||
import net.minecraft.world.entity.schedule.Activity
|
||||
|
||||
class SwitchToPanicWhenHostilesNearbyTaskConfig : SingleTaskConfig {
|
||||
@@ -30,6 +31,8 @@ class SwitchToPanicWhenHostilesNearbyTaskConfig : SingleTaskConfig {
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
runtime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
if (!condition.resolveBoolean()) return null
|
||||
behaviourConfigurationContext.addMemories(MemoryModuleType.NEAREST_HOSTILE)
|
||||
behaviourConfigurationContext.addSensors(SensorType.VILLAGER_HOSTILES)
|
||||
return BehaviorBuilder.create {
|
||||
it.group(it.present(MemoryModuleType.NEAREST_HOSTILE))
|
||||
.apply(it) { nearestHostile ->
|
||||
|
||||
+5
@@ -18,6 +18,7 @@ import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
import net.minecraft.world.entity.ai.behavior.declarative.BehaviorBuilder
|
||||
import net.minecraft.world.entity.ai.behavior.declarative.Trigger
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
import net.minecraft.world.entity.ai.sensing.SensorType
|
||||
import net.minecraft.world.entity.schedule.Activity
|
||||
|
||||
class SwitchToPanicWhenHurtTaskConfig : SingleTaskConfig {
|
||||
@@ -36,6 +37,8 @@ class SwitchToPanicWhenHurtTaskConfig : SingleTaskConfig {
|
||||
runtime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
if (!condition.resolveBoolean()) return null
|
||||
return if (includePassiveDamage.resolveBoolean()) {
|
||||
behaviourConfigurationContext.addMemories(MemoryModuleType.HURT_BY)
|
||||
behaviourConfigurationContext.addSensors(SensorType.HURT_BY)
|
||||
BehaviorBuilder.create {
|
||||
it.group(it.present(MemoryModuleType.HURT_BY))
|
||||
.apply(it) { _ ->
|
||||
@@ -47,6 +50,8 @@ class SwitchToPanicWhenHurtTaskConfig : SingleTaskConfig {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
behaviourConfigurationContext.addMemories(MemoryModuleType.HURT_BY_ENTITY)
|
||||
behaviourConfigurationContext.addSensors(SensorType.HURT_BY)
|
||||
BehaviorBuilder.create {
|
||||
it.group(it.present(MemoryModuleType.HURT_BY_ENTITY))
|
||||
.apply(it) { _ ->
|
||||
|
||||
+2
@@ -8,6 +8,7 @@
|
||||
|
||||
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.npc.configuration.MoLangConfigVariable
|
||||
import com.cobblemon.mod.common.entity.npc.ai.SwitchToBattleTask
|
||||
@@ -20,6 +21,7 @@ class SwitchToPokemonBattleTaskConfig : SingleTaskConfig {
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
): BehaviorControl<in LivingEntity> {
|
||||
behaviourConfigurationContext.addMemories(CobblemonMemories.POKEMON_BATTLE)
|
||||
return SwitchToBattleTask.createForPokemon()
|
||||
}
|
||||
}
|
||||
+6
@@ -36,6 +36,12 @@ class SwitchToSleepOnTrainerBedTaskConfig : SingleTaskConfig {
|
||||
return null
|
||||
}
|
||||
|
||||
behaviourConfigurationContext.addMemories(
|
||||
CobblemonMemories.POKEMON_SLEEPING,
|
||||
CobblemonMemories.POKEMON_BATTLE,
|
||||
MemoryModuleType.WALK_TARGET
|
||||
)
|
||||
|
||||
return BehaviorBuilder.create {
|
||||
it.group(
|
||||
it.absent(CobblemonMemories.POKEMON_BATTLE),
|
||||
|
||||
+74
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.ai.config.task
|
||||
|
||||
import com.bedrockk.molang.Expression
|
||||
import com.cobblemon.mod.common.CobblemonMemories
|
||||
import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
|
||||
import com.cobblemon.mod.common.api.ai.CobblemonAttackTargetData
|
||||
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.resolveBoolean
|
||||
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
|
||||
import net.minecraft.world.entity.ai.behavior.declarative.BehaviorBuilder
|
||||
import net.minecraft.world.entity.ai.behavior.declarative.Trigger
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
import net.minecraft.world.entity.ai.memory.MemoryStatus
|
||||
import net.minecraft.world.entity.ai.sensing.SensorType
|
||||
|
||||
/**
|
||||
* Directly sets the attack target of the entity to the nearest visible entity that matches the [entityCondition]
|
||||
* and is within the [range].
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since June 23rd, 2025
|
||||
*/
|
||||
class TargetEntityTaskConfig : SingleTaskConfig {
|
||||
val entityCondition: Expression = "true".asExpression()
|
||||
val range: ExpressionOrEntityVariable = Either.left("24".asExpression())
|
||||
|
||||
override fun getVariables(entity: LivingEntity) = emptyList<MoLangConfigVariable>()
|
||||
override fun createTask(
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
val range = range.resolveFloat()
|
||||
behaviourConfigurationContext.addMemories(
|
||||
MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES,
|
||||
MemoryModuleType.ATTACK_TARGET,
|
||||
CobblemonMemories.ATTACK_TARGET_DATA
|
||||
)
|
||||
behaviourConfigurationContext.addSensors(SensorType.NEAREST_LIVING_ENTITIES)
|
||||
return BehaviorBuilder.create { instance ->
|
||||
instance.group(
|
||||
instance.present(MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES),
|
||||
instance.registered(MemoryModuleType.ATTACK_TARGET)
|
||||
).apply(instance) { entities, attackTarget ->
|
||||
Trigger { world, entity, _ ->
|
||||
val target = instance.get(entities).findClosest {
|
||||
runtime.withQueryValue("entity", it.asMostSpecificMoLangValue())
|
||||
return@findClosest runtime.resolveBoolean(entityCondition)
|
||||
}.orElse(null)
|
||||
|
||||
if (target != null && target.distanceTo(entity) <= range) {
|
||||
val attackTargetData = CobblemonAttackTargetData(shouldContinue = entityCondition)
|
||||
entity.brain.setMemory(CobblemonMemories.ATTACK_TARGET_DATA, attackTargetData)
|
||||
attackTarget.set(target)
|
||||
}
|
||||
return@Trigger true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -32,6 +32,8 @@ import com.cobblemon.mod.common.util.withQueryValue
|
||||
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
|
||||
|
||||
/**
|
||||
* A configuration for a brain task. Its purpose is to generate a list of tasks to add to the brain of
|
||||
@@ -57,6 +59,7 @@ interface TaskConfig {
|
||||
cobblemonResource("do_nothing") to DoNothingTaskConfig::class.java,
|
||||
cobblemonResource("get_angry_at_attacker") to GetAngryAtAttackerTaskConfig::class.java,
|
||||
cobblemonResource("stop_being_angry_if_attacker_dead") to StopBeingAngryIfAttackerDeadTaskConfig::class.java,
|
||||
cobblemonResource("stop_attacking_if_target_invalid") to StopAttackingIfTargetInvalidTaskConfig::class.java,
|
||||
cobblemonResource("switch_npc_to_battle") to SwitchToNPCBattleTaskConfig::class.java,
|
||||
cobblemonResource("look_at_battling_pokemon") to LookAtBattlingPokemonTaskConfig::class.java,
|
||||
cobblemonResource("switch_npc_from_battle") to SwitchFromNPCBattleTaskConfig::class.java,
|
||||
@@ -96,7 +99,8 @@ interface TaskConfig {
|
||||
cobblemonResource("eat_grass") to EatGrassTaskConfig::class.java,
|
||||
cobblemonResource("find_air") to FindAirTaskConfig::class.java,
|
||||
cobblemonResource("go_to_land") to GoToLandTaskConfig::class.java,
|
||||
cobblemonResource("battle_flight_task") to BattleFlightTaskConfig::class.java,
|
||||
cobblemonResource("manage_flight_in_battle") to ManageFlightInBattleTaskConfig::class.java,
|
||||
cobblemonResource("attack_hostile_mobs") to AttackHostileMobsTaskConfig::class.java,
|
||||
cobblemonResource("move_into_fluid") to MoveIntoFluidTaskConfig::class.java,
|
||||
cobblemonResource("find_herd_leader") to FindHerdLeaderTaskConfig::class.java,
|
||||
cobblemonResource("follow_herd_leader") to FollowHerdLeaderTaskConfig::class.java,
|
||||
@@ -104,8 +108,10 @@ interface TaskConfig {
|
||||
cobblemonResource("switch_from_herd") to SwitchFromHerdTaskConfig::class.java,
|
||||
cobblemonResource("maintain_herd_leader") to MaintainHerdLeaderTaskConfig::class.java,
|
||||
cobblemonResource("count_followers") to CountFollowersTaskConfig::class.java,
|
||||
cobblemonResource("hate_entity") to HateEntityTaskConfig::class.java,
|
||||
cobblemonResource("target_entity") to TargetEntityTaskConfig::class.java,
|
||||
)
|
||||
|
||||
|
||||
val runtime = MoLangRuntime().setup()
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
|
||||
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.WrapperLivingEntityTask
|
||||
import com.cobblemon.mod.common.api.npc.configuration.MoLangConfigVariable
|
||||
@@ -22,6 +24,11 @@ class WakeUpTaskConfig : SingleTaskConfig {
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
if (entity !is PokemonEntity) {
|
||||
return null
|
||||
}
|
||||
behaviourConfigurationContext.addMemories(CobblemonMemories.POKEMON_DROWSY, CobblemonMemories.POKEMON_SLEEPING)
|
||||
behaviourConfigurationContext.addSensors(CobblemonSensors.POKEMON_DROWSY)
|
||||
return WrapperLivingEntityTask(WakeUpTask.create(), PokemonEntity::class.java)
|
||||
}
|
||||
}
|
||||
+6
-3
@@ -98,6 +98,12 @@ class WanderTaskConfig : SingleTaskConfig {
|
||||
|
||||
val wanderChanceExpression = wanderChance.asSimplifiedExpression(entity)
|
||||
|
||||
behaviourConfigurationContext.addMemories(
|
||||
MemoryModuleType.WALK_TARGET,
|
||||
MemoryModuleType.LOOK_TARGET,
|
||||
CobblemonMemories.PATH_COOLDOWN
|
||||
)
|
||||
|
||||
return BehaviorBuilder.create {
|
||||
it.group(
|
||||
it.absent(MemoryModuleType.WALK_TARGET),
|
||||
@@ -134,9 +140,6 @@ class WanderTaskConfig : SingleTaskConfig {
|
||||
maximumHeight = maximumHeight,
|
||||
world = world
|
||||
)
|
||||
// if (targetVec.y < minimumHeight || targetVec.y > maximumHeight) {
|
||||
// return@Trigger false
|
||||
// }
|
||||
walkTarget.set(
|
||||
CobblemonWalkTarget(
|
||||
pos = pos,
|
||||
|
||||
+12
-2
@@ -8,6 +8,7 @@
|
||||
|
||||
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.ai.asVariables
|
||||
@@ -50,11 +51,18 @@ class WaterWanderTaskConfig : SingleTaskConfig {
|
||||
|
||||
val wanderChanceExpression = wanderChance.asSimplifiedExpression(entity)
|
||||
|
||||
behaviourConfigurationContext.addMemories(
|
||||
MemoryModuleType.WALK_TARGET,
|
||||
MemoryModuleType.LOOK_TARGET,
|
||||
CobblemonMemories.PATH_COOLDOWN
|
||||
)
|
||||
|
||||
return BehaviorBuilder.create {
|
||||
it.group(
|
||||
it.absent(MemoryModuleType.WALK_TARGET),
|
||||
it.registered(MemoryModuleType.LOOK_TARGET)
|
||||
).apply(it) { walkTarget, lookTarget ->
|
||||
it.registered(MemoryModuleType.LOOK_TARGET),
|
||||
it.registered(CobblemonMemories.PATH_COOLDOWN)
|
||||
).apply(it) { walkTarget, lookTarget, pathCooldown ->
|
||||
Trigger { world, entity, time ->
|
||||
if (entity !is PathfinderMob || !entity.isInWater) {
|
||||
return@Trigger false
|
||||
@@ -66,6 +74,8 @@ class WaterWanderTaskConfig : SingleTaskConfig {
|
||||
return@Trigger false
|
||||
}
|
||||
|
||||
pathCooldown.setWithExpiry(true, 60L)
|
||||
|
||||
val target = BehaviorUtils.getRandomSwimmablePos(entity, horizontalRange.resolveInt(), verticalRange.resolveInt()) ?: return@Trigger false
|
||||
walkTarget.set(
|
||||
CobblemonWalkTarget(
|
||||
|
||||
+1
-1
@@ -83,7 +83,7 @@ interface ExperienceCandyUseEvent {
|
||||
*
|
||||
* @return If any experience was gained from the candy and if it was consumed.
|
||||
*/
|
||||
fun wasCandyConsumed() = this.experienceResult.experienceAdded > 0 && !player.isCreative
|
||||
fun wasCandyConsumed() = this.experienceResult.experienceAdded > 0 && !player.hasInfiniteMaterials()
|
||||
}
|
||||
|
||||
}
|
||||
+2
-2
@@ -30,7 +30,7 @@ data class PokemonInteractionGUICreationEvent(
|
||||
}
|
||||
|
||||
private fun getNextFreeOrientation(): Orientation {
|
||||
var largest = Orientation.TOP_LEFT
|
||||
var largest = Orientation.NORTH
|
||||
for (orientation in Orientation.entries) {
|
||||
if(!options.containsKey(orientation)) {
|
||||
return orientation
|
||||
@@ -42,4 +42,4 @@ data class PokemonInteractionGUICreationEvent(
|
||||
}
|
||||
return largest
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,20 +29,4 @@ interface EntityInteraction<T : Entity> {
|
||||
* @return true if the interaction was successful and no further interactions should be processed
|
||||
*/
|
||||
fun onInteraction(player: ServerPlayer, entity: T, stack: ItemStack): Boolean
|
||||
|
||||
/**
|
||||
* Decreases the stack size by a given amount.
|
||||
* The stack size should be validated beforehand.
|
||||
* If the [player] is in creative mode the decrement won't be performed.
|
||||
*
|
||||
* @param player The [ServerPlayer] that caused the interaction, this is used to check for creative mode.
|
||||
* @param stack The [ItemStack] being mutated.
|
||||
* @param amount The amount to deduct from the stack, default is 1.
|
||||
*/
|
||||
fun consumeItem(player: ServerPlayer, stack: ItemStack, amount: Int = 1) {
|
||||
if (!player.isCreative) {
|
||||
stack.shrink(amount)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+1
-1
@@ -112,7 +112,7 @@ class ShrinkItemEffect(val amount: Int = 1): InteractionEffect {
|
||||
if (player.getItemInHand(InteractionHand.MAIN_HAND).isDamageableItem)
|
||||
player.getItemInHand(InteractionHand.MAIN_HAND).hurtAndBreak(amount, player, EquipmentSlot.MAINHAND)
|
||||
else
|
||||
player.getItemInHand(InteractionHand.MAIN_HAND).shrink(amount)
|
||||
player.getItemInHand(InteractionHand.MAIN_HAND).consume(amount, player)
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
+1
-3
@@ -87,9 +87,7 @@ interface PokemonAndMoveSelectingItem {
|
||||
player.sendSystemMessage(battleLang("bagitem.invalid").red())
|
||||
} else {
|
||||
battlePokemon.actor.forceChoose(BagItemActionResponse(bagItem, battlePokemon, move.template.name))
|
||||
if (!player.isCreative) {
|
||||
stack.shrink(1)
|
||||
}
|
||||
stack.consume(1, player)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -98,7 +98,7 @@ interface PokemonSelectingItem {
|
||||
} else {
|
||||
battlePokemon.actor.forceChoose(BagItemActionResponse(bagItem, battlePokemon))
|
||||
val stackName = BuiltInRegistries.ITEM.getKey(stack.item)
|
||||
if (!player.isCreative) {
|
||||
if (!player.hasInfiniteMaterials()) {
|
||||
stack.shrink(1)
|
||||
battlePokemon.actor.itemsUsed.add(bagItem)
|
||||
}
|
||||
|
||||
@@ -108,6 +108,7 @@ import net.minecraft.tags.TagKey
|
||||
import net.minecraft.world.damagesource.DamageSource
|
||||
import net.minecraft.world.damagesource.DamageTypes
|
||||
import net.minecraft.world.entity.Entity
|
||||
import net.minecraft.world.entity.EntityDimensions
|
||||
import net.minecraft.world.entity.EntityType
|
||||
import net.minecraft.world.entity.LightningBolt
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
@@ -296,6 +297,13 @@ object MoLangFunctions {
|
||||
}
|
||||
world.setBlock(BlockPos(x, y, z), block.defaultBlockState(), Block.UPDATE_ALL)
|
||||
}
|
||||
map.put("is_air") { params ->
|
||||
val x = params.getDouble(0).toInt()
|
||||
val y = params.getDouble(1).toInt()
|
||||
val z = params.getDouble(2).toInt()
|
||||
val blockState = world.getBlockState(BlockPos(x, y, z))
|
||||
return@put DoubleValue(blockState.isAir)
|
||||
}
|
||||
map.put("get_block") { params ->
|
||||
val x = params.getInt(0)
|
||||
val y = params.getInt(1)
|
||||
@@ -920,6 +928,34 @@ object MoLangFunctions {
|
||||
return@put DoubleValue.ZERO
|
||||
}
|
||||
}
|
||||
map.put("set_render_scale") { params ->
|
||||
val scale = params.getDouble(0)
|
||||
npc.renderScale = scale.toFloat()
|
||||
return@put DoubleValue.ONE
|
||||
}
|
||||
map.put("render_scale") { _ -> DoubleValue(npc.renderScale) }
|
||||
map.put("set_hitbox_scale") { params ->
|
||||
val scale = params.getDouble(0).toFloat()
|
||||
npc.hitboxScale = scale
|
||||
npc.refreshDimensions()
|
||||
return@put DoubleValue.ONE
|
||||
}
|
||||
map.put("hitbox_scale") { _ -> DoubleValue(npc.hitboxScale) }
|
||||
map.put("set_hitbox") { params ->
|
||||
if (params.params.size == 0) {
|
||||
npc.hitbox = null
|
||||
return@put DoubleValue.ONE
|
||||
}
|
||||
val width = params.getDouble(0).toFloat()
|
||||
val height = params.getDouble(1).toFloat()
|
||||
val eyeHeight = params.getDoubleOrNull(2)?.toFloat() ?: (height * 0.85F)
|
||||
npc.hitbox = EntityDimensions.scalable(width, height).withEyeHeight(eyeHeight)
|
||||
return@put DoubleValue.ONE
|
||||
}
|
||||
map.put("unset_hitbox") {
|
||||
npc.hitbox = null
|
||||
return@put DoubleValue.ONE
|
||||
}
|
||||
map.put("aspects") {
|
||||
val aspects = npc.aspects
|
||||
return@put aspects.asArrayValue { StringValue(it) }
|
||||
@@ -1235,6 +1271,7 @@ object MoLangFunctions {
|
||||
map.put("is_sprinting") { DoubleValue(pokemonEntity.isUsingAltPose(cobblemonResource("sprinting"))) }
|
||||
map.put("in_air") { DoubleValue(pokemonEntity.isUsingAltPose(cobblemonResource("in_air"))) }
|
||||
map.put("is_wild") { DoubleValue(pokemonEntity.ownerUUID == null) }
|
||||
map.put("is_in_party") { DoubleValue(pokemonEntity.pokemon.storeCoordinates.get()?.store is PartyStore) }
|
||||
map.put("is_ridden") { DoubleValue(pokemonEntity.hasControllingPassenger()) }
|
||||
map.put("has_aspect") { DoubleValue(it.getString(0) in pokemonEntity.aspects) }
|
||||
map.put("is_pokemon") { DoubleValue.ONE }
|
||||
@@ -1243,6 +1280,12 @@ object MoLangFunctions {
|
||||
}) }
|
||||
map.put("is_wearing_hat") { DoubleValue(pokemonEntity.entityData.get(PokemonEntity.SHOWN_HELD_ITEM).`is`(CobblemonItemTags.WEARABLE_HAT_ITEMS)) }
|
||||
map.put("is_wearing_face") { DoubleValue(pokemonEntity.entityData.get(PokemonEntity.SHOWN_HELD_ITEM).`is`(CobblemonItemTags.WEARABLE_FACE_ITEMS)) }
|
||||
map.put("is_pastured") {
|
||||
DoubleValue((pokemonEntity.tethering != null))
|
||||
}
|
||||
map.put("pasture_conflict_enabled") {
|
||||
DoubleValue(pokemonEntity.getBehaviourFlag(PokemonBehaviourFlag.PASTURE_CONFLICT))
|
||||
}
|
||||
map
|
||||
}
|
||||
)
|
||||
|
||||
@@ -39,9 +39,8 @@ class NPCClass {
|
||||
var resourceIdentifier: ResourceLocation = cobblemonResource("dummy")
|
||||
var names: MutableList<Component> = mutableListOf()
|
||||
var aspects: MutableSet<String> = mutableSetOf() // These only make sense when applied via presets
|
||||
var baseScale: Float = 1F
|
||||
var hitbox = EntityDimensions.scalable(0.6F, 1.8F).withEyeHeight(1.62F)
|
||||
var modelScale: Float = 0.9375F
|
||||
var modelScale: Float = 0.9375F // Should this be removed in favour of the render scale stuff set on the entity?
|
||||
var battleConfiguration = NPCBattleConfiguration()
|
||||
var interaction: NPCInteractConfiguration? = null
|
||||
var canDespawn = true
|
||||
@@ -66,7 +65,6 @@ class NPCClass {
|
||||
fun encode(buffer: RegistryFriendlyByteBuf) {
|
||||
buffer.writeString(resourceIdentifier.toString())
|
||||
buffer.writeCollection(names) { _, v -> buffer.writeText(v) }
|
||||
buffer.writeFloat(baseScale)
|
||||
buffer.writeFloat(hitbox.width)
|
||||
buffer.writeFloat(hitbox.height)
|
||||
buffer.writeBoolean(hitbox.fixed)
|
||||
@@ -107,7 +105,6 @@ class NPCClass {
|
||||
fun decode(buffer: RegistryFriendlyByteBuf) {
|
||||
resourceIdentifier = ResourceLocation.parse(buffer.readString().toString())
|
||||
names = buffer.readList { buffer.readText().copy() }.toMutableList()
|
||||
baseScale = buffer.readFloat()
|
||||
val length = buffer.readFloat()
|
||||
val width = buffer.readFloat()
|
||||
val fixed = buffer.readBoolean()
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user