Compare commits

...
Author SHA1 Message Date
apion 263bccca4b idk whats up here but I wanna swap off this branch so 2025-02-07 17:49:10 -05:00
apion 1d94adface Fabric now boots 2025-01-26 03:02:57 -05:00
apion c741ddbc2e Comments 2025-01-25 04:23:40 -05:00
apion 8cad44ffb1 NEOFORGE IS BOOTING INTO A WORLD!!! 2025-01-25 04:05:34 -05:00
apion dec0376d11 More MDG testing 2025-01-18 15:46:50 -05:00
apion 007b2a49f4 More ModDevGradle porting 2025-01-18 01:19:26 -05:00
apion 082683723d Initial moddevgradle port 2025-01-17 21:31:25 -05:00
Paul bbd2b3aeed Updated sprites for galarica nuts, cuff, wreath 2025-01-13 08:37:39 +10:00
Hiroku 33951c868b Merge branch 'main' into 'main'
Fix Potions from applying more health than intended

See merge request cable-mc/cobblemon!1461
2025-01-12 00:23:35 +00:00
Chase 02f0e62bf8 Edit CHANGELOG.md 2025-01-12 00:01:08 +00:00
Hiroku 977b39e65c Merge branch '1.6.1-molang-expansion' into 'main'
[1.6.1] Add flows and expand some structs, also add FormeChangeEvent

See merge request cable-mc/cobblemon!1444
2025-01-11 22:55:33 +00:00
Chase 25a02e0b27 Small tweak to logic 2025-01-11 15:55:12 +00:00
Chase 4950297daa Remove unused variable 2025-01-11 15:52:26 +00:00
Chase 1c09cf6f30 Fix potion items from calling heal function twice 2025-01-11 15:50:56 +00:00
Paul 00d72902af Added recipes for galarica cuff and wreath 2025-01-11 17:41:29 +10:00
Paul eb986087cf Pipeline fixo (as if by magic!!!) 2025-01-11 16:31:39 +10:00
Paul 294e439f5e Moved the repurposed structures stuff to an inbuilt pack 2025-01-11 15:56:55 +10:00
Paul 6e7e870a1f Added galarica nut item 2025-01-11 12:09:29 +10:00
Hiroku ab78185689 Merge branch 'main' into 'main'
Add Built-in 1.21.1+ Compat With Repurposed Structures

See merge request cable-mc/cobblemon!1457
2025-01-10 20:40:00 +00:00
amo 7403556fa2 fixes for threads 2025-01-10 13:22:50 +00:00
Paul 7f451f1989 Cleaned up duplicates in changelog 2025-01-10 20:36:26 +10:00
Hiroku 3b2bfd5548 Merge branch 'display-cases' into 'main'
Fixed display cases not dropping items if destroyed via explosions

See merge request cable-mc/cobblemon!1460
2025-01-10 09:27:10 +00:00
Hiroku 3d1ee5ee0f Merge branch 'lion-eats-bugs' into 'main'
Small Fixes

Closes #1329, #1324, #1318, and #1325

See merge request cable-mc/cobblemon!1455
2025-01-10 09:13:36 +00:00
Guilherme Pereira 0584276189 emit pokemon aspects changed event only when pokemon is owned 2025-01-10 06:01:59 -03:00
Hiroku a16b17582d Merge branch 'feat/dynamic-pokemon-name-render' into 'main'
Better Pokédex discovery system

See merge request cable-mc/cobblemon!1442
2025-01-10 04:20:53 +00:00
Hiroku 71c1ae5540 Merge branch 'palafin-hero' into 'main'
Add features to several mons

See merge request cable-mc/cobblemon!1439
2025-01-10 04:10:42 +00:00
Hiroku 0233d2b0be Merge branch 'feature/migration-post-mortem' into 'main'
fix moves having raised stages that are beyond what new codecs expect when migrating from 1.5.2

See merge request cable-mc/cobblemon!1453
2025-01-10 03:55:28 +00:00
PolymetaandHiroku b67d474386 fix moves having raised stages that are beyond what new codecs expect when migrating from 1.5.2 2025-01-10 03:55:28 +00:00
Test 3239362e1a fix incorrect texture size for interact interface 2025-01-08 23:41:52 -05:00
Conan 0d240f01b6 Fixed display cases not dropping items if destroyed via explosions. 2025-01-09 02:55:27 +01:00
Test 99a71dc2e1 restore pokedex close transition 2025-01-06 20:20:52 -05:00
Paul fd99573a46 Fixed NPC editing GUI not immediately applying aspect changes on save 2025-01-05 18:16:52 +10:00
Guilherme Pereira fbcae404c0 update CHANGELOG.md 2025-01-05 03:11:27 -03:00
Guilherme Pereira 68cfd16fed emit pokemon aspects changed event only when aspects really changed 2025-01-05 03:10:13 -03:00
Guilherme Pereira 818038c715 fix hay bales not going into restoration machines 2025-01-05 03:09:47 -03:00
TelepathicGrunt 7c4b31db25 Add Built-in Compat With Repurposed Structures 2025-01-04 19:22:10 -05:00
Guilherme Pereira da6a88292e fix berry shear sound 2025-01-04 16:54:17 -03:00
Guilherme Pereira dee9a268d7 update CHANGELOG.md 2025-01-04 14:38:32 -03:00
Guilherme Pereira 5fd37438fc add player to pokerod reel event 2025-01-04 14:35:00 -03:00
Guilherme Pereira 51b30ab468 close pokedex and dialogues on inventory keybind press 2025-01-04 14:27:08 -03:00
Guilherme Pereira 36a3549b3e fix petilil typo 2025-01-04 13:03:31 -03:00
Guilherme Pereira 9e0ea63db6 fix vivichoke dip and leek and potato stew not returning bowls 2025-01-04 12:56:18 -03:00
Guilherme Pereira 739459c061 fix wooloo dex registration 2025-01-04 12:51:13 -03:00
Polymeta a6e06c80fe flipping more signs for particles
Signed-off-by: Polymeta <40173118+Polymeta@users.noreply.github.com>
2025-01-03 13:18:45 +00:00
Polymeta fc1cc54107 Merge branch 'BanInBattleRocketry' into 'main'
Ban in battle rocketry

See merge request cable-mc/cobblemon!1451
2025-01-03 12:07:49 +00:00
JazzMcNade 210bf9f5fb Updated Changelog 2025-01-02 21:13:01 -06:00
JazzMcNade 9454f2046a Addition comments 2025-01-02 20:58:24 -06:00
JazzMcNade 5621e69d58 Merge branch 'main' into BanInBattleRocketry 2025-01-02 20:51:11 -06:00
Polymeta 0c0f022e34 Merge branch 'fix-pokedex-command' into 'main'
Pokédex command and GUI fixes

Closes #1320 and #1321

See merge request cable-mc/cobblemon!1450
2025-01-02 16:58:35 +00:00
lionandPolymeta 220b363864 Pokédex command and GUI fixes 2025-01-02 16:58:35 +00:00
Polymeta 26d97f2043 Merge branch 'add-base-scale-npc-property' into 'main'
Add 'baseScale' NPC property

Closes #1268

See merge request cable-mc/cobblemon!1448
2024-12-31 14:54:38 +00:00
lionandPolymeta c4f5416bb3 Add 'baseScale' NPC property 2024-12-31 14:54:38 +00:00
Polymeta 8066a92ab5 Merge branch 'lion-eats-bugs' into 'main'
Small Fixes

Closes #1311, #889, and #1197

See merge request cable-mc/cobblemon!1449
2024-12-31 14:42:00 +00:00
lionandPolymeta f149439da8 Small Fixes 2024-12-31 14:41:59 +00:00
JazzMcNade 978064d2d0 Update PokemonMoveControl.kt 2024-12-31 02:54:49 -06:00
Polymeta 95dd6cbfcb Merge branch 'test/adorn_compat' into 'main'
Fixing up Adorn compatibility

See merge request cable-mc/cobblemon!1441
2024-12-30 16:17:17 +00:00
aeroeng15andPolymeta 551b3ebe87 Fixing up Adorn compatibility 2024-12-30 16:17:17 +00:00
Polymeta 89914813a1 Merge branch 'fix-pokemon-forgetting-moves-when-evolving' into 'main'
Fix Pokémon forgetting moves when evolving on specific cases

Closes #1252

See merge request cable-mc/cobblemon!1437
2024-12-30 15:54:09 +00:00
lionandPolymeta 742ec131d5 Fix Pokémon forgetting moves when evolving on specific cases 2024-12-30 15:54:09 +00:00
Polymeta 4175c36388 Merge branch 'fix/no-next-level-at-cap' into 'main'
Align the "To next level" display with official games logic, it will now show 0 when at cap.

See merge request cable-mc/cobblemon!1445
2024-12-30 15:32:33 +00:00
Hiroku f6ed1b38f8 Merge branch 'make-berries-shearable' into 'main'
Made berry trees be shearable by dispenser blocks

Closes #1071

See merge request cable-mc/cobblemon!1419
2024-12-30 11:39:21 +00:00
Faintful c299967cce Updated changelog 2024-12-30 12:35:44 +01:00
Polymeta b79f569def Merge branch 'fix-pokemon-riding-two-boats' into 'main'
Fix Pokémon riding two boats

Closes #1281

See merge request cable-mc/cobblemon!1447
2024-12-30 10:54:31 +00:00
lionandPolymeta 944144a671 Fix Pokémon riding two boats 2024-12-30 10:54:31 +00:00
Polymeta 586b5a860f Merge branch 'fix-npc-player-lose-command' into 'main'
Fix npc player lose command

Closes #1306 and #1282

See merge request cable-mc/cobblemon!1443
2024-12-30 01:33:47 +00:00
lionandPolymeta 29d91fb191 Fix npc player lose command 2024-12-30 01:33:46 +00:00
Polymeta 183d85a3b6 Merge branch 'overlay-invisible-man-collab' into 'main'
fix: Party overlay not respecting hidden UI (F1)

See merge request cable-mc/cobblemon!1440
2024-12-30 00:48:56 +00:00
Polymeta 0795b06ca0 use 1.4.1 instead 1.4.0 for tags history [skip-ci]
Signed-off-by: Polymeta <40173118+Polymeta@users.noreply.github.com>
2024-12-30 00:15:21 +00:00
Polymeta 6fdd87f5cf update tags directory to keep history [skip-ci]
Signed-off-by: Polymeta <40173118+Polymeta@users.noreply.github.com>
2024-12-29 23:59:02 +00:00
Ina 3b364a4590 fix: Align the "To next level" display with official games logic, it will now show 0 when at cap. 2024-12-29 17:20:01 +00:00
Ina baca93c9b2 feat: Support for Illusion in the dex reveal process. 2024-12-29 16:54:17 +00:00
amo b6d13b8861 Merge branch 'refs/heads/main' into 1.6.1-molang-expansion
# Conflicts:
#	common/src/main/kotlin/com/cobblemon/mod/common/battles/pokemon/BattlePokemon.kt
2024-12-29 16:42:55 +00:00
amo b271223f6a lots o' stuff 2024-12-29 16:31:25 +00:00
Ina 004f2de623 chore: Changelog 2024-12-29 15:11:45 +00:00
Ina 570629bff2 feat: Improve Pokemon reveal logic 2024-12-29 15:08:16 +00:00
Ina 7e5b8260de refactor: Simplify base label resolving logic. 2024-12-29 13:45:23 +00:00
Ina 3e5e851dba fix: Don't instance new texts for static elements every tick. 2024-12-29 11:25:50 +00:00
Ina 9f866aa292 chore: Hiro bullies the work-challenged. 2024-12-29 11:18:54 +00:00
Ina 4e4417d4df Merge branch 'main' into overlay-invisible-man-collab 2024-12-29 11:17:39 +00:00
Hiroku 900ca0cd8d Merge branch 'feature/small-fixes' into 'main'
fixes and minor cleanup

Closes #1277, #1302, and #1310

See merge request cable-mc/cobblemon!1432
2024-12-29 01:04:53 +00:00
PolymetaandHiroku 5448031cae fixes and minor cleanup 2024-12-29 01:04:53 +00:00
Ina abd92c2325 fix: Party overlay not respecting hidden UI (F1) 2024-12-28 22:07:37 +00:00
Vaniron c4948a6611 Add three_segment feature to Dudunsparce 2024-12-28 18:24:52 +00:00
Vaniron cc459c99aa Add hero features to Palafin 2024-12-28 18:15:28 +00:00
Polymeta a3ac3c36e6 Merge branch 'fix-bait-consumption' into 'main'
Fixed bait being consumed when not reeling in any Pokémon.

Closes #1308 and #1307

See merge request cable-mc/cobblemon!1438
2024-12-28 12:22:19 +00:00
lionandPolymeta 36ce262755 Fixed bait being consumed when not reeling in any Pokémon. 2024-12-28 12:22:19 +00:00
Apion 9246523853 Merge branch 'particle-stuff' into 'main'
A bunch of particle changes

See merge request cable-mc/cobblemon!1295
2024-12-28 03:03:56 +00:00
Apion db2c2f0089 A bunch of particle changes 2024-12-28 03:03:56 +00:00
Polymeta 3a090ba01c Merge branch 'RestorePokemonSpawnYaw' into 'main'
Restore pokemon spawn yaw

See merge request cable-mc/cobblemon!1436
2024-12-28 02:11:17 +00:00
JazzMcNadeandPolymeta 3c4481c9cc Restore pokemon spawn yaw 2024-12-28 02:11:17 +00:00
Polymeta 4e73a19ade Merge branch 'configurable-dex-scanning-range' into 'main'
Add config to max Pokédex scanning range

Closes #1247

See merge request cable-mc/cobblemon!1387
2024-12-28 00:33:24 +00:00
lionandPolymeta c58ba08a65 Add config to max Pokédex scanning range 2024-12-28 00:33:24 +00:00
Polymeta 18940956a8 Merge branch 'fix-pasture-pokemon-list-padding' into 'main'
Fix pasture Pokémon list padding

Closes #1273

See merge request cable-mc/cobblemon!1421
2024-12-27 23:52:04 +00:00
lionandPolymeta 68520307b4 Fix pasture Pokémon list padding 2024-12-27 23:52:04 +00:00
Hiroku 84825dbd69 Add vietnamese 2024-12-27 22:45:16 +00:00
Polymeta b231a80b68 Merge branch 'moe-eats-bugs' into 'main'
Advancement fixes

Closes #1262

See merge request cable-mc/cobblemon!1417
2024-12-27 13:04:27 +00:00
MoeBoy76andPolymeta d2796b8755 Advancement fixes 2024-12-27 13:04:27 +00:00
Polymeta 1ab3ca8628 Merge branch 'fix-collidable-invisible-pokemon' into 'main'
Fix Pokémon being collidable when trying to capture them

Closes #401

See merge request cable-mc/cobblemon!1382
2024-12-27 12:55:22 +00:00
lionandPolymeta f4da1436a5 Fix Pokémon being collidable when trying to capture them 2024-12-27 12:55:22 +00:00
Faintful 9a0b779ca3 Merge remote-tracking branch 'upstream/main' into make-berries-shearable 2024-12-27 13:40:11 +01:00
Polymeta 2bcb42270a Merge branch 'hide-unimplemented-pokemon-from-the-dex' into 'main'
Add config to hide unimplemented Pokémon from the Pokédex

Closes #1274

See merge request cable-mc/cobblemon!1422
2024-12-27 12:37:32 +00:00
lionandPolymeta 51472d2369 Add config to hide unimplemented Pokémon from the Pokédex 2024-12-27 12:37:32 +00:00
Polymeta 2cb430d927 Merge branch 'is-standing-on-blocks-molang-function' into 'main'
Add 'is_standing_on_blocks' MoLang function

See merge request cable-mc/cobblemon!1393
2024-12-27 12:36:04 +00:00
lionandPolymeta 7bbfbf5852 Add 'is_standing_on_blocks' MoLang function 2024-12-27 12:36:04 +00:00
Polymeta 93a368a844 Merge branch 'fix_fishing_condition' into 'main'
Internal change, move condition variables related to fishing into...

See merge request cable-mc/cobblemon!1430
2024-12-27 01:46:23 +00:00
Polymeta 5c934a0b66 Merge branch 'FossilMachineReturnFossilFix' into 'main'
FossilMachineReturnFossilFix

See merge request cable-mc/cobblemon!1426
2024-12-27 01:36:24 +00:00
JazzMcNadeandPolymeta 1a4034ded4 FossilMachineReturnFossilFix 2024-12-27 01:36:23 +00:00
JPAK dbd73c53ea Internal change, move condition variables related to fishing into FishingSpawningCondition.kt instead of SpawningCondition.kt 2024-12-26 11:28:11 -06:00
Polymeta 25d17a271b Merge branch 'toms-fixed' into 'main'
Fix crash when placing a restoration tank next to Tom's Storage block.

See merge request cable-mc/cobblemon!1427
2024-12-26 11:39:22 +00:00
JordanandPolymeta e9b3940eb6 Fix crash when placing a restoration tank next to Tom's Storage block. 2024-12-26 11:39:22 +00:00
Hiroku e442ca2732 Merge branch 'yamask-patch' into 'main'
Add galarian yamask as feature

See merge request cable-mc/cobblemon!1428
2024-12-26 07:40:17 +00:00
Vaniron b34e1f30d1 Add galarian yamask as feature 2024-12-26 07:33:40 +00:00
Polymeta 8747d3cd6f changelog 1.6.1 prep [skip-ci]
Signed-off-by: Polymeta <40173118+Polymeta@users.noreply.github.com>
2024-12-26 00:06:13 +00:00
Hiroku ca7a4e12be Merge branch 'change-modmenu-links' into 'main'
Update mod menu links

See merge request cable-mc/cobblemon!1424
2024-12-25 09:08:44 +00:00
lionandHiroku 9c3b713c4a Update mod menu links 2024-12-25 09:08:44 +00:00
Hiroku 6c0c352001 Merge branch 'fix-dex-crash-when-switching-forms' into 'main'
Fix Pokédex crash when switching forms

See merge request cable-mc/cobblemon!1423
2024-12-25 06:29:12 +00:00
lionandHiroku 51c1706a9a Fix Pokédex crash when switching forms 2024-12-25 06:29:11 +00:00
Hiroku 5320704702 Edit gradle.properties 2024-12-25 06:27:07 +00:00
Paul 91e28616a9 Lil changelog amendment [skip-ci] 2024-12-25 11:39:29 +10:00
Paul 8df06a4836 The grinch stole the jar!! [skip-ci] 2024-12-25 09:25:42 +10:00
Hiroku f2c9886ae0 Merge branch 'feature/updated-tag-scripts' into 'main'
update and run tag scripts

See merge request cable-mc/cobblemon!1420
2024-12-24 23:25:12 +00:00
PolymetaandHiroku d74ca7b70d update and run tag scripts 2024-12-24 23:25:12 +00:00
Paul 2e3302bdec not snap 2024-12-25 08:40:38 +10:00
Paul f77af7c954 Merge remote-tracking branch 'origin/lang-updates' 2024-12-25 07:56:12 +10:00
Hiroku 63ed488b03 Merge branch 'quic-molang-additions' into 'main'
[1.6] Add entity type id molang function

See merge request cable-mc/cobblemon!1415
2024-12-24 21:50:53 +00:00
Hiroku fcce15e210 Edit MoLangFunctions.kt 2024-12-24 21:50:15 +00:00
Test d816710566 Changelog shenanigans 3 [skip-ci] 2024-12-24 21:48:16 +00:00
Hiroku c8a8e689cc Merge branch 'actually-on-hit' into 'main'
[1.6] make THROWN_POKEBALL_HIT actually do what it says on the tin

See merge request cable-mc/cobblemon!1418
2024-12-24 21:47:49 +00:00
Paul 222f6dd955 Changelog shenanigans 2 [skip-ci] 2024-12-25 07:46:03 +10:00
Faintful ba7a3ab3c2 Made berry trees be shearable by dispenser blocks 2024-12-24 17:27:33 +01:00
amo f61efb11b1 fix silly 2024-12-24 14:58:03 +00:00
Briar 19b4d841f4 im a FOOL 2024-12-24 14:31:31 +00:00
Briar 704320f1bc oops 2024-12-24 14:22:42 +00:00
Briar e5480bd05b make THROWN_POKEBALL_HIT actually do what it says on the tin 2024-12-24 14:17:57 +00:00
Briar 8d504d23e1 Update file MoLangFunctions.kt 2024-12-24 13:58:51 +00:00
Paul 2912ffdad9 Changelog shenanigans [skip-ci] 2024-12-24 23:38:25 +10:00
Paul 986f22c5a5 Added clamping for pokemon angles in the hopes of killing the watchdog killer 2024-12-24 18:58:10 +10:00
Hiroku 880f6de77a Merge branch 'fix-no-ai-property' into 'main'
Fix no_ai property not working when set to false

Closes #1270

See merge request cable-mc/cobblemon!1413
2024-12-24 08:01:50 +00:00
lionandHiroku 7f87b0f184 Fix no_ai property not working when set to false 2024-12-24 08:01:50 +00:00
Hiroku a811a823e6 Merge branch 'fix-shiny-magikarp-jump-variations' into 'main'
Fix shiny Magikarp jump variations

See merge request cable-mc/cobblemon!1416
2024-12-24 08:01:20 +00:00
lionandHiroku a45999894b Fix shiny Magikarp jump variations 2024-12-24 08:01:19 +00:00
Hiroku eeba80e7e7 Merge branch 'patch-1' into 'main'
Galarian Mr.Mime typo

See merge request cable-mc/cobblemon!1414
2024-12-24 08:00:17 +00:00
Briar 97b20158e9 Update file MoLangFunctions.kt 2024-12-24 02:28:33 +00:00
VanironCZ 586eaa9135 Fix typo, make form work 2024-12-24 00:58:06 +00:00
Polymeta dc7925ab3e Merge branch 'ci-fixes' into 'main'
Fix CI

See merge request cable-mc/cobblemon!1412
2024-12-23 22:46:40 +00:00
complacentdevandPolymeta 8986159a25 Fix CI 2024-12-23 22:46:39 +00:00
Test b864f715ea update item sprites 2024-12-23 17:24:19 -05:00
Nick 02b7d5eeae Merge branch 'fix/neoforge-payload-logging' into 'main'
No longer log all packets by state, just register

See merge request cable-mc/cobblemon!1411
2024-12-23 21:05:03 +00:00
Nick 614be610d4 No longer log all packets by state, just register 2024-12-23 13:02:40 -08:00
Polymeta 1084c7a289 Merge branch 'ci' into 'main'
Make Cobblemon 20% Smaller

See merge request cable-mc/cobblemon!1224
2024-12-23 17:55:16 +00:00
complacentdevandPolymeta 110d6dc828 Make Cobblemon 20% Smaller 2024-12-23 17:55:16 +00:00
Paul d98d68c7d4 Added cancellation and handler ordering support to flows, more cleanup for Pokedex event, changelog for flows, removed old junk 2024-12-23 21:50:44 +10:00
Hiroku 6369d876e3 Merge branch 'HorizontalTeamAlignmentForMoveTargeting' into 'main'
Horizontal team alignment for move targeting

See merge request cable-mc/cobblemon!1410
2024-12-23 10:31:06 +00:00
Hiroku 8388a53017 Merge branch 'date-and-timolang' into 'main'
[1.6] system time and date molang

See merge request cable-mc/cobblemon!1405
2024-12-23 10:17:04 +00:00
Hiroku 3a59d7d7c9 Edit MoLangFunctions.kt 2024-12-23 10:08:03 +00:00
Hiroku 3d9d3318b1 Merge branch 'cancelable-dex-knowledge' into 'main'
[1.6] Cancelable dex data event, split into pre & post

See merge request cable-mc/cobblemon!1403
2024-12-23 09:26:26 +00:00
Paul d032e0449b Tweaks for inbuilt region bias pack and changelog 2024-12-23 19:25:05 +10:00
Hiroku bcdbb19a75 Merge branch 'fix-pasture-shiny-effect' into 'main'
Fix shiny pasture Pokémon playing the shiny effect incorrectly

Closes #1257

See merge request cable-mc/cobblemon!1409
2024-12-23 09:24:36 +00:00
lionandHiroku 2181cdb4ef Fix shiny pasture Pokémon playing the shiny effect incorrectly 2024-12-23 09:24:36 +00:00
JazzMcNade 24257a4c6e Swapped team alignment from vertical to horizontal 2024-12-23 02:12:19 -06:00
Test 2a293def4f Merge branch 'inbuilt-packs' into 'main'
Setup inbuilt resource packs for various things

See merge request cable-mc/cobblemon!1408
2024-12-23 07:28:33 +00:00
Hiroku a3d77dd2a0 Merge branch 'CounterMovesUITargetingFix' into 'main'
Fix UI targeting for MetalBurst, Counter, MIrrorCoat, etc

See merge request cable-mc/cobblemon!1407
2024-12-23 06:51:43 +00:00
Paul 311f0e3192 Setup inbuilt resource packs for various things 2024-12-23 16:30:20 +10:00
JazzMcNade be2099130b Fix UI targeting for MetalBurst, Counter, MIrrorCoat, etc 2024-12-23 00:18:35 -06:00
Hiroku 6ebe0b9c7e Merge branch 'fix-spectators-obscuring-line-of-sight' into 'main'
Fix spectators obscuring line of sight when interacting with other players

Closes #1261

See merge request cable-mc/cobblemon!1406
2024-12-23 04:11:58 +00:00
lionandHiroku dde5c00789 Fix spectators obscuring line of sight when interacting with other players 2024-12-23 04:11:57 +00:00
amo d980faed64 resolve threads 2024-12-23 03:22:39 +00:00
Hiroku 7a80bc54ea Merge branch 'disable-entity-labels-when-crouching-only' into 'main'
Set 'displayEntityLabelsWhenCrouchingOnly' config default to false

See merge request cable-mc/cobblemon!1390
2024-12-23 02:53:53 +00:00
lionandHiroku f207206b13 Set 'displayEntityLabelsWhenCrouchingOnly' config default to false 2024-12-23 02:53:52 +00:00
amo edf510d8e8 split dex data changed event into pre and post, make pre cancelable 2024-12-23 02:30:38 +00:00
Hiroku 721384547f Merge branch 'feature/small-fixes' into 'main'
(1.6) Small fixes

Closes #1188 and #1264

See merge request cable-mc/cobblemon!1404
2024-12-23 01:36:36 +00:00
PolymetaandHiroku ce5189e83a (1.6) Small fixes 2024-12-23 01:36:36 +00:00
amo d7fc09b967 split dex data changed event into pre and post, make pre cancelable 2024-12-22 22:47:45 +00:00
Gustavo PuerariandWeblate 703eb7645c Translated using Weblate (Portuguese (Brazil))
Currently translated at 34.8% (2228 of 6391 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/pt_BR/
2024-12-22 21:41:42 +00:00
Polymeta 604c184029 Merge branch 'This-time-I-wont-mess-up' into 'main'
Let's try this again

See merge request cable-mc/cobblemon!1402
2024-12-22 19:00:29 +00:00
Slippy 727ada3e00 Let's try this again 2024-12-22 12:51:58 -06:00
Hiroku d29e471ab4 Merge branch 'ok-fine-heres-a-journey-molang-mr' into 'main'
[1.6 pls] Journey Molang Migration

See merge request cable-mc/cobblemon!1385
2024-12-22 08:10:23 +00:00
Paul 6c1e6677b3 More molang cleanup 2024-12-22 18:03:31 +10:00
Paul aaa7fcee47 Cleaned up particle molang functions, moved reusable particle spawning logic from netcode to ParticleStorm 2024-12-22 18:01:05 +10:00
Hiroku 37b050f2e5 Merge branch 'ihatebugtypes' into 'main'
Ihatebugtypes

Closes #1167, #1201, and #1225

See merge request cable-mc/cobblemon!1369
2024-12-22 06:24:19 +00:00
Hiroku 16ccd6bcc3 Merge branch 'upstream/npcs' into 'main'
Allow for programmatic persistence of npcs

See merge request cable-mc/cobblemon!1388
2024-12-22 06:23:00 +00:00
Paul 8b0d228339 Merge remote-tracking branch 'origin/main' 2024-12-22 12:07:59 +10:00
Paul 5019026472 Further reworked brewing, JEI/EMI compat might exist on Neo now (fabric is impossibru (for now)) 2024-12-22 12:07:48 +10:00
amo ace38ad6be Merge branch 'main' into ok-fine-heres-a-journey-molang-mr 2024-12-21 17:03:47 +00:00
Polymeta 5c885112ef Merge branch '1.6-additional-additions' into 'main'
1.6 additional additions

See merge request cable-mc/cobblemon!1398
2024-12-21 14:23:06 +00:00
Plastered_CrabandPolymeta a37532579e 1.6 additional additions 2024-12-21 14:23:05 +00:00
Segfault Guy 0f751eb732 cleanup 2024-12-21 07:18:41 -05:00
Paul 9840a2758a Fixed everything being medicinal brew. Drink it!!! (fixes #1249) 2024-12-21 22:07:30 +10:00
Paul ad52d1ed5f Fixed busted flowers tag, fixed party check criterion 2024-12-21 21:48:09 +10:00
Paul 74464dc13a Fixed PC block waterlog property not being the right one, causing export issues, closes #1253 2024-12-21 21:33:24 +10:00
Hiroku f280ec8979 Merge branch 'half-slabs' into 'main'
Stonecutter Fixes

Closes #1260

See merge request cable-mc/cobblemon!1399
2024-12-21 05:57:42 +00:00
dhi_holo 25ca0fbd13 Recreate flowers.json
Moved the working flowers.json from being just in items to being a block tag too
2024-12-21 15:25:33 +10:00
dhi_holo 2c8d544088 Tag Fix
Cleans up a tag, removes a recursive tag error, and tweaks a spawn to be valid again.
2024-12-21 15:16:12 +10:00
Segfault Guy 7dbe31d084 Merge remote-tracking branch 'origin/main' into ihatebugtypes 2024-12-20 23:47:30 -05:00
Segfault Guy de05133b31 update licenses 2024-12-20 23:45:45 -05:00
Segfault Guy 3b70b8351a Block battles on evolution. 2024-12-20 23:44:36 -05:00
dhi_holo 784439475a Stonecutter Fixes
Moved the count value from outside the result to inside of it. No idea why it ended up outside, but hey, easy fix. Resolves #1260
2024-12-21 14:22:44 +10:00
Paul 2024ddb4f0 Wrap spawn direction angle within acceptable entity rotation values 2024-12-21 12:37:32 +10:00
Paul ad35be7ddb Added player level range influence to fishing 2024-12-21 10:51:27 +10:00
Paul dbf688fade Merge remote-tracking branch 'origin/lang-updates'
# Conflicts:
#	common/src/main/resources/assets/cobblemon/lang/de_de.json
#	common/src/main/resources/assets/cobblemon/lang/es_mx.json
#	common/src/main/resources/assets/cobblemon/lang/th_th.json
2024-12-21 09:30:37 +10:00
Polymeta 17d3d5f829 Merge branch 'implement_pokemon' into 'main'
This weeks pokemon implementation

Closes #1230 and #1137

See merge request cable-mc/cobblemon!1397
2024-12-20 13:30:37 +00:00
Frank The FarmerandPolymeta fba00c23b4 This weeks pokemon implementation 2024-12-20 13:30:35 +00:00
Hiroku cfe516e086 Merge branch 'RaftClientSyncFix' into 'main'
Fixed client sync issue with platforms. (Clients do not possess accurate behavior data.)

See merge request cable-mc/cobblemon!1394
2024-12-20 10:29:40 +00:00
Polymeta 63d921cb12 Merge branch 'fix-drop-message' into 'main'
Fix 'air dropped to the ground' message when Pokémon are killed in lava and drop no loot

See merge request cable-mc/cobblemon!1395
2024-12-20 09:23:07 +00:00
lionandPolymeta 6acde8c90f Fix 'air dropped to the ground' message when Pokémon are killed in lava and drop no loot 2024-12-20 09:23:07 +00:00
Hiroku 196ce2ab6d Merge branch 'fix-evolution-animation' into 'main'
Fix evolution animation not playing back to back

Closes #1229

See merge request cable-mc/cobblemon!1396
2024-12-20 09:09:12 +00:00
lionandHiroku 6fb6ea2927 Fix evolution animation not playing back to back 2024-12-20 09:09:12 +00:00
JazzMcNade 538027cb1b Fixed client sync issue with platforms. (Clients do not possess accurate behavior data.) 2024-12-19 17:47:17 -06:00
Paul 51fcc91d88 Fixed blinks not running 2024-12-19 21:24:00 +10:00
Gustavo Felippi PuerariandWeblate 63c603cc01 Translated using Weblate (Portuguese (Brazil))
Currently translated at 33.9% (2169 of 6391 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/pt_BR/
2024-12-18 23:02:36 +00:00
TeggyandWeblate a7406dd321 Translated using Weblate (Spanish)
Currently translated at 98.0% (6267 of 6391 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/es/
2024-12-18 23:02:36 +00:00
Paul 0e1611fd8e Merge remote-tracking branch 'origin/main' 2024-12-18 19:15:35 +10:00
Paul 51e575c6a6 Fixed action effects not playing animations, particles, or sounds in many circumstances. Tweaked spawn direction handling 2024-12-18 19:15:17 +10:00
Test 8789d16a53 replace hardcoded values with attribute for item interaction range 2024-12-17 22:09:12 -05:00
Gustavo Felippi PuerariandWeblate f7986d5ccf Translated using Weblate (Portuguese (Brazil))
Currently translated at 33.7% (2160 of 6391 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/pt_BR/
2024-12-18 02:41:45 +00:00
Felipe Bermudes OrmeñoandWeblate c7423408a9 Translated using Weblate (Spanish (Mexico))
Currently translated at 30.6% (1960 of 6391 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/es_MX/
2024-12-18 02:41:44 +00:00
TeggyandWeblate 52b0c63751 Translated using Weblate (Spanish)
Currently translated at 96.8% (6189 of 6391 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/es/
2024-12-18 02:41:44 +00:00
Polymeta 7ae20ccd60 Merge branch 'scrappy-lang-fix' into 'main'
Updated Scrappy's ability description

See merge request cable-mc/cobblemon!1389
2024-12-17 23:53:29 +00:00
Conan 621b867d14 Updated Scrappy's ability description 2024-12-17 21:46:24 +01:00
chasem-dev b0ea22d220 Allow for programmatic persistence of npcs 2024-12-17 15:19:56 -05:00
amo dfb54b3bc3 brainfart 2024-12-17 01:17:01 +00:00
Polymeta 2928667500 Merge branch '1.6-spawns' into 'main'
Updated recipes for Scope Lens, Wide Lens, and Zoom Lens. Updated spawns....

See merge request cable-mc/cobblemon!1384
2024-12-16 23:50:04 +00:00
VeraxielandPolymeta 1c528a909c Updated recipes for Scope Lens, Wide Lens, and Zoom Lens. Updated spawns.... 2024-12-16 23:50:04 +00:00
amo 1083e770d0 add player-specific packet molang methods for snowstorm particles & animations 2024-12-16 12:43:15 +00:00
Paul 920f3f114b Merge remote-tracking branch 'origin/main' 2024-12-16 21:08:27 +10:00
Hiroku 9ca5d12f84 Merge branch 'FixInBattleFlightFidgeting' into 'main'
FixInBattleFlightFidgeting

See merge request cable-mc/cobblemon!1383
2024-12-16 09:41:22 +00:00
Hiroku cc9bb528a8 Merge branch 'npc-hitbox' into 'main'
Fixed npcs not being able to take custom hitbox properties

See merge request cable-mc/cobblemon!1381
2024-12-16 09:40:46 +00:00
Paul 1cbd00691f Merge remote-tracking branch 'origin/main' 2024-12-16 19:05:10 +10:00
JazzMcNade f4c847fdd5 Replaced isGrounded with the more reliable isAirborne. Prevented pokemon from currently flying from receiving a raft. 2024-12-16 01:04:46 -06:00
Conan ec6e1403e7 Fixed npcs not being able to take custom hitbox properties 2024-12-16 05:24:26 +01:00
Hiroku 10a4a03a8b Merge branch 'close-battle-gui-with-mouse' into 'main'
Fix battle GUI not closing with mouse keybind

Closes #1093

See merge request cable-mc/cobblemon!1380
2024-12-16 03:06:46 +00:00
lionandHiroku e0a86f8794 Fix battle GUI not closing with mouse keybind 2024-12-16 03:06:45 +00:00
Paul 767e024ec4 Debug logging of pokemon entity ticking 2024-12-16 09:55:45 +10:00
Polymeta c8b0f36049 Merge branch 'bugfixes-apion' into 'main'
Fixes #1182

Closes #1182

See merge request cable-mc/cobblemon!1373
2024-12-15 18:25:02 +00:00
ApionandPolymeta be2a0be806 Fixes #1182 2024-12-15 18:25:02 +00:00
Paul ba4d42ccf6 Try tweaking spawn direction handling 2024-12-15 23:04:08 +10:00
Paul 5545d3498f Include 2 more variables in clamping of rotations 2024-12-15 20:53:50 +10:00
Hiroku 641bd7ebaa Merge branch 'advancing' into 'main'
1.6 Advancement Reworks

See merge request cable-mc/cobblemon!1374
2024-12-15 09:16:28 +00:00
dhi_holoandHiroku 234c4fa0d4 1.6 Advancement Reworks 2024-12-15 09:16:28 +00:00
Hiroku 3dfda71ed5 Merge branch 'AbilityPatchCapsuleRefactor' into 'main'
AbilityPatchCapsuleRefactor

See merge request cable-mc/cobblemon!1377
2024-12-15 09:08:05 +00:00
Hiroku 65ee6de93f Merge branch 'chest-boat-interact' into 'main'
moved changes to chest boat (i'm dumb)

Closes #1214

See merge request cable-mc/cobblemon!1379
2024-12-15 09:07:48 +00:00
Paul be88b727bc Added useFixedRandom to pool party provider, added randomizePartyOrder to NPC classes and presets for randomly choosing lead battle pokemon 2024-12-15 18:04:04 +10:00
luke a69fc462ee moved changes to chest boat (i'm dumb) 2024-12-15 00:38:08 -07:00
Hiroku 7d5c30d27c Merge branch 'shift-click-interact' into 'main'
Changed distance to use player attribute

Closes #1232

See merge request cable-mc/cobblemon!1378
2024-12-15 07:32:39 +00:00
Hiroku f7c9c9d4f4 Update AbilityTypeChanger.kt 2024-12-15 07:30:12 +00:00
luke 41bc14168a Changed distance to use player attribute 2024-12-15 00:24:38 -07:00
Paul 9540c38a72 Updated readme example for NPC 2024-12-15 16:58:31 +10:00
JazzMcNade 7a96ed7cd1 Refactored queryPossible() as to not to require explicit Priority values 2024-12-15 00:45:51 -06:00
Hiroku 677adc8d2f Merge branch 'starter-selection-cry' into 'main'
Play cry when Pokémon is clicked on the starter selection screen

See merge request cable-mc/cobblemon!1362
2024-12-15 06:25:29 +00:00
lionandHiroku a99b1dfc6c Play cry when Pokémon is clicked on the starter selection screen 2024-12-15 06:25:29 +00:00
Hiroku 4a718ad0f6 Merge branch 'dex-update-event' into 'main'
Dex Data Updated Event

See merge request cable-mc/cobblemon!1353
2024-12-15 05:27:08 +00:00
Paul ddd417d458 Added player to PokedexDataChangedEvent's flow context 2024-12-15 15:19:43 +10:00
Paul 10a12a897e Merge remote-tracking branch 'origin/main' into dex-update-event 2024-12-15 15:15:48 +10:00
Paul 9fce99ed73 Improved dex event, added dex update flow, expanded dex molang and added q.player.pokedex 2024-12-15 15:15:13 +10:00
Hiroku c35f60dd5d Merge branch 'AbilitiesFixesRedux' into 'main'
AbilitiesFixesRedux

Closes #1245

See merge request cable-mc/cobblemon!1376
2024-12-15 03:11:07 +00:00
JazzMcNade 54e5a5e819 Fixed single abilities mons always evolving into the hidden ability. Fixed ability capsule / patch not being able to revert abilities. 2024-12-14 20:35:23 -06:00
Test 79ae35ea9e Merge branch 'n-p-c' into 'main'
fix npc scaling + eye height, update edit interface

See merge request cable-mc/cobblemon!1375
2024-12-15 02:17:45 +00:00
Test 58f85e6d0d fix npc scaling + eye height, update edit interface 2024-12-15 02:17:45 +00:00
Polymeta 71bfdf41f4 Merge branch 'the-else-strikes-back' into 'main'
Fix Feebas spawning

Closes #1187

See merge request cable-mc/cobblemon!1365
2024-12-15 01:13:26 +00:00
JordanandPolymeta 9976965673 Fix Feebas spawning 2024-12-15 01:13:26 +00:00
Hiroku 098df1a5a6 Merge branch 'dex-travelling-dimensions' into 'main'
Fix Pokédex screen getting stuck when changing dimensions or opening the battle GUI

See merge request cable-mc/cobblemon!1370
2024-12-15 01:09:47 +00:00
Guilherme PereiraandHiroku f49f34efa3 Fix Pokédex screen getting stuck when changing dimensions or opening the battle GUI 2024-12-15 01:09:47 +00:00
Hiroku eac19929c4 Merge branch 'fix-dex-animations-not-playing' into 'main'
Fix animations not playing on Pokédex

See merge request cable-mc/cobblemon!1355
2024-12-15 00:43:09 +00:00
Guilherme PereiraandHiroku 59cced5b2c Fix animations not playing on Pokédex 2024-12-15 00:43:08 +00:00
Apion f07707221f Merge branch 'implement_pokemon' into 'main'
Pokémon fixes and tweaks

Closes #1230 and #1137

See merge request cable-mc/cobblemon!1371
2024-12-14 23:57:34 +00:00
PolymetaandApion 89b89592ab Pokémon fixes and tweaks 2024-12-14 23:57:33 +00:00
Hiroku cdeb977769 Update DexInformationChangedEvent.kt 2024-12-14 23:55:43 +00:00
Gustavo Felippi PuerariandWeblate 78192c43a7 Translated using Weblate (Portuguese (Brazil))
Currently translated at 33.6% (2148 of 6391 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/pt_BR/
2024-12-14 18:41:41 +00:00
Paul a3987b433c Merge remote-tracking branch 'origin/main' 2024-12-14 22:19:51 +10:00
Paul 99de91bd7e Added optional level property to pool party providers for using molang to force a level value, closes #1244 2024-12-14 22:19:39 +10:00
Paul 4b292b1241 Less zealous on the warning logging 2024-12-14 22:16:07 +10:00
Hiroku 1e6e4d8c5f Merge branch 'moe-eats-bugs' into 'main'
Added ignore checks to prevent passive healing/revival when config values are 0

Closes #875

See merge request cable-mc/cobblemon!1372
2024-12-14 11:41:35 +00:00
MoeBoy76 9a61c3471b Added ignore checks to prevent passive healing/revival when config values are 0 2024-12-14 22:12:08 +11:00
Paul 77f7439853 Fixed brewing on neoforged 2024-12-14 14:51:01 +10:00
Segfault Guy 439161c180 Merge remote-tracking branch 'origin/main' into ihatebugtypes 2024-12-13 23:39:22 -05:00
Paul e9718b7e8b Merge remote-tracking branch 'origin/main' 2024-12-14 14:29:28 +10:00
Hiroku 4cadd4e20f Merge branch 'fix/watchdog' into 'main'
Watchdog: Possible fix for watchdog crashing

See merge request cable-mc/cobblemon!1368
2024-12-14 04:26:24 +00:00
Hiroku 17a3d86324 Update PokemonEntity.kt 2024-12-14 04:25:19 +00:00
Hiroku 48653073f5 if ( 2024-12-14 04:21:49 +00:00
Nick 82c7c03e28 Initial tests for watchdog fix 2024-12-13 20:18:13 -08:00
Nick 2d7f3257d1 Merge branch 'hiro-fix' into 'main'
I fix bugs too

Closes #1212, #1222, and #1228

See merge request cable-mc/cobblemon!1367
2024-12-14 04:16:35 +00:00
HirokuandNick bc7b4f94c2 I fix bugs too 2024-12-14 04:16:35 +00:00
Paul 7a9e9d7ced Fixed battles being startable while pokemon are busy, closes #1212 2024-12-14 13:52:19 +10:00
Paul 0f85ece16f Fixed cry sound effects playing twice for specific cases, closes #1222 2024-12-14 13:36:53 +10:00
Paul c4656e1a4e Fixed cubone alola bias not being visible, closes #1228 2024-12-14 12:57:17 +10:00
Paul 0c48a318c5 Added /runmolangscript, updated molang version 2024-12-14 12:22:25 +10:00
Paul dab89a9f8c Merge remote-tracking branch 'origin/main' 2024-12-14 11:05:55 +10:00
Paul 53fd2dba2d Fixed flows double-registering then triple-registering then quadruple-registering then- 2024-12-14 11:05:48 +10:00
Polymeta a5b15c6127 Merge branch 'more-items-tooltips' into 'main'
Add tooltips to many items

See merge request cable-mc/cobblemon!1346
2024-12-14 00:48:11 +00:00
Guilherme PereiraandPolymeta 174fb59bbb Add tooltips to many items 2024-12-14 00:48:11 +00:00
Paul 2f8bd44938 Added q.set_query for assigning new query function values, closes #1240 2024-12-14 10:36:53 +10:00
Paul 9d58c7126e Fixed set_npc_variable not initializing NPC data properly 2024-12-14 10:12:50 +10:00
Hiroku 2afd722125 Incl default return for get_npc_variable when no data exists for the NPC yet 2024-12-14 00:03:25 +00:00
Polymeta c9cfe489d6 Merge branch 'EV-Berry-Lang-fixes' into 'main'
Fixed lang files for EV lowering berries to actually be correct

See merge request cable-mc/cobblemon!1364
2024-12-13 11:23:29 +00:00
Plastered_Crab 4ee029fa54 Fixed lang files for EV lowering berries to actually be correct 2024-12-12 09:41:17 -08:00
TeggyandWeblate e2ebb32708 Translated using Weblate (Spanish)
Currently translated at 87.6% (5601 of 6391 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/es/
2024-12-11 15:53:06 +00:00
Polymeta 5b0a221ade Merge branch 'RaftFixes' into 'main'
Fixed reading speciesdata instead of formdata. Fixed rafts deploying on...

See merge request cable-mc/cobblemon!1359
2024-12-11 08:14:41 +00:00
JazzMcNadeandPolymeta af23b82ce5 Fixed reading speciesdata instead of formdata. Fixed rafts deploying on... 2024-12-11 08:14:41 +00:00
Segfault Guy b0466447cc Temp fix for missing form langs. 2024-12-10 21:59:39 -05:00
Zack the GhastandWeblate 727ff96ff8 Translated using Weblate (Portuguese (Portugal))
Currently translated at 28.9% (1851 of 6391 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/pt_PT/
2024-12-10 12:41:43 +00:00
Gustavo Felippi PuerariandWeblate 9307f957b7 Translated using Weblate (Portuguese (Brazil))
Currently translated at 32.6% (2089 of 6391 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/pt_BR/
2024-12-10 12:41:43 +00:00
TeggyandWeblate d48978f6a4 Translated using Weblate (Spanish)
Currently translated at 86.5% (5531 of 6391 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/es/
2024-12-10 12:41:42 +00:00
amo d1a8171079 resolve threads 2024-12-09 23:57:38 +00:00
amo d4b673ea38 Merge branch 'main' into dex-update-event 2024-12-09 23:54:08 +00:00
Hiroku 36e78a5af2 Merge branch 'fix-dex-quiet-cries' into 'main'
Fix quiet cries in the Pokédex

See merge request cable-mc/cobblemon!1354
2024-12-07 22:38:12 +00:00
Guilherme PereiraandHiroku 55621b01b7 Fix quiet cries in the Pokédex 2024-12-07 22:38:12 +00:00
Paul b828fe2b3a Merge remote-tracking branch 'origin/main' 2024-12-07 20:59:45 +10:00
Paul b7b10151e1 Added get_npc_variable and set_npc_variable to player functions for convenience, updated molang for flexibility with query struct nested assignments 2024-12-07 20:59:33 +10:00
amo de21b7c402 forgot me loighter 2024-12-07 04:44:27 +00:00
amo 10fe3c4362 🍋‍🟩 Chore: Add Dex data update event 2024-12-07 04:40:50 +00:00
Gustavo Felippi PuerariandWeblate aca1433595 Translated using Weblate (Portuguese (Brazil))
Currently translated at 30.8% (1969 of 6391 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/pt_BR/
2024-12-07 03:41:43 +00:00
TeggyandWeblate 082c382179 Translated using Weblate (Spanish)
Currently translated at 80.4% (5140 of 6391 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/es/
2024-12-07 03:41:42 +00:00
Test cac6ed843a Merge branch 'sterr/bugfixes' into 'main'
Adjusted portrait space detection in the Pokedex to prevent overlap

Closes #1055

See merge request cable-mc/cobblemon!1348
2024-12-06 18:32:20 +00:00
SterrezoandTest 8f5f40c360 Adjusted portrait space detection in the Pokedex to prevent overlap 2024-12-06 18:32:19 +00:00
Hiroku 0e586b4f38 Merge branch 'fix/ivs' into 'main'
Rework copy on properties, just clone fields rather than serialize + deserialize JSON

See merge request cable-mc/cobblemon!1344
2024-12-06 12:38:01 +00:00
Paul 62dd487448 Removed platform independent JSON datapack loading because Fabric has fixed the bug, closes #1184 2024-12-06 20:06:50 +10:00
Nick 04ecd9189c It would seem a particular build step was forgotten 2024-12-05 21:37:34 -08:00
Nick 55be22e942 Revert previous change, update stats differently instead 2024-12-05 21:29:13 -08:00
Hiroku f2e1b3dab4 Merge branch 'pokeedit-hidden-ability-false' into 'main'
Revert Pokémon ability to normal when hiddenAbility is false

See merge request cable-mc/cobblemon!1351
2024-12-06 00:51:21 +00:00
Paul 66f98ebf12 Added v.npc for on_player_wins and on_player_loses script hooks, v.npc to on_defeat and on_victory hooks 2024-12-05 20:43:04 +10:00
Paul c1842e42b0 Fixed run_molang script hooks not running multi-expressions, closes #1224 2024-12-05 19:14:49 +10:00
Hiroku e6c2f241d4 Merge branch 'MoreDynamicRafts' into 'main'
MoreDynamicRafts

See merge request cable-mc/cobblemon!1347
2024-12-05 08:39:13 +00:00
Segfault Guy c2d85a0cdf Battle performance, bugs, and PokemonEntity fixes. 2024-12-05 00:22:20 -05:00
JazzMcNade 0f9c282e1f Merge branch 'main' into MoreDynamicRafts 2024-12-04 21:23:45 -06:00
JazzMcNade 7bd5d77b60 Fixed naming conventions, removed some unnecessary variables. 2024-12-04 21:22:35 -06:00
Guilherme Pereira f7b4d4e65a add changelog of when hiddenability=false on pokespawn and pokeedit commands 2024-12-04 22:23:28 -03:00
Guilherme Pereira e78f403198 set pokemon ability to normal when property is false 2024-12-04 21:43:07 -03:00
Test 4ca91cc8d8 Merge branch 'pokeedit-nickname-completion' into 'main'
Add nickname completion suggestion for pokeedit and pokespawn commands

See merge request cable-mc/cobblemon!1350
2024-12-05 00:20:08 +00:00
Test 1518181f6b Merge branch 'sound' into 'main'
Move sounds + Pokedex volume adjustments + missing sound fixes

See merge request cable-mc/cobblemon!1341
2024-12-05 00:14:06 +00:00
Hiroku b915237c8d Merge branch 'more-npc-dakka' into 'main'
Even more npc dakka

See merge request cable-mc/cobblemon!1330
2024-12-04 21:52:38 +00:00
Guilherme Pereira bb41a72067 add nickname completion suggestion for properties argument type 2024-12-04 16:29:36 -03:00
Paul fbb8492c75 Added ScriptPartyProvider 2024-12-04 22:36:17 +10:00
Paul c07aef04b1 Merge remote-tracking branch 'origin/main' into more-npc-dakka 2024-12-04 22:05:11 +10:00
Paul 6ff4befb04 Possible fix for tick watchdog hang 2024-12-04 22:00:56 +10:00
Paul a858d4f532 Use emptyList default rather than null for party provider player list, update doco, corrected LookInDirectionTask's extra start conditions 2024-12-04 21:13:38 +10:00
Hiroku 28fc273b26 Merge branch 'gimmi_tower_typo_fix' into 'main'
Fixing something i found in the processor lists

See merge request cable-mc/cobblemon!1345
2024-12-04 10:47:14 +00:00
JazzMcNade fc89757a09 Tab spacing 2024-12-04 01:16:00 -06:00
JazzMcNade 243c9abfd1 Rafts can now can (un)deploy upon touching water or a solid surface. 2024-12-04 01:11:02 -06:00
Weblate 7cea5ad69e Update translation files
Updated by "Remove blank strings" add-on in Weblate.

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/
2024-12-04 00:41:50 +00:00
Zack the GhastandWeblate 0b9b5ac306 Translated using Weblate (Portuguese (Portugal))
Currently translated at 28.8% (1845 of 6391 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/pt_PT/
2024-12-04 00:41:46 +00:00
Gustavo Felippi PuerariandWeblate 8941f3079b Translated using Weblate (Portuguese (Brazil))
Currently translated at 29.1% (1866 of 6391 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/pt_BR/
2024-12-04 00:41:44 +00:00
Alexis SalgueiroandWeblate e9a0815ca6 Translated using Weblate (French)
Currently translated at 100.0% (6391 of 6391 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/fr/
2024-12-04 00:41:41 +00:00
Slippy b871645e9e Fixing something i found in the processor lists 2024-12-03 11:23:40 -06:00
Hiroku cec0ee04e0 Merge branch 'ability-patch-fix' into 'main'
Ability Patch fix

See merge request cable-mc/cobblemon!1342
2024-12-03 11:41:07 +00:00
Conan 069bc91aa1 Added fix to changelog 2024-12-03 12:39:54 +01:00
Hiroku 692a1bd6ba Merge branch 'stat-sanity' into 'main'
Make Stats#getStat use actual sane checking logic

See merge request cable-mc/cobblemon!1343
2024-12-03 11:22:35 +00:00
Paul c79916d8a0 More handy NPC presets, add player context to dynamic party molang environments, separated applied aspects from variation aspects for API 2024-12-03 21:20:31 +10:00
Nick d503d4a1eb Rework copy on properties, just clone fields rather than serialize + deserialize JSON 2024-12-02 19:10:30 -08:00
amo 3d877496b3 🍋‍🟩 Chore: why was it ever any other way 2024-12-03 02:18:33 +00:00
Conan 1e4964d80c Fixed an issue where Pokémon with their hidden ability couldn't change back to their original abilities 2024-12-02 13:41:01 +01:00
Paul a0f75dd090 Added is_chunk_loaded_at molang to level, added deeper support to json -> component deserialization 2024-12-02 09:46:52 +10:00
Sterrezo 5eceaa849c Quick fix to Mud Sport particles 2024-12-01 16:12:53 +01:00
Sterrezo 0e0233993a Merge branch 'main' into sound 2024-12-01 15:34:51 +01:00
Sterrezo 56ed5a6412 Added a sound to Kinesis 2024-12-01 15:30:47 +01:00
Hiroku 92ecaa66fa Merge branch 'power-items-tooltips' into 'main'
Fixes power items tooltips

See merge request cable-mc/cobblemon!1340
2024-12-01 09:46:08 +00:00
Guilherme Pereira 4d3e6400ab fixes power items tooltips 2024-12-01 05:30:46 -03:00
Paul f2e5ecef66 Conflicts begone 2024-12-01 17:00:03 +10:00
Paul ad9e85923a Merge remote-tracking branch 'origin/main' into more-npc-dakka
# Conflicts:
#	common/src/main/kotlin/com/cobblemon/mod/common/CobblemonNetwork.kt
2024-12-01 16:57:06 +10:00
Paul 60d0c490dd Critical typo correction 2024-12-01 12:23:23 +10:00
Paul bf461297b2 Corrected multiple little inaccuracies around molang and flows 2024-12-01 12:09:11 +10:00
Hiroku 3ec89cd84e Merge branch 'beast-rod-line-fix' into 'main'
Fix fishing line color for beast rod

See merge request cable-mc/cobblemon!1339
2024-12-01 01:50:25 +00:00
Hiroku 6452521434 Merge branch 'held-items-tooltips' into 'main'
Held items, evolutions items and candies tooltips

See merge request cable-mc/cobblemon!1318
2024-12-01 01:39:30 +00:00
Guilherme PereiraandHiroku 5cbf961ac2 Held items, evolutions items and candies tooltips 2024-12-01 01:39:30 +00:00
Hiroku 6b473cffa3 Merge branch 'dex' into 'main'
refactor pokedex item model registration, update Pokedex rendering

See merge request cable-mc/cobblemon!1323
2024-12-01 01:38:41 +00:00
Nick f353548f9e Merge branch 'TheRaftShow' into 'main'
Battle Rafts

See merge request cable-mc/cobblemon!1338
2024-12-01 01:02:38 +00:00
JazzMcNadeandNick bba995f3d2 Battle Rafts 2024-12-01 01:02:38 +00:00
Sterrezo 5965d5a81b Psychiiiiiiic 2024-12-01 01:58:23 +01:00
Sterrezo 4e02ca310d Added sounds for Ember, fixed Ember missing an impact and corrected Psychic's timing again 2024-12-01 00:44:35 +01:00
Sterrezo 3260271d3c Adjusted Psychic 2024-11-30 23:58:20 +01:00
Sterrezo a77863adab Implemented sounds for new move particles 2024-11-30 18:07:30 +01:00
Sterrezo 455cfeb894 Missing sound fixes for particles 2024-11-30 17:29:42 +01:00
Plastered_Crab 46266c08ac Fix fishing line color for beast rod 2024-11-29 21:40:47 -08:00
Nick 19aa45e0af Merge branch 'bugfixes' into 'main'
Fishing bugfixes

See merge request cable-mc/cobblemon!1337
2024-11-30 03:26:06 +00:00
Nick 0fe8ebd008 Merge branch 'Offhand-bait-fixes' into 'main'
Fix offhand bait being applied

See merge request cable-mc/cobblemon!1336
2024-11-30 03:19:34 +00:00
Sterrezo 3e393546a2 Fishing Pokemon now uses up durability 2024-11-30 01:45:13 +01:00
Plastered_Crab e5995a5491 Fix offhand bait being applied
It was being applied still even when that bait was already on the bobber.
2024-11-29 16:31:25 -08:00
Sterrezo 7de083bf4f Fixed Fishermen selling 3 Pokerod smithing templates and capped max trades 2024-11-29 23:34:39 +01:00
Test 5f7451c284 rm unused files 2024-11-29 19:13:17 +00:00
Sterrezo fd3c614c2c Pokedex sound balancing
why did mojang hardcode this
2024-11-29 14:54:29 +01:00
Zack the GhastandWeblate fe48da6277 Translated using Weblate (Portuguese (Portugal))
Currently translated at 27.3% (1750 of 6391 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/pt_PT/
2024-11-29 09:15:34 +00:00
MiaandWeblate 12c9c1c295 Translated using Weblate (German)
Currently translated at 88.8% (5679 of 6391 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/de/
2024-11-29 09:15:33 +00:00
Test 454c2c60ab merge from main 2024-11-28 17:35:37 -05:00
Test c581673ef1 Merge branch 'main' of https://gitlab.com/cable-mc/cobblemon into dex
# Conflicts:
#	common/src/main/kotlin/com/cobblemon/mod/common/client/gui/pokedex/PokedexGUI.kt
2024-11-28 17:19:53 -05:00
Test 09e29137fc check for view counter block in packet handler 2024-11-28 17:04:48 -05:00
Test fd1e5ef421 split lectern block entity into reuseable class 2024-11-28 16:38:39 -05:00
Test 8de05006f4 update dex rendering for player and blockEntities 2024-11-28 11:15:15 -05:00
Hiroku 7188978a66 Merge branch 'sound' into 'main'
Sounds for candy items + missing sound fixes + cleanup

See merge request cable-mc/cobblemon!1334
2024-11-28 11:08:28 +00:00
Hiroku f60fd26cbf Merge branch 'Lure_ball_tooltip_fix' into 'main'
Add correct Lure Ball tooltip now that fishing works :D

See merge request cable-mc/cobblemon!1335
2024-11-28 04:39:32 +00:00
Hiroku 3ba59d2165 Merge branch 'pokerod-durability-buff' into 'main'
Increase durability of Pokerods to be 256 instead of 64

See merge request cable-mc/cobblemon!1333
2024-11-28 04:24:44 +00:00
Plastered_Crab cd80598857 Add correct Lure Ball tooltip now that fishing works :D 2024-11-27 17:55:04 -08:00
Sterrezo 0978febaba Update CHANGELOG.md 2024-11-28 00:25:25 +01:00
Sterrezo bb67629fa5 Fixed Quick Attack and Paralysis missing sounds 2024-11-28 00:16:24 +01:00
Sterrezo d21039953f Update quickattack.json 2024-11-27 23:25:13 +01:00
Sterrezo 682f931f0f sounds.json fixes and duplicate asset removal 2024-11-27 23:16:00 +01:00
Plastered_Crab 3796997a12 Increase durability of Pokerods to be 256 instead of 64 2024-11-27 12:55:01 -08:00
Sterrezo b4cf49e1a8 Added a sound for using candy items
Closes a closed issue that requested sounds for candy items
2024-11-27 19:05:42 +01:00
Hiroku 2820989586 Merge branch 'ihatebugtypes' into 'main'
Ihatebugtypes

Closes #1174, #1180, and #1183

See merge request cable-mc/cobblemon!1313
2024-11-27 11:44:53 +00:00
Hiroku d37f6bc5a4 Merge branch 'pumpkins-can-move' into 'main'
re-added Pumpkaboo's moves

Closes #1202

See merge request cable-mc/cobblemon!1332
2024-11-27 11:44:23 +00:00
Hiroku 90d7fc3c2f Merge branch 'sterr/subtitles' into 'main'
Generic subtitles + bugfix

Closes #1200

See merge request cable-mc/cobblemon!1331
2024-11-27 11:44:03 +00:00
MoeBoy76 e2779c55f2 re-added Pumpkaboo's moves 2024-11-27 11:46:32 +11:00
Segfault Guy 349b4c28cc Merge remote-tracking branch 'origin/main' into ihatebugtypes 2024-11-26 13:49:07 -05:00
Sterrezo 7f2540a48f Added generic subtitles to block sounds 2024-11-26 18:02:22 +01:00
Sterrezo 367db9a368 Corrected subtitles for successful capture
Closes #1200
2024-11-26 17:53:16 +01:00
Zack the GhastandWeblate 7471b336be Translated using Weblate (Portuguese (Portugal))
Currently translated at 26.9% (1720 of 6391 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/pt_PT/
2024-11-26 12:15:28 +00:00
Paul 4f3eb7e4ba Event flows merged in and used for a few battle-related NPC presets, heaps more molang hooks 2024-11-26 21:57:55 +10:00
Hiroku c95f4cb9ad Merge branch 'implement_pokemon' into 'main'
Several fixes to some pokemon and redo of Magikarp jump forms to fit standards

Closes #1137

See merge request cable-mc/cobblemon!1329
2024-11-26 11:30:17 +00:00
Frank The FarmerandHiroku c0ccefd9b4 Several fixes to some pokemon and redo of Magikarp jump forms to fit standards 2024-11-26 11:30:17 +00:00
Nick f45a1681fa Merge branch 'pokerod-tooltip-changes' into 'main'
Add new tooltips for pokerods to show players how to add bait

See merge request cable-mc/cobblemon!1328
2024-11-25 21:09:40 +00:00
Plastered_Crab 12c820313a Add lang files for adding and removing bait tooltips 2024-11-25 13:01:28 -08:00
Nick e6b287434b Merge branch 'off-hand-fishing-bait-changes' into 'main'
Changes to how offhand bait is applied to rod

See merge request cable-mc/cobblemon!1327
2024-11-25 20:13:38 +00:00
Nick d39ee60158 Merge branch 'lucky-sea-rate-changes' into 'main'
Alter Luck of the Sea spawn bucket rates

See merge request cable-mc/cobblemon!1326
2024-11-25 20:12:05 +00:00
Plastered_Crab d405ede256 Changes to how offhand bait is applied to rod
- only 1 bait from off hand is applied
- if bait is already on the rod when applying from offhand, bait is dropped from rod before applying bait from offhand
2024-11-25 11:29:19 -08:00
Nick bbaf4332c6 Merge branch 'jumping-ancient-balls' into 'main'
Ancient Pokeball particles and animations.

See merge request cable-mc/cobblemon!1324
2024-11-25 19:20:20 +00:00
TyzillionandNick 954e690a20 Ancient Pokeball particles and animations. 2024-11-25 19:20:20 +00:00
Nick 0dda070c4c Merge branch 'sound' into 'main'
Poke Ball sound overhaul

See merge request cable-mc/cobblemon!1319
2024-11-25 19:17:41 +00:00
Plastered_Crab e855e0f1ae Alter Luck of the Sea bucket rates 2024-11-25 10:13:36 -08:00
Hiroku 0515b3204b Merge branch 'improve-dex-search' into 'main'
Add functionality to search by species, ability, or drops in dex

Closes #1129

See merge request cable-mc/cobblemon!1320
2024-11-25 12:00:28 +00:00
TestandHiroku 049c0c308a Add functionality to search by species, ability, or drops in dex 2024-11-25 12:00:27 +00:00
Hiroku e424bd76b5 Merge branch 'sterr/npc-sound' into 'main'
Click sound in NPC dialogue now plays at the correct pitch

See merge request cable-mc/cobblemon!1325
2024-11-25 03:54:50 +00:00
Sterrezo 0443aa5109 Click sound now plays at the correct pitch. That float is in fact not the volume. 2024-11-25 04:45:44 +01:00
Paul f9a3d2dc0e Merge remote-tracking branch 'origin/event-flows' into more-npc-dakka
# Conflicts:
#	common/src/main/kotlin/com/cobblemon/mod/common/Cobblemon.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/CobblemonNetwork.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/api/events/pokemon/PokemonCapturedEvent.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/api/molang/MoLangFunctions.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/data/CobblemonDataProvider.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/entity/pokemon/PokemonEntity.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/pokemon/Pokemon.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/util/MoLangExtensions.kt
2024-11-24 21:07:50 +10:00
Paul f817c18f4f Added NPC variable editing in NPC config menu 2024-11-24 21:02:38 +10:00
Test bd801b1517 refactor pokedex item model registration 2024-11-23 23:08:47 -05:00
Hiroku 0f17d30ece Merge branch 'Extreme-Tower-Makeover' into 'main'
Giving the Frozen Gimmi tower a new look & making it so Breezes sometimes...

See merge request cable-mc/cobblemon!1322
2024-11-23 10:39:20 +00:00
Hiroku f54aed0953 Merge branch 'particle-packet-expansion' into 'main'
[1.6] Expand SpawnSnowstormEntityPacket capabilties to support non-posable entities at a basic level

See merge request cable-mc/cobblemon!1309
2024-11-23 10:37:18 +00:00
Slippy 2b5a16d30f Giving the Frozen Gimmi tower a new look & making it so Breezes sometimes spawn on top instead of Evokers (Don't fall) 2024-11-23 02:11:03 -06:00
Slippy f1ed9b010e Merge branch 'main' of https://gitlab.com/cable-mc/cobblemon into 1.6-Bug-Testing 2024-11-23 01:58:17 -06:00
Paul e8dcd994be Fixed fish baits. Fished fix baits? Bished fix fates 2024-11-23 16:27:33 +10:00
Hiroku da371fd940 Merge branch 'fishingrod-crash-fix' into 'main'
Fix drowned crashing game when holding fishing rod

See merge request cable-mc/cobblemon!1321
2024-11-23 05:56:47 +00:00
mia 0cdeab0800 check livingEntity instanceof Player before casting 2024-11-22 20:14:29 -05:00
Sterrezo eca3c582aa Added sounds for Poke Balls landing on the ground during capture, updated sounds with new iterations 2024-11-22 14:32:54 +01:00
Sterrezo 8dd09a2e14 Merge branch 'main' into sound 2024-11-22 13:16:41 +01:00
Hiroku a96880b8ed Merge branch 'more-npc-dakka' into 'main'
Added panic AI for NPCs and much more molang hooking

See merge request cable-mc/cobblemon!1303
2024-11-22 10:15:33 +00:00
Hiroku 40de8b3ab9 Merge branch 'dex-fix' into 'main'
Fix dex search crash + add text cursor functionality

Closes #1185

See merge request cable-mc/cobblemon!1317
2024-11-22 08:59:37 +00:00
TestandHiroku 6eb814a7f0 Fix dex search crash + add text cursor functionality 2024-11-22 08:59:37 +00:00
Paul 2f2fd3b17e Fixed a couple of molang functions, added level support and fixes to NPC spawn files 2024-11-22 17:21:20 +10:00
Hiroku 4234f9be67 Merge branch 'fishing_particles' into 'main'
Fishing Particles

See merge request cable-mc/cobblemon!1316
2024-11-22 06:46:43 +00:00
Tyzillion f5766cdad4 Milliseconds? More like LITERAL TICKS. Lime disease... 2024-11-22 01:29:17 -05:00
Tyzillion 8c11ef9c00 System time? More like fishing time. Amiright? 2024-11-22 01:15:41 -05:00
Tyzillion 78ac8542f6 Added new particles to Poke fishing. 2024-11-22 00:51:55 -05:00
Segfault Guy 8c1d03359a Fix deserialization of IVs and EVs for PokemonProperties. 2024-11-21 22:19:01 -05:00
amo bb574e58d8 Merge branch 'main' into particle-packet-expansion 2024-11-22 00:51:23 +00:00
amo 5c3c7b4195 🍋‍🟩 Chore: Oops! v2 2024-11-22 00:50:37 +00:00
Hiroku ddec062e87 Merge branch 'experience-fix' into 'main'
Stops rewarding Pokemon EXP upon forfeiting NPC battles.

See merge request cable-mc/cobblemon!1278
2024-11-22 00:07:51 +00:00
Conan 3322f3ffb6 Changelog addition 2024-11-22 01:05:00 +01:00
Hiroku ab1ec11c26 Merge branch 'sterr/bugfixes' into 'main'
Sound and music bugfixes

Closes #1161 and #1172

See merge request cable-mc/cobblemon!1299
2024-11-21 23:49:19 +00:00
Hiroku 36aaa97029 Merge branch 'small-bugfixes' into 'main'
Small bugfixes

Closes #1099 and #1156

See merge request cable-mc/cobblemon!1284
2024-11-21 23:48:39 +00:00
Hiroku 6b3443fbd2 Merge branch 'berries-tooltips' into 'main'
Add tooltips for Pomeg, Tamato, Grepa, Kelpsy, Hondew and Qualot berries

See merge request cable-mc/cobblemon!1308
2024-11-21 23:46:56 +00:00
Hiroku 268a1ab311 Merge branch 'feed-display-case-from-underneath' into 'main'
Add support for feeding display case items from underneath

Closes #1177

See merge request cable-mc/cobblemon!1307
2024-11-21 23:42:45 +00:00
Paul 40957b6eac Added defaults to new PermissionValidator functions 2024-11-22 09:37:12 +10:00
Sterrezo d67be68b4b Changelog, updated break out animation (thanks Torch!), new break out sound for ancient Pokeballs 2024-11-22 00:29:52 +01:00
Hiroku f6f34a2b10 Merge branch 'npc-no-pain-no-gain' into 'main'
Added NPC properties: isInvulnerable, isLeashable, and allowProjectileHits. (no pain no gain)

Closes #1179

See merge request cable-mc/cobblemon!1306
2024-11-21 23:18:28 +00:00
Hiroku b2f71d305f Update SpawnSnowstormEntityParticleHandler.kt 2024-11-21 23:12:05 +00:00
Hiroku 51a8c31997 Merge branch 'npc-kill-command' into 'main'
Added a command to delete NPCs

See merge request cable-mc/cobblemon!1315
2024-11-21 23:10:40 +00:00
Conan 67ae5ff155 Added a command to delete NPCs 2024-11-22 00:06:07 +01:00
Hiroku 9e0cf03d8e Merge branch 'fix-mega-event-spelling-error' into 'main'
Fix spelling error in mega evolution event

See merge request cable-mc/cobblemon!1314
2024-11-21 22:13:25 +00:00
Conan 6a076d36f9 "isInvincible" != "isInvulnerable" 2024-11-21 20:28:54 +01:00
Sterrezo 4314a0b506 Major rework of Pokeball sound implementation and new sounds 2024-11-21 20:18:28 +01:00
amo 77490b5084 🍋‍🟩 Chore: Oops! 2024-11-21 14:15:44 +00:00
Segfault Guy 109eecd4fe Merge remote-tracking branch 'origin/main' into ihatebugtypes 2024-11-20 23:00:34 -05:00
Segfault Guy d6353aa2c7 Remedy for remedy. 2024-11-20 22:44:04 -05:00
Test fd0e741a25 update ui, fix renders in dex from clipping into background 2024-11-20 22:39:50 -05:00
Segfault Guy b0e0a06e9a Fix battle music race condition on forceBattle. 2024-11-20 21:00:16 -05:00
Conan 1c569ac5cf Added property descriptions 2024-11-20 17:01:14 +01:00
Guilherme Pereira 5ff5de8d14 re-add tooltip 'Cannot be eaten by holder' on another line for pomeg, tamato, grepa, kelpsy, hondew and qualot berries 2024-11-20 07:58:41 -03:00
Hiroku 881e1dc1a6 Merge branch 'hatenna-line-files-wrong-dex-numbers' into 'main'
Rename Hatenna line folders to match correct pokedex numbers

Closes #1173

See merge request cable-mc/cobblemon!1310
2024-11-20 09:20:37 +00:00
Hiroku 09b9fade87 Merge branch 'feature/fix-gui-mixin' into 'main'
fix gui mixin to prevent accidental 3rd person HUD disappearances

See merge request cable-mc/cobblemon!1312
2024-11-20 09:18:25 +00:00
Segfault Guy acd3b7cade Fix activation messages on ability suppressing moves. 2024-11-19 22:28:48 -05:00
Polymeta 482a0015bc fix gui mixin to prevent accidental 3rd person HUD disappearances
Signed-off-by: Polymeta <40173118+Polymeta@users.noreply.github.com>
2024-11-20 02:13:40 +00:00
Guilherme Pereira b881c96630 add changelog for feeding display case items from underneath fix 2024-11-19 20:09:25 -03:00
Hiroku 79cd1f5224 Merge branch 'init-events' into 'main'
emit(Unit), not just emit(), otherwise theres no data to post, duh

See merge request cable-mc/cobblemon!1311
2024-11-19 21:18:01 +00:00
Xander Forrest f369877c10 emit(Unit), not just emit(), otherwise theres no data to post, duh 2024-11-19 18:52:03 +00:00
Guilherme Pereira 1f1ff0e4fd rename hatenna, hattrem and hatterene folders to match correct pokedex numbers 2024-11-19 13:55:28 -03:00
amo 0a34e51e07 🍋‍🟩 Chore: Changelog 2024-11-19 15:51:45 +00:00
amo 741530eb43 🍋‍🟩 Feature: Expand SpawnSnowstormEntityParticleHandler to support non-bedrock entities at a very basic level 2024-11-19 15:44:02 +00:00
Guilherme Pereira 6c9c5a93f1 add tooltips for pomeg, tamato, grepa, kelpsy, hondew and qualot berries 2024-11-19 11:43:35 -03:00
Guilherme Pereira ddbf6d7345 add support for feeding display case items from underneath 2024-11-19 09:52:38 -03:00
Hiroku 0da09c767c Merge branch 'evolution_tweaks' into 'main'
Edited the obscuring evolution particles to better obscure pokemon based on hitbox volume and scale.

See merge request cable-mc/cobblemon!1305
2024-11-19 09:36:18 +00:00
Conan fb39ff8657 Added NPC properties: isInvulnerable, isLeashable, and allowProjectileHits. 2024-11-19 08:41:10 +01:00
Conan dd516c153e Added NPC properties: isInvulnerable, isLeashable, and allowProjectileHits. 2024-11-19 08:39:14 +01:00
Tyzillion 739d31a9ca I'M LOSING MY MIND... Anyways, more tweaks to the obscure particle. 2024-11-18 23:45:22 -05:00
Tyzillion a5675aedcb Tweaked the formula further to better account for middle stage evos. 2024-11-18 22:46:00 -05:00
Tyzillion 196bf42fb6 Tweaked obscuring molang formula to better obscure Pokemon based on hitbox volume and scale. 2024-11-18 22:02:34 -05:00
Test 1d01a2bf1f fix species name not being translated when scanned 2024-11-18 19:23:28 -05:00
Natchakot ChuchokjatupornandWeblate 948f299f8f Translated using Weblate (Thai)
Currently translated at 90.1% (5764 of 6391 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/th/
2024-11-18 21:41:42 +00:00
Paul ce6087f368 Added panic AI for NPCs and much more molang hooking 2024-11-18 13:28:50 +10:00
mia f706dcda26 clarify ItemPropertiesMixin inject location 2024-11-17 20:45:59 -05:00
Segfault Guy 8e46a55cbd Merge remote-tracking branch 'origin/main' into ihatebugtypes 2024-11-17 19:12:41 -05:00
Hiroku d3ae4cd3e7 Merge branch '1.6-spawns' into 'main'
Updated spawn files. Edited ocean_monument preset. Edited is_lush, is_ocean,...

See merge request cable-mc/cobblemon!1293
2024-11-17 09:25:02 +00:00
Hiroku b41b496b80 Merge branch 'bugfix/dexo-fixo' into 'main'
Fixed dex errors caused by /giveallpokemon and other random catches & command permission

See merge request cable-mc/cobblemon!1301
2024-11-17 09:17:30 +00:00
Hiroku 9cd3ded705 Merge branch 'summary-updates' into 'main'
Summary updates

See merge request cable-mc/cobblemon!1300
2024-11-17 09:15:50 +00:00
TestandHiroku ca4b50d727 Summary updates 2024-11-17 09:15:50 +00:00
Paul f6bc3f662a PokedexCommand permission tweak 2024-11-17 13:23:07 +10:00
Paul 7ab621e5b9 Fixed dex errors caused by /giveallpokemon and other random catches 2024-11-17 13:22:55 +10:00
plastered_crab 4e63cb0bb3 Remove Tympole, Palpitoad, Seismitoad spawn pool world files 2024-11-16 18:15:07 -08:00
plastered_crab 671c7adb05 Tweak incorrect data for Magikarp and Spiritomb spawns 2024-11-16 18:13:14 -08:00
Sterrezo edbe539537 Merge branch 'main' into sterr/bugfixes 2024-11-17 03:05:56 +01:00
Sterrezo e20728faa0 Made owned shiny ambient sounds actually audible 2024-11-17 03:05:28 +01:00
Sterrezo 5a2f948acb Fixed music not playing when fishing or in npc battles
Doozy. Basically, using forceBattle from PokemonEntity.kt makes InitializeInstruction.kt send a packet with battle music before battleTheme is assigned in PlayerBattleActor.kt.
There's likely a more sophisticated way to fix this, but this works.
Closes #1172 and #1161
2024-11-17 03:04:00 +01:00
Hiroku 8a1faf3270 Merge branch 'apion-bugfix' into 'main'
Fix issue with evo progression not allowing 0.

See merge request cable-mc/cobblemon!1298
2024-11-16 22:55:55 +00:00
Hiroku d0b148a91a Merge branch 'cc-compat' into 'main'
Set cobblemon data version on genned chunks

See merge request cable-mc/cobblemon!1297
2024-11-16 22:52:51 +00:00
apion f6f88f5eef Revert "Added additional checks"
This reverts commit 3f36624ba7.
2024-11-16 16:19:48 -05:00
apion 3f36624ba7 Added additional checks 2024-11-16 15:22:08 -05:00
apion 7e256e8381 Fix issue with evo progression not allowing 0. 2024-11-16 12:24:59 -05:00
apion ad1aa9ad47 Licenses :( 2024-11-16 11:31:11 -05:00
apion b4e403a701 Removed unnecessary inject 2024-11-16 11:27:00 -05:00
apion 08557913d8 Set cobblemon data version on genned chunks 2024-11-16 11:22:42 -05:00
Hiroku 830c409a06 Merge branch 'non-pushable-npcs' into 'main'
Added a flag to prevent NPCs from being pushed.

See merge request cable-mc/cobblemon!1281
2024-11-16 12:59:34 +00:00
Hiroku 5e2ef6b5fb Merge branch 'main' into 'non-pushable-npcs'
# Conflicts:
#   common/src/main/kotlin/com/cobblemon/mod/common/util/DataKeys.kt
2024-11-16 12:59:16 +00:00
Conan a05f4edc82 Added a flag to prevent NPCs from being pushed (part 3). 2024-11-16 12:28:07 +01:00
Paul 97a3dc4d61 Treat NPC skill as a proper optional property on the entity instead of duplicating class data 2024-11-16 14:22:40 +10:00
Hiroku 768789d998 Merge branch 'feature/small-fixes' into 'main'
no more caffeine for shouldered pokemon

Closes #1146 and #1162

See merge request cable-mc/cobblemon!1277
2024-11-16 04:14:48 +00:00
PolymetaandHiroku bfa58e9fb9 no more caffeine for shouldered pokemon 2024-11-16 04:14:48 +00:00
Hiroku 9a514477c5 Merge branch 'trading-display-names' into 'main'
Display correct usernames in the TradeGUI

Closes #1168

See merge request cable-mc/cobblemon!1294
2024-11-16 04:12:16 +00:00
Paul 7623452f4a Fixed spectating not being an option in interact wheel (lol) 2024-11-16 13:47:15 +10:00
Test 72635d0f2f genericize example names 2024-11-15 22:39:11 -05:00
Paul 34e581a470 Merge remote-tracking branch 'origin/main' 2024-11-16 13:09:28 +10:00
Paul 5444d67c21 Added heaps of documentation on brain AI stuff for NPCs 2024-11-16 13:09:09 +10:00
Sterrezo 4c8c0fd063 Shiny Pokemon now play the shiny sendout sound when breaking out of a Pokeball instead of the notification 2024-11-16 03:01:07 +01:00
Sterrezo 73209ab6b5 Shiny notification and owned ambient particles no longer play in spectator 2024-11-16 02:35:09 +01:00
Hiroku 539331bdc7 Merge branch 'bait-tooltip-fixes' into 'main'
Changed fishing bait to use a codec instead of nbt stuff. Fixed issue where...

See merge request cable-mc/cobblemon!1296
2024-11-15 22:37:26 +00:00
apion 0d0598d68c Changed fishing bait to use a codec instead of nbt stuff. Fixed issue where bait tooltips don't work on servers 2024-11-15 06:06:03 -05:00
Conan 08d621ca5e Display correct usernames in the TradeGUI 2024-11-15 00:03:41 +01:00
mia 6dfb1323b7 cleanup if statement logic 2024-11-14 08:49:01 -05:00
mia 973e730b48 license + remove unused imports 2024-11-14 08:42:36 -05:00
Natchakot ChuchokjatupornandWeblate 5c075d7d29 Translated using Weblate (Thai)
Currently translated at 88.7% (5671 of 6391 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/th/
2024-11-13 22:41:55 +00:00
mia bbb06677b9 fix: uncast rods (both pokerods and vanilla) appearing as cast when dual-wielding 2024-11-13 09:19:20 -05:00
mia 8a5279741d fix bobber line being drawn incorrectly sometimes (fixes #1099) 2024-11-13 09:18:30 -05:00
Segfault Guy fc8b6fb54b Fix illusion not copying caught ball. 2024-11-12 22:09:36 -05:00
Weblate 854f02d34f Update translation files
Updated by "Remove blank strings" add-on in Weblate.

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/
2024-11-12 21:41:59 +00:00
Natchakot ChuchokjatupornandWeblate a3c3fa12e5 Translated using Weblate (Thai)
Currently translated at 87.1% (5567 of 6391 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/th/
2024-11-12 21:41:53 +00:00
Alexis SalgueiroandWeblate 3527da02a6 Translated using Weblate (French)
Currently translated at 100.0% (6391 of 6391 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/fr/
2024-11-12 21:41:48 +00:00
MiaandWeblate 96f537fa27 Translated using Weblate (German)
Currently translated at 87.5% (5596 of 6391 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/de/
2024-11-12 21:41:45 +00:00
mia 9e22b662a4 remove duplicate sand_attack sounds and re-add to particles (fixes #1156) 2024-11-12 15:23:22 -05:00
Conan d731bde915 Added a flag to prevent NPCs from being pushed (part 2). 2024-11-12 12:48:34 +01:00
Conan 6ecdf25821 Added a flag to prevent NPCs from being pushed. 2024-11-12 03:09:28 +01:00
Conan 77c3f12634 Stops rewarding Pokemon EXP upon forfeiting NPC battles. 2024-11-11 18:52:35 +01:00
Segfault Guy d13d3fb137 licenses? who cares. 2024-11-10 21:43:51 -05:00
Segfault Guy f436b4a738 Merge remote-tracking branch 'origin/main' into ihatebugtypes 2024-11-10 21:43:00 -05:00
Segfault Guy 9e1a1c957b Tweak scheduler functions to work with new TickRateManager changes. 2024-11-10 21:20:59 -05:00
Segfault Guy e04155094b Fix trade parties being mirrored. 2024-11-10 21:03:24 -05:00
Segfault Guy 188115bf15 Boost effects will only play if stat stages change. 2024-11-10 20:55:35 -05:00
Segfault Guy 1d99037005 casting sounds are started by the client on bobber spawn. please dont start them on the server. 2024-11-10 15:47:07 -05:00
Natchakot ChuchokjatupornandWeblate e9f58df359 Translated using Weblate (Thai)
Currently translated at 84.1% (5381 of 6391 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/th/
2024-11-09 21:29:17 +00:00
Adam IdriciandWeblate 6885569f9e Translated using Weblate (French)
Currently translated at 100.0% (6391 of 6391 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/fr/
2024-11-09 21:29:15 +00:00
Alexis SalgueiroandWeblate 601927406c Translated using Weblate (French)
Currently translated at 100.0% (6391 of 6391 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/fr/
2024-11-09 21:29:15 +00:00
Natchakot ChuchokjatupornandWeblate 347b0bfa37 Translated using Weblate (Thai)
Currently translated at 81.4% (5206 of 6391 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/th/
2024-11-07 23:47:02 +00:00
Alexis SalgueiroandWeblate efa63b105f Translated using Weblate (French)
Currently translated at 100.0% (6391 of 6391 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/fr/
2024-11-07 23:47:01 +00:00
Adam IdriciandWeblate 18d8c19df7 Translated using Weblate (French)
Currently translated at 100.0% (6391 of 6391 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/fr/
2024-11-07 23:47:01 +00:00
Natchakot ChuchokjatupornandWeblate 8d7c92f30e Translated using Weblate (Thai)
Currently translated at 80.9% (5173 of 6391 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/th/
2024-11-07 22:41:43 +00:00
Alexis SalgueiroandWeblate 4e7b7d8d59 Translated using Weblate (French)
Currently translated at 96.6% (6179 of 6391 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/fr/
2024-11-07 22:41:41 +00:00
Felipe Bermudes OrmeñoandWeblate 1213fc9145 Translated using Weblate (Spanish (Mexico))
Currently translated at 30.5% (1954 of 6391 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/es_MX/
2024-11-07 22:41:40 +00:00
Adam IdriciandWeblate 071038dc09 Translated using Weblate (French)
Currently translated at 96.6% (6176 of 6391 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/fr/
2024-11-04 12:28:48 +00:00
Weblate 2688e37f77 Update translation files
Updated by "Remove blank strings" add-on in Weblate.

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/
2024-11-03 22:31:01 +00:00
阿鱼andWeblate e8a9ea1185 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (6391 of 6391 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/zh_Hans/
2024-11-03 22:30:58 +00:00
Alexis SalgueiroandWeblate 4770c273f9 Translated using Weblate (French)
Currently translated at 96.3% (6159 of 6391 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/fr/
2024-11-03 22:30:55 +00:00
Adam IdriciandWeblate 0e2e42b826 Translated using Weblate (French)
Currently translated at 96.3% (6159 of 6391 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/fr/
2024-11-03 22:30:54 +00:00
GottvaterNougatKoenigandWeblate de819828ce Translated using Weblate (German)
Currently translated at 87.5% (5597 of 6391 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/de/
2024-11-03 22:30:53 +00:00
MiaandWeblate fed34e9b98 Translated using Weblate (German)
Currently translated at 87.5% (5597 of 6391 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/de/
2024-11-03 22:30:53 +00:00
Paul a7e6e638fe Added run_command molang function to general query structs and player structs 2024-05-20 09:10:04 +10:00
Paul 9ef3ea2932 Use context for flows because it's cooler, added more functions to pokemon related molang 2024-05-19 19:08:56 +10:00
Paul 38dcee3327 Merge remote-tracking branch 'origin/sega_bass_pro_fishing_2' into event-flows
# Conflicts:
#	common/src/main/kotlin/com/cobblemon/mod/common/CobblemonNetwork.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/entity/pokeball/EmptyPokeBallEntity.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/util/MoLangExtensions.kt
2024-05-19 11:27:18 +10:00
Paul 12b92d3f35 Added flow datapackable thing 2024-02-24 11:58:57 +10:00
Paul dacfb4f1ff Merge branch 'npcs' into event-flows
# Conflicts:
#	common/src/main/kotlin/com/cobblemon/mod/common/entity/pokeball/EmptyPokeBallEntity.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/util/MoLangExtensions.kt
2024-02-24 10:02:26 +10:00
Paul 4086ba73d3 Some structs for things 2024-02-24 09:59:27 +10:00
2397 changed files with 86430 additions and 47174 deletions
+148 -29
View File
@@ -3,23 +3,155 @@ image: amazoncorretto:21
before_script:
- export GRADLE_USER_HOME=`pwd`/.gradle
# TODO add client reference test process, search for import com.cobblemon.mod.common.client
stages:
- preprocessing
- packsquash
- replaceresources
- build
- deploy
#TODO add client reference test process, search for import com.cobblemon.mod.common.client
check_assets_cache:
stage: preprocessing
script:
- echo "Checking if cached hash matches current hash"
# Calculate the current hash
- find common/src/main/resources/assets common/src/main/resources/data -type f -exec sha256sum {} + | sort -k 2 | sha256sum > current_hash.txt
- echo "Current hash:"
- cat current_hash.txt
# Check for the existence of the previous hash
- if [[ -f assets_data_hash.txt ]]; then
echo "Previous cached hash found:";
cat assets_data_hash.txt;
if cmp -s assets_data_hash.txt current_hash.txt; then
echo "Hashes match, skipping PackSquash";
rm -f run_packsquash.flag || true;
else
echo "Hashes differ, PackSquash needed";
touch run_packsquash.flag;
fi;
else
echo "No cached hash found, marking PackSquash as required";
touch run_packsquash.flag;
fi
# Save the current hash for future runs
- echo "Saving current hash to cache";
- cp current_hash.txt assets_data_hash.txt
artifacts:
paths:
- current_hash.txt
- assets_data_hash.txt
- run_packsquash.flag
expire_in: 7 days
cache:
key: "cache-${CI_COMMIT_REF_NAME}"
paths:
- assets_data_hash.txt
- ./compressed_pack.zip
setup_resource_pack:
stage: preprocessing
script:
- echo "Setting up fake resource pack"
- mkdir ./fake_resource_pack
- cp -r common/src/main/resources/assets common/src/main/resources/data ./fake_resource_pack/
- echo '{"pack":{"pack_format":34,"description":"Fake Cobblemon Pack"}}' > ./fake_resource_pack/pack.mcmeta
artifacts:
paths:
- ./fake_resource_pack/
expire_in: 7 days
setup_packsquash:
stage: preprocessing
script:
- echo "Installing wget & unzip"
- yum install -y wget unzip
- echo "Downloading PackSquash"
- wget https://github.com/ComunidadAylas/PackSquash/releases/download/v0.4.0/PackSquash.CLI.executable.x86_64-unknown-linux-musl.zip
- unzip PackSquash.CLI.executable.x86_64-unknown-linux-musl.zip -d ./packsquash_bin
- echo "Creating PackSquash options.toml"
- |
cat <<EOF > ./options.toml
pack_directory = "./fake_resource_pack/"
output_file_path = "./compressed_pack.zip"
zip_spec_conformance_level = "high"
['**/*?.ogg']
transcode_ogg = false
two_pass_vorbis_optimization_and_validation = false
sampling_frequency = 999999
empty_audio_optimization=false
EOF
artifacts:
paths:
- ./packsquash_bin/
- ./options.toml
expire_in: 7 days
default:
artifacts:
expire_in: 7 days
run_packsquash:
stage: packsquash
dependencies:
- check_assets_cache
- setup_resource_pack
- setup_packsquash
script:
- ls -l
- if [[ ! -f ./compressed_pack.zip || -f run_packsquash.flag ]]; then
echo "Running PackSquash";
chmod +x ./packsquash_bin/packsquash;
./packsquash_bin/packsquash ./options.toml;
else
echo "Skipping PackSquash; no changes detected and compressed pack exists";
fi
cache:
key: "cache-${CI_COMMIT_REF_NAME}"
policy: pull-push
paths:
- assets_data_hash.txt
- ./compressed_pack.zip
artifacts:
paths:
- ./compressed_pack.zip
replace_resources:
stage: replaceresources
dependencies:
- run_packsquash
script:
- echo "Installing unzip"
- yum install -y unzip
- echo "Unzipping compressed pack"
- mkdir temp_unpack
- unzip ./compressed_pack.zip -d temp_unpack
- echo "Removing original assets and data"
- rm -rf common/src/main/resources/assets
- rm -rf common/src/main/resources/data
- echo "Replacing assets and data"
- mv temp_unpack/assets common/src/main/resources/
- mv temp_unpack/data common/src/main/resources/
artifacts:
paths:
- common/src/main/resources/
build:
stage: build
only:
- branches@cable-mc/cobblemon
dependencies:
- replace_resources
script:
- export GRADLE_OPTS="-Xmx4G -Xms4G"
- chmod +x ./gradlew
- ./gradlew build
cache:
key: "$CI_COMMIT_REF_NAME"
policy: push
artifacts:
paths:
- neoforge/build/libs
- fabric/build/libs
@@ -28,39 +160,26 @@ publish:
stage: deploy
dependencies:
- build
cache:
key: "CI_COMMIT_REF_NAME"
policy: pull
paths:
- neoforge/build/libs/*.jar
- fabric/build/libs/*.jar
rules:
- if: '$CI_COMMIT_BRANCH == "main"'
- if: '$CI_PROJECT_PATH == "cable-mc/cobblemon" && $CI_COMMIT_BRANCH == "main"'
script:
- export GRADLE_OPTS="-Xmx4G -Xms4G"
- chmod +x ./gradlew
- ./gradlew publish
# Separate step to deploy the artifacts, save Norry the headache of keeping even more shit around
deploy:
stage: deploy
dependencies:
- build
when: manual
cache:
key: "$CI_COMMIT_REF_NAME"
policy: pull
artifacts:
paths:
- neoforge/build/libs/*.jar
- fabric/build/libs/*.jar
script:
deploy_artifacts:
stage: deploy
dependencies:
- build
script:
- echo "Collecting artifacts..."
- mv neoforge/build/libs/*+*.jar ./
- mv fabric/build/libs/*+*.jar ./
- find neoforge/build/libs/ -type f -name "*.jar" | grep -vE "dev-shadow|sources|javadoc" | xargs -I {} mv {} ./
- find fabric/build/libs/ -type f -name "*.jar" | grep -vE "dev-shadow|sources|javadoc" | xargs -I {} mv {} ./
- for f in *.jar; do mv "$f" "$(echo "$f" | sed s/+/b$CI_PIPELINE_IID+/)"; done
artifacts:
expire_in: 28 days
paths:
- ./*.jar
# - neoforge/build/libs/*+*.jar
# - fabric/build/libs/*+*.jar
+198 -90
View File
@@ -1,58 +1,142 @@
# Changelog
## [1.6.0 - The Bass Pro Fishing Update (Month Xth, 2024)](#1-6-0)
## [1.6.1 (Release TBD)](#1-6-1)
### Additions
- Added config setting `maxPokedexScanningDetectionRange` to control from what distance the player can scan Pokémon using the Pokédex.
- Added the `is_standing_on_blocks(depth, blocks...)` MoLang function, which returns whether the specified entity is standing on a specific block or set of blocks. Example usage: `q.is_standing_on_blocks(2, minecraft:sand)`
- Added config setting `hideUnimplementedPokemonInThePokedex` which hides unimplemented Pokémon from the Pokédex when set to true.
- Added molang particle queries for getting distance to targeted entities.
- Added debug renderer for poseable entity locators.
- Added `baseScale` property to NPCs.
- Added the player to `PokerodReelEvent`.
- Pokédex and Dialogue API screens now close when the inventory keybind is pressed.
- Added Galarica Nuts, used for crafting Galarica Cuffs and Wreaths. Dropped from certain Pokémon.
- Added specific compatibility with Repurposed Structures. (Thank you, TelepathicGrunt!)
### Changes
- Pokémon will now be dynamically revealed to the Pokédex as they're seen instead of revealing entire parties at the end of battle regardless.
- Unseen wild Pokémon will update their name from '???' to their real name as soon as a battle starts to reflect the battle UI showing the actual species name.
- Pokémon under the illusion effect will reveal their disguise to the Pokédex first and then the base Pokémon once the disguise is broken.
### Fixes
- Fixed Pokédex sometimes crashing when switching forms.
- Fixed Pokédex interface not transitioning out when closed.
- Fixed texture dimensions for the interact interface.
- Fixed crash related to Tom's Simple Storage mod and Fossil Machine.
- Fixed not being able to retrieve a fossil from the Fossil Machine with an empty hand.
- Fixed Pokémon being collidable while being captured by a Poké Ball.
- Fixed `full_party`, `own_zangoose_seviper`, `use_revive` and `use_candy` Advancement triggers.
- Fixed `healing_machine` Advancement by using the correct 1.21 trigger.
- Fix Display Cases not dropping items if destroyed through explosions.
- Fixed an issue where the first Pokémon in the pastured Pokémon list clipped into the interface.
- Fixed all Pokémon facing South on spawn.
- Parametric particle motion now works.
- Event spawned particles now work.
- Particles can now have independent coordinate spaces.
- Fixed bait being consumed when not reeling in any Pokémon.
- Fixed Miltank milk magically disappearing out of your bucket.
- Fixed Pokémon nicknames migrating from 1.5.2 not being displayed properly.
- Fixed capitalization in one of our config fields, but allowing typo'd version to still be valid.
- Fixed Poké Rods not working if lure or luck of the sea enchantments get removed by other mods.
- Fixed crashes related to Pokémon when they are ready to evolve while holding an enchanted item.
- Fixed crashes that sometimes occur when evolving Nincada.
- Fixed plants not being compostible on NeoForge.
- Fixed hide UI (F1 key) not hiding the party overlay.
- Fixed NPC MoLang command `player_lose_command` not working.
- Corrected misaligned tooltips with editboxes in the NPC editor screen.
- Fixed Pokémon riding two boats when attempting to deploy a platform on water.
- Made berry trees be shearable by dispenser blocks.
- Fixed the summary screen showing there's experience to reach the next level when at level cap.
- Fixed Pokémon forgetting moves when evolving on specific cases.
- Fixed Adorn compatibility, including improvements when using JEI/REI (Apricorn items now show up under the collapsed entries rather than standalone).
- Fixed error message appearing on battle log when using Solar Beam with Sunny Day.
- Fixed Pokémon Model offsets for larger species.
- Fixed `/pokedex grant all` command not giving male/female/shininess completion for some Pokémon.
- Fixed `/pokedex grant only` and `/pokedex remove only` not respecting the form parameter passed.
- Fixed variant forms appearing incorrectly in the Pokédex when the normal form had not been unlocked.
- Fixed Pokémon occasionally being shot into the sky during battle.
- Fixed NPC editing GUI not updating aspects until a game restart.
- Fix some users being unable to open their PC if a Pokémon in said PC had a lot of pp raises beyond normal bounds
- Fix some color variants (dubwool, conkeldurr and undyed wooloo) missing in the Pokédex
- Fix invalid species or held_items causing Players to not be able to load into their world anymore (commonly happening after removing addons/mods)
- Fixed Wooloo variants not being automatically registered in the owner's Pokédex when dyed.
- Fixed Vivichoke Dip and Leek and Potato Stew not returning a bowl upon consumption.
- Fixed Fossil Restoration Machine not accepting Hay Bales.
- Fixed Potion items so that they no longer apply over double their intended healing value.
### Molang & Datapacks
- Added flows for:
- `forme_change`: Triggered when a Pokémon changes form in battle.
- `mega_evolution`: Triggered when a Pokémon mega evolves in battle. (Note: Third party mods are required for this feature currently)
- `zpower_used`: Triggered when a Pokémon uses a Z-Power move in battle. (Note: Third party mods are required for this feature currently)
- `terastallization`: Triggered when a Pokémon terastallizes in battle. (Note: Third party mods are required for this feature currently)
- `battle_fainted`: Triggered when a Pokémon faints in battle.
- `battle_fled`: Triggered when a Player flees from battle.
- `battle_started_pre`: Triggered when a battle starts. Cancelable!
- `battle_started_post`: Triggered when a battle starts.
- `apricorn_harvested`: Triggered when an apricorn is harvested.
- `thrown_pokeball_hit`: Triggered when a thrown Pokéball hits a Pokémon.
- `level_up`: Triggered when a Pokémon levels up.
- `pokemon_fainted`: Triggered when a Pokémon faints.
- `pokemon_gained`: Triggered when a Player gains a Pokémon.
- Added molang functions:
- For Pokémon:
- `pokemon.apply(PokemonProperties)`: Applies the given properties to the Pokémon.
- `pokemon.owner`: Returns the owner of the Pokémon or 0.0 if there is no owner or they are not online.
## [1.6.0 - The Record Catch Update (December 25th, 2024)](#1-6-0)
#### "Now that there's a fishing mechanic, the mod is actually good!"
### Additions
- Added the Poké Dex as a craftable item.
- Poké Dexes can be placed on lecterns.
- Added Pokémon (and item) fishing using modified fishing rods - Poké Rods! You'll need a Poké Rod smithing template, a fishing rod, and some type of Poké Ball. Each Poké Ball makes a differently themed rod. Why not?
- Added the Pokédex as a craftable item that can be placed on lecterns.
- Added Pokémon (and item) fishing using modified fishing rods - Poké Rods! You'll need a Poké Rod smithing template, a fishing rod, and some type of Poké Ball. Each Poké Ball makes a differently themed rod because it's cool.
- Added Lure Ball functionality, increasing the catch rate of Pokémon that were caught on a fishing rod.
- Added Repeat Ball functionality, increasing the catch rate of Pokémon that are already registered as caught in a player's Pokédex.
- Added property chaining support for duplicate CustomPokemonPropertyType elements.
- Added flat level battling with options to set all Pokemon to level 50, 100, or 5 for the duration of a battle. No experience or EVs are granted for a flat battle.
- Added `aspect` and `unaspect` PokemonProperty arguments (which also includes commands such as `/pokemonedit`, `/spawnpokemon`, and `/givepokemon`) to allow forcing or un-forcing an aspect on a Pokémon.
- Added `type` alternatively `elemental_type` PokemonProperty argument, this is only used for filtering and is not applied to Pokémon. Example `type=fire` would be true for Charmander but false for Squirtle.
- Added flat level battling with options to set all Pokémon to level 50, 100, or 5 for the duration of a battle. No experience or EVs are granted for a flat battle.
- Added support for Double Battles, Triple Battles, and Multi-battles.
- Added raft platforms for non-swimming, non-flying Pokémon to stand on during battles that take place on the water's surface (Flying Pokémon will fly over water in battle, and water breathing Pokémon will swim in water during battle).
- Added smarter send-out positions for Pokémon in battle. They should get in your way less!
- CriticalCaptures and Pokédex progress capture multiplier now work with the Pokédex.
- Added extra visuals to early berry growth stages.
- Moves impacted by the abilities Pixelate, Refrigerate, Aerilate, Galvanize, and Normalize now display as their altered typing.
- Added Polished Tumblestone and Tumblestone Brick block sets from Tumblestone, Black Tumblestone, and Sky Tumblestone.
- Added Metronome, Protective Pads, Punching Glove, Room Service, Scope Lens, Shed Shell, Terrain Extender, Throat Spray, Utility Umbrella, Wide Lens, and Zoom Lens held items
- Added particles for moves: Watersport, Mud Sport, and Psychic.
- Added Fire, Water, Thunder, Leaf, Ice, Sun, Moon, Shiny, Dawn, and Dusk Stone storage blocks.
- Added Eject Pack, Metronome, Protective Pads, Punching Glove, Room Service, Scope Lens, Shed Shell, Terrain Extender, Throat Spray, Utility Umbrella, Wide Lens, and Zoom Lens held items
- Added `stonjourner_henge_ruins`, `luna_henge_ruins`, and `sol_henge_ruins` structures.
- Added a `battleInvulnerability` gamerule to make players invulnerable to any damage during a battle.
- Added a `mobTargetInBattle` gamerule to exclude players from being targeted by mobs during a battle.
- Added battle log messages for switching out Pokémon.
- Added Evolution particles and sounds for Pokémon that are sent out when evolution is started.
- Added a Nurse profession that can be unlocked by having villagers claim a healing machine block.
- Added pokecenters to all 5 village types.
- Added a `natural` block state property for the healing machine block; when property is set to true, the block will have a different texture and drop an iron ingot instead of itself.
- New config setting `displayEntityNameLabel` and `displayEntityLabelsWhenCrouchingOnly` to control what and when is displayed for the pokemon label
- `/freezepokemon` command to pause a Pokémon's animation at a specific point in time.
- Added `no_ai` and `freeze_frame` options to the `/spawnpokemon` command.
- Added shiny Pokémon effects.
- Added effects for the burn status effect.
- Added effects for the moves: Psychic, Water Sport, and Mud Sport.
- Added a new universal locator called "top".
- Added `moves` option to Pokémon properties, allowing you to set the moves of a Pokémon in commands and spawn files using comma-separated move names.
- Added shiny Pokémon effects.
- Added shiny Pokémon particle effects and sounds to help find them.
- Added effects for the burn status effect.
- Added effects for the moves: Seismic Toss, Withdraw, Bite, Crunch, Super Fang, Hyper Fang, Pursuit, Mist, Haze, Lick, Kinesis, Psychic, Water Sport, and Mud Sport.
- Added a new universal locator called `top`.
- Added shiny Pokémon particles with sound effects.
- Added animation for trading.
- Added icons for pending trade, team-up, and battle requests from other players.
- Added `/spawnnpc` and `/spawnnpcat` commands.
- Added extra visuals to early berry growth stages.
- Added Polished Tumblestone and Tumblestone Brick block sets from Tumblestone, Black Tumblestone, and Sky Tumblestone.
- Moves impacted by the abilities Pixelate, Refrigerate, Aerilate, Galvanize, and Normalize now display as their altered typing.
- Added Fire, Water, Thunder, Leaf, Ice, Sun, Moon, Shiny, Dawn, and Dusk Stone storage blocks.
- Added Eject Pack, Metronome, Protective Pads, Punching Glove, Room Service, Scope Lens, Shed Shell, Terrain Extender, Throat Spray, Utility Umbrella, Wide Lens, and Zoom Lens held items.
- Added a full evolution particle effect for Pokémon that are sent out when evolution is started.
- Added a Nurse profession that can be unlocked by having villagers claim a healing machine block.
- Pokémon are now animated when seen in any GUI that isn't the party GUI.
- Added animation and sounds for trading.
- Added icons for pending trade, team-up, and battle requests from other players.
- Quirk animations can now occur for Pokémon that are shoulder mounted.
- Added `fishing boat` structures that contain a map to a shipwreck cove and a pokerod smithing template.
- Added `submerged_shipwreck_cove` and `lush_shipwreck_cove` structures.
- Added new sounds for Poké Balls bouncing off of Pokémon and landing on the ground during capture.
- Added a unique set of sounds for Ancient Poké Balls.
- Added a sound for using Exp Candy and Rare Candy items.
- Added revamped Poké Ball animation for Pokémon breaking out.
- Added battle log messages for switching out Pokémon.
- Added config setting `displayEntityNameLabel` and `displayEntityLabelsWhenCrouchingOnly` to control what and when is displayed for the pokemon label.
- Added `no_ai` and `freeze_frame` options to the `/spawnpokemon` command.
- Added `moves` option to Pokémon properties, allowing you to set the moves of a Pokémon in commands and spawn files using comma-separated move names.
- Added a `natural` block state property for the healing machine block; when property is set to true, the block will have a different texture and drop an iron ingot instead of itself.
- Added a `battleInvulnerability` gamerule to make players invulnerable to any damage during a battle.
- Added a `mobTargetInBattle` gamerule to exclude players from being targeted by mobs during a battle.
- Added a `/freezepokemon` command to pause a Pokémon's animation at a specific point in time.
- Added `/spawnnpc` and `/spawnnpcat` commands.
- Added `hiddenability=false` option to `/spawnpokemon` and `/pokemonedit` commands, allowing the Pokémon's ability to be reverted to a normal ability.
- Added `aspect` and `unaspect` PokemonProperty arguments (which also includes commands such as `/pokemonedit`, `/spawnpokemon`, and `/givepokemon`) to allow forcing or un-forcing an aspect on a Pokémon.
- Added `type` alternatively `elemental_type` PokemonProperty argument, this is only used for filtering and is not applied to Pokémon. Example `type=fire` would be true for Charmander but false for Squirtle.
### Structures Added
- Fishing boat structure that contain an Explorer Map leading to a shipwreck cove and a Poké Rod Smithing Template.
- Stonjourner Henge Ruins, Luna Henge Ruins, and Sol Henge Ruins.
- Submerged Shipwreck Cove and Lush Shipwreck Cove.
- Pokémon Centers to all 5 village types.
### Pokémon Added
#### Gen 1
- Alola Bias Cubone
- Alola Bias Cubone (built-in resource pack)
- Alolan Marowak
#### Gen 2
@@ -67,6 +151,7 @@
- Octillery
- Mantine
- Smeargle
- Delibird
#### Gen 3
- Slakoth
@@ -124,9 +209,6 @@
#### Gen 9
- Wattrel
- Kilowattrel
- Wiglett
- Wugtrio
- Flamigo
- Veluza
- Farigiraf
- Klawf
@@ -138,8 +220,8 @@
- Dondozo
#### Unique Forms
- Magikarp Jump Variants
- Gyarados Jump Variants
- Magikarp Jump variants for Magikarp
- Magikarp Jump variants for Gyarados (built-in resource pack, enabled by default on Fabric)
### Added cries to the following Pokémon
- Sandshrew, Sandslash
@@ -246,6 +328,7 @@
### Model updates for the following Pokémon
- Bulbasaur, Ivysaur, Venusaur
- Charmander, Charmeleon, Charizard
- Caterpie
- Kakuna, Beedrill
- Lapras
- Porygon, Porygon2, Porygon-Z
@@ -281,9 +364,11 @@
- Phantump, Trevenant
- Litten, Torracat, Incineroar
- Popplio, Brionne, Primarina
- Mudbray
- Lurantis
- Scorbunny, Cinderace
- Quaxly
- Skeledirge
- Tatsugiri
### Changes
@@ -293,42 +378,55 @@
- Adjusted volumes of sounds made by Display Cases, Berry Bushes, Energy Root, Medicinal Leek, Vivichoke, Mints, Revival Herbs and Gilded Chests.
- Changes to mulch buffs/durations.
- Updated potion sprites.
- Link Cable recipe has been redesigned.
- Changed Link Cable recipe to be much cheaper.
- Updated sounds for Medicinal Leeks, Big Roots, Energy Roots and Revival Herbs.
- Updated UI sounds for clicking and evolving Pokémon.
- Updated cries for Chansey, Crobat, Hoothoot, Noctowl.
- Removed the interchangeable evolution results for the first stage Hisuian starters to prevent confusion. The method still exists for stage 2 to 3, but stage 1 to 2 was not distinguishable enough for many users.
- Bulbasaur, Ivysaur, Venusaur, Kakuna, Beedrill, Snorlax, Munchlax, Krabby, Kingler, Lurantis, Horsea, Seadra, Kingdra, Litten, Torracat, Incineroar, Mudkip, Marshtomp, Swampert, Scorbunny, Cinderace, Prinplup, Empoleon, Relicanth, Goldeen, Seaking, Shellder, Cloyster, Tatsugiri, Igglybuff, Jigglypuff, Wigglytuff, Krookodile, Gible, Gabite, Garchomp, Rhyhorn, Rhydon, Rhyperior, and Carvanha received model updates.
- Vivillon wings will stop being clear when you remove any Vivillon related resourcepacks. The default pattern will be the meadow wings.
- Adjusted Pokémon sendout positions for single battles.
- Wild Pokémon interaction range increased to 12 blocks (from 10 blocks).
- Player trade range increased to 12 blocks (from 10 blocks).
- PvP battle range increased to 32 blocks (from 10 blocks).
- Spectate range increased to 64 blocks (from 10 blocks).
- The inventory key now closes our GUIs if they are open, mirroring how Minecraft screens usually work.
- The noise from the pasture and PC blocks being interacted with now activates Sculk sensors.
- Updated dialogue GUI assets with proper assets.
- Updated dialogue GUI assets with proper assets not made by a programmer. Well, it was still a programmer, but- someone who can also draw!
- Updated party switching interface when in battle.
- Relic coin pouches can now be waterlogged.
- Pokémon name and level labels are now only visible when crouching by default. Set the `displayEntityLabelsWhenCrouchingOnly` config to `false` to always have them displayed.
- The "Press R to start battle prompt" will now disappear after a player's first battle has been won.
- The default number of digits for the Pokédex number in the summary has been increased, from 3 to 4.
- The "Press R to start battle prompt" will now disappear after a player's first battle has been won. You've probably figured that detail out by then.
- The default number of digits for the Pokédex number in the summary has been increased, from 3 to 4. There sure are a lot of Pokémon these days.
- The pasture block model's screen is now off by default.
- The Poké Balls creative tab is now named Utility Items as it also encompasses Poké Rod and Pokédex items.
- Moves can now be benched without specifying a replacement move, allowing for empty move slots.
- Moves learned via Sketch now persist after battle.
- Updated potion sprites
- Removed the interchangeable evolution results for the first stage Hisuian starters to prevent confusion. The method still exists for stage 2 to 3, but stage 1 to 2 was not distinguishable enough for many users.
- Hidden Power now displays its effective typing.
- Updated particles for moves: Confusion, Protect, Sand Attack, and Quick Attack.
- Updated particles for status effects: Paralysis, Poison, and Sleep.
- Updated particles on Gastly.
- Revamped stat buff and de-buff particles.
- Improved the performance of display cases that contain Pokémon photos.
- Updated sounds for Poké Balls closing, opening and for Pokémon breaking out.
- Improved the performance of display cases that contain Pokémon Model items.
- Removed species Base Stats from the summary interface as it is now viewable within the Pokédex.
- Changed summary tab text labels to icons. You'll get used to them. Or else.
- Clicking the summary interface exit button while the swap moves or evolve screen is open will cause the interface to switch back to the party screen. The button will exit the interface otherwise.
- Ancient Poke Balls now jump once rather than shaking 3 times when capturing Pokémon.
- The jump height indicate the number of shakes that would have occurred.
- A high wobbly jump indicates 1 shake.
- A high jump indicates 2 shakes.
- A medium jump indicates 3 shakes.
- A short jump indicates that you caught the Pokémon.
- Pokémon sent out during battle will spawn facing their opponent.
- Pokémon sent out outside a battle will spawn facing their trainer.
- Wailord is now 25% bigger. ... [But I have an idea.](https://tenor.com/view/star-wars-more-gif-21856591)
- Region-biased Pokémon forms are now optional to a built-in resource pack. This pack is enabled by default for Fabric. For NeoForge users, all our built-in resource packs default to disabled because that's all it supports right now.
- Update item sprites for Cell Battery, Chipped Pot, Covert Cloak, Cracked Pot, Masterpiece Teacup, Red Card, Sachet, and Unremarkable Teacup.
### Fixes
- Fixed Ability Patches not reverting Hidden Abilities back to Normal Abilities.
- Fixed awarding Pokémon experience upon forfeiting battles.
- Scaled down Amaura's fetus model to avoid clipping through the tank while animating.
- Fixed Cubone's cry not having a sound.
- Fixed Cubone's cry not having a sound (as if that Pokémon needed to be more tragic).
- Fixed the sendout sound erroneously playing when a wild Pokémon breaks out of a Poké ball.
- Flamethrower is no longer missing sounds.
- Fixed the Seafloor spawning context not being a usable context.
@@ -336,60 +434,58 @@
- Fixed Gilded Chests not dropping the chest itself when broken, only the contents.
- Fixed Pokémon losing their Hidden Ability through evolution if the middle stage did not have a Hidden Ability.
- Hidden Power no longer plays the water type action effect (It now plays the normal type action effect).
- Fixed Chimchar and Monferno T-posing whenever they sleep.
- Fixed Cetitan's cry breaking its walk and sleep animations.
- Fixed Crumbling Arch not blending in with the world.
- Fixed Energy Root applying being usable on a fainted Pokémon.
- Fixed Pokémon entity not spawning when starting a battle while recalling said Pokémon.
- Fixed Crumbling Arch structures not blending in with the world.
- Fixed Energy Root being usable on a fainted Pokémon.
- Fixed Pokémon not being sent out when starting a battle while recalling said Pokémon.
- Fixed species comparison not using namespace for both sides in `PokemonProperties.isSubsetOf`.
- Fixed `PokemonProperties#asString` prefixing nicknames with a '$'.
- Fixed PC not saving when Pokémon was changed outside.
- Fixed shearable Pokémon not dropping correct wool colors.
- Fixed pasture spawning Pokémon inside solid blocks when closest spawning position is blocked off.
- Fixed Tumbling Down advancement not being granted by tumblestone variants.
- Improve error handling when loading spawn sets to ensure invalid configurations don't crash the server.
- Fixed empty `JsonPlayerData` files resulting in players being unable to join server/world.
- Evolution notification and UI sound is now correctly playing (again).
- Sound for evolving Pokémon through the Summary Menu is now correctly playing again.
- Fix Starter prompt not showing up.
- Fix evolution now granting Pokédex entries.
- Fix Pokédex crash when a form is looked up without ever seeing the "normal" form.
- Fixed owned poké balls floating upwards if pausing mid-transition.
- Fixed owned Poké balls floating upwards if pausing the game mid-transition (which looked absolutely hilarious).
- Fixed all mouse buttons working for Battle UI navigation (now it's only primary/left click).
- Fixed trading Pokémon setting their friendship to 0 instead of the base value.
- Fixed a scenario where a Pokémon that rolled to spawn with a special Tera type sometimes has a Tera type that is already a part of their natural typing.
- Fixed a scenario where a Pokémon that rolled to spawn with a special Tera type sometimes having a Tera type that is already a part of their natural typing.
- Fixed PokemonProperty argument suggestions for `tera` and `tera_type` not suggesting `stellar`.
- Fixed being able to stack Relic Coin Pouches on top of each other.
- Fixed Model loader generating misleading crash-reports when client is crashing.
- Fixed model loader generating misleading crash-reports when client is crashing - that resurrection tank error wasn't our fault! We're innocent, your honour!
- Big Roots and Energy Roots now share the same sounds as intended.
- Fixed sounds made by blocks playing at a lower pitch than intended.
- Fixed Chimchar and Monferno T posing whenever they sleep.
- Fixed Chimchar and Monferno comically T posing whenever they sleep.
- Fixed Cetitan's cry breaking its walk and sleep animations.
- Fixed the Magby line not having any placeholder walk animations.
- Fixed Duskull and Dusclops using skylight levels for their nether spawn data. There is no sun in the Nether!
- Fixed Hisuian Zoroark using base Zoroark stats.
- Fixed Bellossom clipping into the player head when shoulder mounted.
- Fixed Shroomish's look range to prevent it from looking higher than it should.
- Fixed Maushold's faint animations not playing. It's sadder than Tandemaus!
- Fixed Maushold's faint animations not playing. It's even sadder than Tandemaus!
- Fixed Slowking's battle idle.
- Fixed Grafaiai's walk speed to prevent model sliding.
- Fixed Maushold's faint animations not playing. It's sadder than Tandemaus!
- Fixed Slowking's battle idle.
- Fixed Grafaiai's walk speed to prevent model sliding.
- Fixed Alolan Exeggutor's tail not showing in the party UI. It will now also stand in front of all Pokémon in the party menu :)
- Fixed Timburr duplicating its log while fainting.
- Fixed reviving items throwing an exception when used in battle.
- Fixed hitbox sizes for Grotle and Torterra being set to default values.
- Fixed Hisuian Sneasel using Johtonian Sneasel's cry. Johto-nian. Jotonion. Jotunheim?
- Fixed Trevenant T-posing after 8 seconds of sleeping. I also do that.
- Fixed Bewear T-posing for a bit if a wild one faints where you can see.
- Fixed Noctowl's placeholder fly animation.
- Corrected Lotad blinking animation.
- Fixed reviving items causing errors when used in battle.
- Fixed messages for Focus Sash, Confusion, Mummy, Ice Face, Own Tempo, and Revive.
- Improve error handling when loading spawn-sets to ensure invalid configurations don't crash the server.
- Fixed `crumbling_arch_ruins` from generating a giant cube of air and removed the chest.
- Fixed Crumbling Arch Ruins generating a giant cube of air and removed the chest.
- Fixed possible crash on large population servers due to concurrent access of data.
- Quickly sending out and recalling Pokémon now looks smoother and can no longer be spammed to cause desync issues.
- Pokémon are now invulnerable during sendout animation and intangible during recall animation.
- Pokémon are now invincible during sendout animation and intangible during recall animation.
- Scrolling with party keybinding now behaves properly when using high scroll speed or scroll sensitivity.
- Fixed battle log GUI flashing when Battle GUI is opened.
- Bag Items used during a turn will now be refunded if the battle ends before the next turn begins.
- Pokémon whose current owner is not its Original Trainer now gains extra experience.
- Pokémon whose current owner is not its Original Trainer now gain extra experience.
- Fixed Fossil Resurrection advancement not being granted.
- Fixed village generation caps not applying for berry farms. You were not meant to see more than two berry farms per village!
- Fixed village generation caps not applying for berry farms. You were not meant to see more than two berry farms per village! This has been broken for ages but no one noticed... Hmmm... We could just remove it from here...
- Fixed the Ice Face ability activation being displayed incorrectly in a battle.
- Fixed edge case of F1 and R locking you in battle with no R functionality (requiring ESC to get out).
- Fixed Poké Ball render orientation in battle interface when capturing.
@@ -402,22 +498,23 @@
- Fixed top black border rendering in scroll interfaces in summary UI.
- Fixed aspect tracking for Advancements.
- Fixed illusion not copying aspects or caught ball.
- Prevent summary stats tab from making sounds when clicking on an already open tab.
- Fixed display case not being able to be fed items from underneath.
- Fixed Pokémon battling in water continuously sinking to the bottom.
- Fixed passive healing and wake from faint not disabling when their config values are set to 0.
- Fixed an issue where rebinding the R key to a mouse button prevented players from closing the battle interface using that button.
### Developer
- `SpawnCause` is now an implementation of `SpawningInfluence`.
- Many types related to `Pokemon` including itself now have dedicated `Codec`, please migrate to them from the NBT/JSON/PacketBuffer write/read methods.
- `TeraTypes` now implements `Iterable`.
- `PokemonBattle` now starts on turn 0.
- SpawnCause is now an implementation of SpawningInfluence.
- Renamed Pokemon.hp to Pokemon.maxHealth to make it clearer. Backwards compatibility is provided but it is an active deprecation, please migrate away from it.
- Many types related to ``Pokemon`` including itself now have dedicated ``Codec``, please migrate to them from the NBT/JSON/PacketBuffer write/read methods.
- Serialization of PokemonStores and Pokemon themselves now require registry access, which will break some sidemods. This sucked for us more than it will suck for you! If you have a world or player instance, you can get it from there.
- ``TeraTypes`` now implements ``Iterable``.
- PokemonBattle now starts on turn 0.
- Added `forcedAspects` to Pokémon to make it easier to easily add basic aspects to a Pokémon in a way that persists. We already know that everyone is going to overuse this.
- Made the `Pokemon.aspects` setter private. This could technically break side-mods but if you are affected by this then you were using it wrong! Use `Pokemon.forcedAspects` to fix it.
- Cobblemon's main logger is properly static now.
- PokemonEntity.enablePoseTypeRecalculation can be used to disable automatic pose type recalculation.
- `PokemonEntity.enablePoseTypeRecalculation` can be used to disable automatic pose type recalculation.
- Added CollectEggEvent and HatchEggEvent for compatibility usage.
- Added events for:
- Showdown Instructions
@@ -433,32 +530,42 @@
- Added HealingSource, an interface applied to all sources of healing from player actions, for easier tracking of healing sources.
- Move Change
- Shiny Chance Calculation Event (with player context)
- Dex Information Changed (Pre and Post); this event is fired when the Pokédex is updated with new information.
- Rebuilt large swaths of the model animation code to simplify it.
- Renamed a bunch of things from %Poseable% to %Posable% because spelling.
- Renamed StatelessAnimation to PoseAnimation.
- Renamed StatefulAnimation to ActiveAnimation.
- Documented the animation system.
- Allowed for SpawnSnowstormEntityParticleHandler to handle non-posable entities (due to being non-posable, locators are useless - to set the offset use the settings in the particle itself).
- Added property chaining support for duplicate CustomPokemonPropertyType elements.
### Data Pack & Resource Pack Creators
- Added experimental `flow` datapack directory for handling events using MoLang event handlers.
- Added support for "shedders" similar to Shedinja's evolution logic.
- Fixed the placeholder `WingFlapIdle` animation so the wings are not rotating opposite to each other.
- 'player' type dialogue faces can now be explicitly stated so that NPC mods that use fake players can show in dialogue portraits.
- Added `isLeftSide` field for dialogue faces. This determines what side of dialogue box the portrait is on.
- "sounds/attacks" folder has been renamed to "sounds/move"
- `sounds/attacks` directory has been renamed to `sounds/move`.
- Moves sharing generic sounds now have unique sound events, allowing them to be changed with resource packs.
- All move sound events have been renamed to "move.NAME.SOURCE" for consistency.
- Status moves have been moved out of the 'attacks' folder and split into volatile and nonvolatile.
- 'status.badlypoison.actor' sound event has been renamed to "status.toxpoison.actor"
- Mulch and berry harvesting sound events have been renamed and moved to their respective folders in "sounds/block."
- All sounds related to evolving Pokémon have been moved to the "sounds/evolution" folder.
- Sound events for all blocks now start with "block."
- All move sound events have been renamed to `move.<NAME>.<SOURCE>` for consistency.
- Status moves have been moved out of the `attacks` directory and split into volatile and nonvolatile.
- `status.badlypoison.actor` sound event has been renamed to `status.toxpoison.actor`
- Mulch and berry harvesting sound events have been renamed and moved to their respective directories in `sounds/block`.
- All sounds related to evolving Pokémon have been moved to the `sounds/evolution` directory.
- Sound events for all blocks now start with `block`.
- Gimmighoul chest and item interaction sounds have been moved to where its cry is.
- Unused sound files and sound events have been removed.
- Poké Ball sounds are now in their animation files, making them more flexible to edit.
- Added MoLang compatibility in the isVisible property for transformed parts.
- Added q.has_aspect('some_aspect') function to animations, posers, and entity particle effects.
- Added `q.has_aspect('some_aspect')` function to animations, posers, and entity particle effects.
- Added support for conditional pose animations.
- Added a new universal locator called "top".
- Added `eggs_collected` and `eggs_hatched` Advancement triggers.
- Added missing `minYaw` configuration to the `q.look()` function for JSON posers.
- Some pose condition names have been changed:
- `isTouchingWaterOrRain` has been changed to `isInWaterOrRain`
- `isSubermegedInWater` has been changed to `isUnderWater`
### Localization
- Updated translations for:
@@ -1693,6 +1800,7 @@ Thank you so much to all of our community translators that bring the mod to the
- Lowered spawn rate of Tauros.
- Sableye now spawns near gem ores as well as amethyst.
- Added evolution stones and items to item tags
- Pokémon now play their cry animations when clicked on the starter selection screen.
### Fixes
- Fixed catch rates being entirely too difficult.
+27
View File
@@ -0,0 +1,27 @@
plugins {
id("java-gradle-plugin")
kotlin("jvm") version "2.1.0"
}
repositories {
mavenCentral()
gradlePluginPortal()
maven("https://maven.architectury.dev/")
maven("https://maven.fabricmc.net/")
}
dependencies {
implementation("net.neoforged:moddev-gradle:2.0.75")
implementation("dev.architectury:at:1.0.1")
implementation("net.fabricmc:access-widener:2.1.0")
}
gradlePlugin {
plugins {
create("cobblemongradle") {
id = "com.cobblemon.gradle"
implementationClass = "com.cobblemon.gradle.CobblemonGradle"
version = "1.0.0"
}
}
}
+7
View File
@@ -0,0 +1,7 @@
dependencyResolutionManagement {
versionCatalogs {
create("libs") {
from(files("../gradle/libs.versions.toml"))
}
}
}
@@ -0,0 +1,85 @@
package com.cobblemon.gradle
import com.cobblemon.gradle.extension.CobblemonGradleExtension
import com.cobblemon.gradle.extension.tasks.ConvertAccessWidenersTask
import com.cobblemon.gradle.extension.tasks.UnzipAccessWidenersTask
import net.neoforged.nfrtgradle.CreateMinecraftArtifacts
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.attributes.LibraryElements
import org.gradle.language.jvm.tasks.ProcessResources
class CobblemonGradle : Plugin<Project> {
override fun apply(project: Project) {
val cobblemonExtension = project.extensions.create(
CobblemonGradleExtension.EXTENSION_NAME,
CobblemonGradleExtension::class.java
)
//This exists because all of
// - com.cobblemon:mod
// - com.cobblemon:mod-resources
// - com.cobblemon:accesswidener
//technically point to the same dependency (the :common project). To pick the proper artifact from that project
//we set attributes in that project and check for them here.
val accessWideners = project.configurations.register("accessWidener") { configuration ->
configuration.isCanBeConsumed = false
configuration.isCanBeResolved = true
configuration.isCanBeDeclared = true
configuration.attributes {
it.attribute(
LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE,
project.objects.named(LibraryElements::class.java, LibraryElements.OBJECTS)
)
}
}
val includeRootResources = project.configurations.register("includeRootResources") { configuration ->
configuration.isCanBeConsumed = false
configuration.isCanBeResolved = true
configuration.isCanBeDeclared = true
configuration.attributes {
it.attribute(
LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE,
project.objects.named(LibraryElements::class.java, LibraryElements.RESOURCES)
)
}
}
val unzipAwTask = project.tasks.register("unzipAccessWideners", UnzipAccessWidenersTask::class.java) {
it.accessWidenerZips = accessWideners.get()
}
val convertAwTask = project.tasks.register(ConvertAccessWidenersTask.NAME, ConvertAccessWidenersTask::class.java) {
it.enabled = cobblemonExtension.convertAccessWideners
it.dependsOn(unzipAwTask)
it.accessWideners = project.files(unzipAwTask).plus(project.files(cobblemonExtension.additionalAccessWideners))
}
//Add root resources and access wideners to output jar
project.tasks.named("processResources", ProcessResources::class.java) { task ->
task.dependsOn(includeRootResources)
if (cobblemonExtension.convertAccessWideners) {
task.dependsOn(convertAwTask)
task.from(convertAwTask)
}
else {
task.dependsOn(unzipAwTask)
task.from(unzipAwTask)
}
task.doLast {
project.copy {
it.from(project.provider {
includeRootResources.get().resolve().map { project.zipTree(it) }
})
it.into(task.destinationDir)
}
}
}
project.tasks.withType(CreateMinecraftArtifacts::class.java) {
it.dependsOn(convertAwTask)
it.accessTransformers.from(convertAwTask)
}
}
}
@@ -0,0 +1,12 @@
package com.cobblemon.gradle.extension
import org.gradle.api.file.FileCollection
abstract class CobblemonGradleExtension {
var additionalAccessWideners: FileCollection? = null
var convertAccessWideners = true
companion object {
const val EXTENSION_NAME = "cobblemon"
}
}
@@ -0,0 +1,82 @@
package com.cobblemon.gradle.extension.tasks
import dev.architectury.at.AccessChange
import dev.architectury.at.AccessTransform
import dev.architectury.at.AccessTransformSet
import dev.architectury.at.ModifierChange
import dev.architectury.at.io.AccessTransformFormats
import net.fabricmc.accesswidener.AccessWidenerReader
import net.fabricmc.accesswidener.AccessWidenerVisitor
import org.cadixdev.bombe.type.signature.MethodSignature
import org.gradle.api.DefaultTask
import org.gradle.api.file.FileCollection
import org.gradle.api.tasks.InputFiles
import org.gradle.api.tasks.Internal
import org.gradle.api.tasks.OutputFiles
import org.gradle.api.tasks.TaskAction
import java.io.Writer
import java.nio.file.Files
abstract class ConvertAccessWidenersTask : DefaultTask() {
abstract var accessWideners: FileCollection
@InputFiles get
@Internal
val accessTransformerDir = project.layout.buildDirectory.dir("access-transformers")
@OutputFiles
val accessTransformers = project.files ({
accessWideners.files.map {
accessTransformerDir.get().file(it.name.replace("accesswidener", "accesstransformer.cfg"))
}
})
@TaskAction
fun convertAccessWideners() {
accessWideners.files.forEach { file ->
val awFile = Files.newBufferedReader(file.toPath())
val result = AccessTransformSet.create();
AccessWidenerReader(object : AccessWidenerVisitor {
override fun visitClass(name: String, access: AccessWidenerReader.AccessType, transitive: Boolean) {
result.getOrCreateClass(name).merge(toAt(access));
}
override fun visitMethod(owner: String, name: String, descriptor: String, access: AccessWidenerReader.AccessType, transitive: Boolean) {
result.getOrCreateClass(owner).mergeMethod(MethodSignature.of(name, descriptor), toAt(access));
}
override fun visitField(owner: String, name: String, descriptor: String, access: AccessWidenerReader.AccessType, transitive: Boolean) {
result.getOrCreateClass(owner).mergeField(name, toAt(access));
}
}).read(awFile)
val outputFile = accessTransformerDir.get().file(
file.name.replace("accesswidener", "accesstransformer.cfg")
)
var outputWriter: Writer? = null
try {
outputWriter = outputFile.asFile.writer()
AccessTransformFormats.FML.write(outputWriter, result)
}
finally {
outputWriter?.flush()
outputWriter?.close()
}
}
}
private fun toAt(access: AccessWidenerReader.AccessType): AccessTransform {
return when (access) {
AccessWidenerReader.AccessType.ACCESSIBLE -> AccessTransform.of(AccessChange.PUBLIC)
AccessWidenerReader.AccessType.EXTENDABLE, AccessWidenerReader.AccessType.MUTABLE -> AccessTransform.of(
AccessChange.PUBLIC,
ModifierChange.REMOVE
)
}
}
companion object {
const val NAME = "convertAccessWideners"
}
}
@@ -0,0 +1,33 @@
package com.cobblemon.gradle.extension.tasks
import org.gradle.api.DefaultTask
import org.gradle.api.Task
import org.gradle.api.file.FileCollection
import org.gradle.api.tasks.InputFiles
import org.gradle.api.tasks.Internal
import org.gradle.api.tasks.OutputFile
import org.gradle.api.tasks.OutputFiles
import org.gradle.api.tasks.TaskAction
abstract class UnzipAccessWidenersTask : DefaultTask() {
abstract var accessWidenerZips: FileCollection
@InputFiles get
@OutputFiles
val outputFiles = project.provider {
project.files(accessWidenerZips.flatMap { zip ->
project.zipTree(zip).files.map { OUTPUT_DIR.get().file(it.name) }
})
}
@Internal
val OUTPUT_DIR = project.layout.buildDirectory.dir("cobblemon-working/access-wideners")
@TaskAction
fun run() {
project.copy {
it.from(accessWidenerZips.map(project::zipTree))
it.into(OUTPUT_DIR)
}
}
}
+3 -1
View File
@@ -1,12 +1,14 @@
plugins {
id("cobblemon.root-conventions")
//id("cobblemon.root-conventions")
id ("net.nemerosa.versioning") version "3.1.0"
}
version = "${project.property("mod_version")}+${project.property("mc_version")}"
val isSnapshot = project.property("snapshot")?.equals("true") ?: false
/*
if (isSnapshot) {
val fixedBranchName = versioning.info.branch.substringAfter("/")
version = "$version-${fixedBranchName}-${versioning.info.build}"
}
*/
+90 -54
View File
@@ -1,68 +1,102 @@
import java.time.OffsetDateTime
import java.time.ZoneOffset
import java.time.format.DateTimeFormatter
import utilities.isSnapshot
import utilities.version
/*
*
* * 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/.
*
*/
plugins {
id("cobblemon.base-conventions")
id("cobblemon.publish-conventions")
id("net.kyori.blossom")
id("org.jetbrains.gradle.plugin.idea-ext")
id("net.nemerosa.versioning") version "3.1.0"
kotlin("jvm") version "2.1.0"
id ("net.neoforged.moddev") version "2.0.75"
id("net.kyori.blossom") version "2.1.0"
id("com.github.johnrengelman.shadow") version "8.1.1"
id("com.cobblemon.gradle")
}
architectury {
common("neoforge", "fabric")
cobblemon {
additionalAccessWideners = files(sourceSets.main.get().resources).filter { it.extension == "accesswidener" }
}
val rootResources = configurations.create("rootResources") {
isCanBeConsumed = true
isCanBeResolved = false
attributes {
attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, objects.named(LibraryElements.RESOURCES))
}
}
val accessWidenerExport = configurations.create("accessWidenerExport") {
isCanBeConsumed = true
isCanBeResolved = false
attributes {
attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, objects.named(LibraryElements.OBJECTS))
}
}
tasks.processResources {
exclude("*.accesswidener")
}
tasks.create<Zip>("zipResources") {
dependsOn("processResources")
from(tasks.processResources.get().destinationDir)
this.archiveBaseName = "mod-resources"
}
tasks.create<Zip>("zipAccessWideners") {
from(sourceSets.main.get().resources)
include("*.accesswidener")
this.archiveBaseName = "mod-accesswideners"
}
tasks.jar {
archiveBaseName = "mod"
manifest {
attributes(mapOf("FMLModType" to "GAMELIBRARY"))
}
exclude {
it.file in tasks.processResources.get().outputs.files
}
}
tasks.assemble {
dependsOn(tasks.named("zipResources"))
dependsOn(tasks.named("zipAccessWideners"))
}
artifacts {
add("rootResources", tasks.getByName<Zip>("zipResources"))
add("accessWidenerExport", tasks.getByName("zipAccessWideners"))
}
buildscript {
repositories {
mavenCentral()
gradlePluginPortal()
maven("https://maven.architectury.dev/")
maven("https://maven.fabricmc.net/")
}
}
repositories {
maven(url = "${rootProject.projectDir}/deps")
maven(url = "https://api.modrinth.com/maven")
maven(url = "https://maven.neoforged.net/releases")
mavenLocal()
mavenCentral()
maven("https://maven.fabricmc.net/")
maven("https://maven.blamejared.com/")
maven("https://api.modrinth.com/maven")
maven(url = "../deps")
}
dependencies {
implementation(libs.bundles.kotlin)
modImplementation(libs.fabric.loader)
modApi(libs.molang)
// Integrations
compileOnlyApi(libs.jei.api)
modCompileOnly(libs.bundles.fabric.integrations.compileOnly) {
compileOnly(libs.bundles.mongo)
compileOnly(libs.bundles.kotlin)
compileOnly(libs.molang)
compileOnly(libs.graal)
compileOnly(libs.jei.api)
compileOnly(libs.bundles.fabric.integrations.compileOnly) {
isTransitive = false
}
// Flywheel has no common dep so just pick one and don't use any platform specific code in common
// modCompileOnly(libs.flywheelFabric)
// Showdown
modCompileOnly(libs.graal)
// Data Storage
modCompileOnly(libs.bundles.mongo)
// Unit Testing
compileOnly("net.fabricmc:sponge-mixin:0.15.5+mixin.0.8.7")
compileOnly("io.github.llamalad7:mixinextras-fabric:0.4.1")
testImplementation(libs.bundles.unitTesting)
}
tasks.withType<Test> {
useJUnitPlatform()
testLogging {
setEvents(listOf("failed"))
setExceptionFormat("full")
}
neoForge {
neoFormVersion = "1.21.1-20240808.144430"
interfaceInjectionData.from("src/main/resources/interfaces.json")
validateAccessTransformers = true
}
sourceSets {
@@ -72,7 +106,7 @@ sourceSets {
fun generateLicenseHeader() : String {
val builder = StringBuilder()
builder.append("/*\n")
rootProject.file("HEADER").forEachLine {
project.projectDir.parentFile.resolve("HEADER").forEachLine {
if(it.isEmpty()) {
builder.append(" *").append("\n")
} else {
@@ -85,12 +119,14 @@ sourceSets {
property("license", generateLicenseHeader())
property("modid", "cobblemon")
property("version", project.version())
property("isSnapshot", if(rootProject.isSnapshot()) "true" else "false")
property("version", project.version as String)
property("isSnapshot", "true")
/*
property("gitCommit", versioning.info.commit)
property("branch", versioning.info.branch)
System.getProperty("buildNumber")?.let { property("buildNumber", it) }
property("timestamp", OffsetDateTime.now(ZoneOffset.UTC).format(DateTimeFormatter.ofPattern("MM/dd/yyyy hh:mm:ss")) + " UTC")
*/
}
}
}
+97
View File
@@ -0,0 +1,97 @@
import java.time.OffsetDateTime
import java.time.ZoneOffset
import java.time.format.DateTimeFormatter
import utilities.isSnapshot
import utilities.version
/*
*
* * 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/.
*
*/
plugins {
id("cobblemon.base-conventions")
id("cobblemon.publish-conventions")
id("net.kyori.blossom")
id("org.jetbrains.gradle.plugin.idea-ext")
id("net.nemerosa.versioning") version "3.1.0"
}
architectury {
common("neoforge", "fabric")
}
repositories {
maven(url = "${rootProject.projectDir}/deps")
maven(url = "https://api.modrinth.com/maven")
maven(url = "https://maven.neoforged.net/releases")
mavenLocal()
}
dependencies {
implementation(libs.bundles.kotlin)
modImplementation(libs.fabric.loader)
modApi(libs.molang)
// Integrations
compileOnlyApi(libs.jei.api)
modCompileOnly(libs.bundles.fabric.integrations.compileOnly) {
isTransitive = false
}
// Flywheel has no common dep so just pick one and don't use any platform specific code in common
// modCompileOnly(libs.flywheelFabric)
// Showdown
modCompileOnly(libs.graal)
// Data Storage
modCompileOnly(libs.bundles.mongo)
// Unit Testing
testImplementation(libs.bundles.unitTesting)
}
tasks.withType<Test> {
useJUnitPlatform()
testLogging {
setEvents(listOf("failed"))
setExceptionFormat("full")
}
}
sourceSets {
main {
blossom {
kotlinSources {
fun generateLicenseHeader() : String {
val builder = StringBuilder()
builder.append("/*\n")
rootProject.file("HEADER").forEachLine {
if(it.isEmpty()) {
builder.append(" *").append("\n")
} else {
builder.append(" * ").append(it).append("\n")
}
}
return builder.append(" */").append("\n").toString()
}
property("license", generateLicenseHeader())
property("modid", "cobblemon")
property("version", project.version())
property("isSnapshot", if(rootProject.isSnapshot()) "true" else "false")
property("gitCommit", versioning.info.commit)
property("branch", versioning.info.branch)
System.getProperty("buildNumber")?.let { property("buildNumber", it) }
property("timestamp", OffsetDateTime.now(ZoneOffset.UTC).format(DateTimeFormatter.ofPattern("MM/dd/yyyy hh:mm:ss")) + " UTC")
}
}
}
}
+95
View File
@@ -0,0 +1,95 @@
[versions]
# Kotlin
kotlin = "2.0.0"
# Plugins
licenser = "0.6.1"
shadow = "8.1.1"
blossom = "2.1.0"
idea-ext = "1.1.7"
# Loom
loom = "1.7-SNAPSHOT"
architectury-plugin = "3.4-SNAPSHOT"
# Common
molang = "1.1.18"
graal = "22.3.0"
icu4j = "71.1"
jei-api = "19.8.2.99"
# Fabric
fabric-loader = "0.16.5"
fabric-api = "0.104.0+1.21.1"
fabric-kotlin = "1.11.0+kotlin.2.0.0"
fabric-permissions-api = "0.2-SNAPSHOT"
lambDynamicLights = "3.0.1+1.21.1"
debugutils-fabric = "1.21-1.0.6-fabric"
# NeoForge
neoforge = "21.1.66"
neo-kotlin-for-forge = "5.5.0"
debugutils-forge = "1.21-1.0.6-neoforge"
# Data Storage
mongo = "4.10.2"
# Testing
junit = "5.9.0"
mockito = "5.2.0"
mockk = "1.12.1"
classgraph = "4.8.153"
[libraries]
# General Buildscript Plugins
kotlin = { group = "org.jetbrains.kotlin", name = "kotlin-gradle-plugin", version.ref = "kotlin" }
loom = { group = "dev.architectury", name = "architectury-loom", version.ref = "loom" }
architectury = { group = "architectury-plugin", name = "architectury-plugin.gradle.plugin", version.ref = "architectury-plugin" }
shadow = { group = "com.github.johnrengelman", name = "shadow", version.ref = "shadow" }
blossom = { group = "net.kyori", name = "blossom", version.ref = "blossom" }
ideaExt = { group = "org.jetbrains.gradle.plugin.idea-ext", name = "org.jetbrains.gradle.plugin.idea-ext.gradle.plugin", version.ref = "idea-ext"}
licenser = { group = "gradle.plugin.org.cadixdev.gradle", name = "licenser", version.ref = "licenser" }
# Kotlin
kotlin-stdlib = { group = "org.jetbrains.kotlin", name = "kotlin-stdlib-jdk8", version.ref = "kotlin" }
kotlin-reflect = { group = "org.jetbrains.kotlin", name = "kotlin-reflect", version.ref = "kotlin" }
# Common
jei-api = { group = "mezz.jei", name = "jei-1.21-common-api", version.ref = "jei-api"}
molang = { group = "local.com.bedrockk", name = "molang", version.ref = "molang" }
graal = { group = "org.graalvm.js", name = "js", version.ref = "graal" }
icu4j = { group = "com.ibm.icu", name = "icu4j", version.ref = "icu4j" }
# Fabric
fabric-loader = { group = "net.fabricmc", name = "fabric-loader", version.ref = "fabric-loader" }
fabric-api = { group = "net.fabricmc.fabric-api", name = "fabric-api", version.ref = "fabric-api" }
fabric-kotlin = { group = "net.fabricmc", name = "fabric-language-kotlin", version.ref = "fabric-kotlin" }
fabric-permissions = { group = "me.lucko", name = "fabric-permissions-api", version.ref = "fabric-permissions-api" }
adorn-fabric = { group = "maven.modrinth", name = "adorn", version = "6.0.0-neoforge"}
lambDynamicLights = { group = "maven.modrinth", name = "lambdynamiclights", version.ref = "lambDynamicLights"}
jei-api-fabric = { group = "mezz.jei", name = "jei-1.21-fabric-api", version.ref = "jei-api" }
jei-fabric = { group = "mezz.jei", name = "jei-1.21-fabric", version.ref = "jei-api"}
fabric-debugutils = { group = "maven.modrinth", name = "debugutils", version.ref = "debugutils-fabric"}
# NeoForge
neoforge = { group = "net.neoforged", name = "neoforge", version.ref = "neoforge" }
neo-kotlin-forge = { group = "thedarkcolour", name = "kotlinforforge-neoforge", version.ref = "neo-kotlin-for-forge" }
neoforge-debugutils = { group = "maven.modrinth", name = "debugutils", version.ref = "debugutils-forge"}
# Data Storage
mongo-driver-core = { group = "org.mongodb", name = "mongodb-driver-core", version.ref = "mongo" }
mongo-driver-sync = { group = "org.mongodb", name = "mongodb-driver-sync", version.ref = "mongo" }
# Testing
junit = { group = "org.junit.jupiter", name = "junit-jupiter", version.ref = "junit" }
mockito-core = { group = "org.mockito", name = "mockito-core", version.ref = "mockito" }
mock-kotlin = { group = "io.mockk", name = "mockk", version.ref = "mockk" }
classgraph = { group = "io.github.classgraph", name = "classgraph", version.ref = "classgraph" }
[bundles]
kotlin = [ "kotlin-stdlib", "kotlin-reflect" ]
fabric = [ "fabric-kotlin", "fabric-permissions" ]
fabric-integrations-compileOnly = [ "adorn-fabric", "lambDynamicLights", "jei-api-fabric" ]
fabric-integrations-runtimeOnly = [ "jei-fabric" ]
mongo = [ "mongo-driver-core", "mongo-driver-sync" ]
unitTesting = [ "junit", "mockito-core", "mock-kotlin", "classgraph" ]
@@ -45,21 +45,4 @@ public class ChunkStorageMixin {
int curVersion = vanillaFixed.contains(VERSION_KEY) ? vanillaFixed.getInt(VERSION_KEY) : 0;
return DataFixTypes.CHUNK.update(CobblemonSchemas.getDATA_FIXER(), vanillaFixed, curVersion, CobblemonSchemas.DATA_VERSION);
}
@Inject(
method = "upgradeChunkTag(Lnet/minecraft/resources/ResourceKey;Ljava/util/function/Supplier;Lnet/minecraft/nbt/CompoundTag;Ljava/util/Optional;)Lnet/minecraft/nbt/CompoundTag;",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/nbt/NbtUtils;addCurrentDataVersion(Lnet/minecraft/nbt/CompoundTag;)Lnet/minecraft/nbt/CompoundTag;"
)
)
public void cobblemon$addChunkVersion(
ResourceKey<Level> resourceKey,
Supplier<DimensionDataStorage> supplier,
CompoundTag compoundTag,
Optional<ResourceKey<MapCodec<? extends ChunkGenerator>>> optional,
CallbackInfoReturnable<CompoundTag> cir
) {
compoundTag.put(VERSION_KEY, IntTag.valueOf(CobblemonSchemas.DATA_VERSION));
}
}
@@ -9,6 +9,20 @@
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.world.entity.Entity;
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;
@@ -34,4 +48,39 @@ public class EntityRenderDispatcherMixin {
public void resourceManagerReloadHook(ResourceManager resourceManager, CallbackInfo ci) {
CobblemonClient.INSTANCE.onAddLayer(this.playerRenderers);
}
@Inject(
method = "renderHitbox(Lcom/mojang/blaze3d/vertex/PoseStack;Lcom/mojang/blaze3d/vertex/VertexConsumer;Lnet/minecraft/world/entity/Entity;FFFF)V",
at = @At(value = "TAIL")
)
private static void renderLocators(
PoseStack poseStack,
VertexConsumer buffer,
Entity entity,
float red,
float green,
float blue,
float alpha,
CallbackInfo ci
) {
if (entity instanceof PosableEntity posableEntity) {
if (posableEntity.getDelegate() instanceof PosableState state) {
state.getLocatorStates().forEach((locator, matrix) -> {
poseStack.pushPose();
Vec3 pos = matrix.getOrigin().subtract(entity.position());
LevelRenderer.renderLineBox(
poseStack,
buffer,
AABB.ofSize(pos, 0.25, 0.25, 0.25),
0F,
1F,
0F,
1F
);
poseStack.popPose();
});
}
}
}
}
@@ -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.mixin;
import com.cobblemon.mod.common.entity.fishing.PokeRodFishingBobberEntity;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.client.renderer.item.ItemProperties;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(ItemProperties.class)
public class ItemPropertiesMixin {
// Mixins into the fishing rod's register() lambda expression
// Without this, the fishing rod item model appears cast when using a PokeRod in the other hand
@Inject(method = "method_27883", at = @At(value = "RETURN", ordinal = 1), cancellable = true)
private static void cobblemon$preventRodMixup(ItemStack itemStack, ClientLevel clientLevel, LivingEntity livingEntity, int i, CallbackInfoReturnable<Float> cir) {
if (!(livingEntity instanceof Player) || ((Player) livingEntity).fishing instanceof PokeRodFishingBobberEntity) {
cir.setReturnValue(0.0f);
}
}
}
@@ -10,7 +10,6 @@ package com.cobblemon.mod.common.mixin;
import com.cobblemon.mod.common.Cobblemon;
import com.cobblemon.mod.common.ModAPI;
import com.cobblemon.mod.common.client.CobblemonBakingOverrides;
import com.cobblemon.mod.common.item.PokeBallItem;
import com.cobblemon.mod.common.item.PokedexItem;
import com.mojang.blaze3d.vertex.PoseStack;
@@ -20,7 +19,9 @@ import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.entity.ItemRenderer;
import net.minecraft.client.resources.model.BakedModel;
import net.minecraft.client.resources.model.ModelResourceLocation;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemDisplayContext;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;
@@ -52,25 +53,33 @@ public abstract class ItemRendererMixin {
)
private void cobblemon$overrideItemModel(ItemStack stack, ItemDisplayContext renderMode, boolean leftHanded, PoseStack matrices, MultiBufferSource multiBufferSource, int light, int overlay, BakedModel model, CallbackInfo ci) {
boolean shouldBe2d = renderMode == ItemDisplayContext.GUI || renderMode == ItemDisplayContext.FIXED;
if (!shouldBe2d && stack.getItem() instanceof PokedexItem) {
BakedModel replacementModel = CobblemonBakingOverrides.INSTANCE.getPokedexOverride(((PokedexItem) stack.getItem()).getType()).getModel();
if (!cobblemon$isSameModel(model, replacementModel)) {
ci.cancel();
render(stack, renderMode, leftHanded, matrices, multiBufferSource, light, overlay, replacementModel);
}
} else if (shouldBe2d && stack.getItem() instanceof PokeBallItem pokeBallItem) {
BakedModel replacementModel = this.itemModelShaper.getModelManager().getModel(new ModelResourceLocation(pokeBallItem.getPokeBall().getModel2d(), "inventory"));
if (!cobblemon$isSameModel(model, replacementModel)) {
ci.cancel();
render(stack, renderMode, leftHanded, matrices, multiBufferSource, light, overlay, replacementModel);
if (shouldBe2d) {
ResourceLocation resourceLocation = null;
if (stack.getItem() instanceof PokeBallItem pokeBallItem) resourceLocation = pokeBallItem.getPokeBall().getModel2d();
else if (stack.getItem() instanceof PokedexItem pokedexItem) resourceLocation = pokedexItem.getType().getItemSpritePath();
if (resourceLocation != null) {
BakedModel replacementModel = this.itemModelShaper.getModelManager().getModel(new ModelResourceLocation(resourceLocation, "inventory"));
if (!cobblemon$isSameModel(model, replacementModel)) {
ci.cancel();
render(stack, renderMode, leftHanded, matrices, multiBufferSource, light, overlay, replacementModel);
}
}
}
}
@Inject(method = "getModel", at = @At("HEAD"), cancellable = true)
private void cobblemon$bakePokeballModel(ItemStack stack, Level world, LivingEntity entity, int seed, CallbackInfoReturnable<BakedModel> cir) {
if (stack.getItem() instanceof PokeBallItem pokeBallItem) {
BakedModel model = this.itemModelShaper.getModelManager().getModel(new ModelResourceLocation(pokeBallItem.getPokeBall().getModel3d(), MODEL_PATH));
private void cobblemon$getItemModel(ItemStack stack, Level world, LivingEntity entity, int seed, CallbackInfoReturnable<BakedModel> cir) {
ResourceLocation resourceLocation = null;
if (stack.getItem() instanceof PokeBallItem pokeBallItem) resourceLocation = pokeBallItem.getPokeBall().getModel3d();
else if (stack.getItem() instanceof PokedexItem pokedexItem) {
boolean isScanModel = entity instanceof Player && entity.getUseItem() == stack && entity.isUsingItem();
boolean canOpenScreen = entity != null && ((entity.getOffhandItem() == stack && !(entity.getMainHandItem().getItem() instanceof PokedexItem)) || entity.getMainHandItem() == stack);
resourceLocation = pokedexItem.getType().getItemModelPath(isScanModel ? "scanning" : (canOpenScreen ? null : "off"));
}
if (resourceLocation != null) {
BakedModel model = this.itemModelShaper.getModelManager().getModel(new ModelResourceLocation(resourceLocation, MODEL_PATH));
ClientLevel clientWorld = world instanceof ClientLevel ? (ClientLevel) world : null;
BakedModel overriddenModel = model.getOverrides().resolve(model, stack, clientWorld, entity, seed);
cir.setReturnValue(overriddenModel == null ? this.itemModelShaper.getModelManager().getMissingModel() : overriddenModel);
@@ -52,10 +52,11 @@ public abstract class LecternBlockMixin {
if (lecternEntity instanceof LecternBlockEntity) {
((LecternBlockEntity) lecternEntity).setItemStack((pokedexItemStack));
world.playSound(null, blockPos, CobblemonSounds.POKEDEX_CLOSE, SoundSource.BLOCKS, 0.5F, 1.25F);
cir.setReturnValue(ItemInteractionResult.SUCCESS);
} else {
cir.setReturnValue(itemStack.isEmpty() && interactionHand == InteractionHand.MAIN_HAND ? ItemInteractionResult.SKIP_DEFAULT_BLOCK_INTERACTION : ItemInteractionResult.PASS_TO_DEFAULT_BLOCK_INTERACTION);
}
world.playSound(null, blockPos, CobblemonSounds.POKEDEX_CLOSE, SoundSource.BLOCKS, 0.5F, 1.25F);
cir.setReturnValue(itemStack.isEmpty() && interactionHand == InteractionHand.MAIN_HAND ? ItemInteractionResult.SKIP_DEFAULT_BLOCK_INTERACTION : ItemInteractionResult.PASS_TO_DEFAULT_BLOCK_INTERACTION);
}
}
}
@@ -22,7 +22,7 @@ public abstract class MinecraftDedicatedServerMixin implements ServerInterface {
@Inject(method = "shouldDiscardEntity", at = @At(value = "HEAD"), cancellable = true)
public void cobblemon$allowPokemonSpawns(Entity entity, CallbackInfoReturnable<Boolean> callback) {
if(entity instanceof PokemonEntity) {
if (entity instanceof PokemonEntity) {
callback.setReturnValue(false);
}
}
@@ -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.mixin;
import static com.cobblemon.mod.common.datafixer.CobblemonSchemas.VERSION_KEY;
import com.cobblemon.mod.common.datafixer.CobblemonSchemas;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.NbtUtils;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(NbtUtils.class)
public class NbtUtilsMixin {
@Inject(
method = "addCurrentDataVersion(Lnet/minecraft/nbt/CompoundTag;)Lnet/minecraft/nbt/CompoundTag;",
at = @At("TAIL")
)
private static void addCobblemonDataVersion(
CompoundTag tag,
CallbackInfoReturnable<CompoundTag> cir
) {
tag.putInt(VERSION_KEY, CobblemonSchemas.DATA_VERSION);
}
}
@@ -1,39 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.mixin.client;
import com.cobblemon.mod.common.client.CobblemonClient;
import net.minecraft.client.DeltaTracker;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.Gui;
import net.minecraft.client.gui.GuiGraphics;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
/**
* Mixin to give us a hook to render the PartyOverlay below the Chat
*
* @author Qu
* @since 2022-02-22
*/
@Mixin(Gui.class)
public class GuiMixin {
//This injects into the actual BooleanSupplier lambda for the "this.layers.add(layeredDraw, () -> !minecraft.options.hideGui)" call
// sus af. You have to get the method name by looking at the bytecode of the class. Can do in intellij By clicking View -> Show Bytecode (top left)
@Inject(method = "method_55797", at = @At("HEAD"), cancellable = true)
private static void cobblemon$dontRenderUiInPokedex(Minecraft minecraft, CallbackInfoReturnable<Boolean> cir) {
if (CobblemonClient.INSTANCE.getPokedexUsageContext().getScanningGuiOpen() && minecraft.options.getCameraType().isFirstPerson()) {
cir.setReturnValue(false);
}
}
}
@@ -54,7 +54,10 @@ import com.cobblemon.mod.common.api.storage.pc.PCStore
import com.cobblemon.mod.common.api.storage.pc.link.PCLinkManager
import com.cobblemon.mod.common.api.storage.player.PlayerInstancedDataStoreManager
import com.cobblemon.mod.common.api.storage.player.PlayerInstancedDataStoreTypes
import com.cobblemon.mod.common.api.storage.player.adapter.*
import com.cobblemon.mod.common.api.storage.player.adapter.DexDataMongoBackend
import com.cobblemon.mod.common.api.storage.player.adapter.DexDataNbtBackend
import com.cobblemon.mod.common.api.storage.player.adapter.PlayerDataJsonBackend
import com.cobblemon.mod.common.api.storage.player.adapter.PlayerDataMongoBackend
import com.cobblemon.mod.common.api.storage.player.factory.CachedPlayerDataStoreFactory
import com.cobblemon.mod.common.api.tags.CobblemonEntityTypeTags
import com.cobblemon.mod.common.api.tags.CobblemonItemTags
@@ -65,22 +68,15 @@ import com.cobblemon.mod.common.battles.BattleSide
import com.cobblemon.mod.common.battles.ShowdownThread
import com.cobblemon.mod.common.battles.actor.PokemonBattleActor
import com.cobblemon.mod.common.battles.pokemon.BattlePokemon
import com.cobblemon.mod.common.command.argument.DexArgumentType
import com.cobblemon.mod.common.command.argument.DialogueArgumentType
import com.cobblemon.mod.common.command.argument.FormArgumentType
import com.cobblemon.mod.common.command.argument.MoveArgumentType
import com.cobblemon.mod.common.command.argument.NPCClassArgumentType
import com.cobblemon.mod.common.command.argument.PartySlotArgumentType
import com.cobblemon.mod.common.command.argument.PokemonPropertiesArgumentType
import com.cobblemon.mod.common.command.argument.PokemonStoreArgumentType
import com.cobblemon.mod.common.command.argument.SpawnBucketArgumentType
import com.cobblemon.mod.common.command.argument.SpeciesArgumentType
import com.cobblemon.mod.common.client.CobblemonPack
import com.cobblemon.mod.common.command.argument.*
import com.cobblemon.mod.common.config.CobblemonConfig
import com.cobblemon.mod.common.config.LastChangedVersion
import com.cobblemon.mod.common.config.constraint.IntConstraint
import com.cobblemon.mod.common.config.starter.StarterConfig
import com.cobblemon.mod.common.data.CobblemonDataProvider
import com.cobblemon.mod.common.events.AdvancementHandler
import com.cobblemon.mod.common.events.FlowHandler
import com.cobblemon.mod.common.events.PokedexHandler
import com.cobblemon.mod.common.events.ServerTickHandler
import com.cobblemon.mod.common.net.messages.client.settings.ServerSettingsPacket
@@ -93,17 +89,21 @@ import com.cobblemon.mod.common.pokemon.evolution.variants.BlockClickEvolution
import com.cobblemon.mod.common.pokemon.feature.TagSeasonResolver
import com.cobblemon.mod.common.pokemon.helditem.CobblemonHeldItemManager
import com.cobblemon.mod.common.pokemon.properties.AspectPropertyType
import com.cobblemon.mod.common.pokemon.properties.BattleCloneProperty
import com.cobblemon.mod.common.pokemon.properties.FreezeFrameProperty
import com.cobblemon.mod.common.pokemon.properties.HiddenAbilityPropertyType
import com.cobblemon.mod.common.pokemon.properties.NoAIProperty
import com.cobblemon.mod.common.pokemon.properties.UnaspectPropertyType
import com.cobblemon.mod.common.pokemon.properties.UncatchableProperty
import com.cobblemon.mod.common.pokemon.properties.BattleCloneProperty
import com.cobblemon.mod.common.pokemon.properties.tags.PokemonFlagProperty
import com.cobblemon.mod.common.pokemon.stat.CobblemonStatProvider
import com.cobblemon.mod.common.starter.CobblemonStarterHandler
import com.cobblemon.mod.common.trade.TradeManager
import com.cobblemon.mod.common.util.*
import com.cobblemon.mod.common.util.DataKeys
import com.cobblemon.mod.common.util.cobblemonResource
import com.cobblemon.mod.common.util.ifDedicatedServer
import com.cobblemon.mod.common.util.isLaterVersion
import com.cobblemon.mod.common.util.party
import com.cobblemon.mod.common.util.server
import com.cobblemon.mod.common.world.feature.CobblemonPlacedFeatures
import com.cobblemon.mod.common.world.feature.ore.CobblemonOrePlacedFeatures
import com.cobblemon.mod.common.world.gamerules.CobblemonGameRules
@@ -115,7 +115,7 @@ import java.io.File
import java.io.FileReader
import java.io.FileWriter
import java.io.PrintWriter
import java.util.*
import java.util.UUID
import kotlin.math.roundToInt
import kotlin.properties.Delegates
import kotlin.reflect.full.memberProperties
@@ -124,6 +124,7 @@ import kotlin.reflect.jvm.javaField
import net.minecraft.client.Minecraft
import net.minecraft.commands.synchronization.SingletonArgumentInfo
import net.minecraft.resources.ResourceKey
import net.minecraft.server.packs.PackType
import net.minecraft.world.item.NameTagItem
import net.minecraft.world.level.Level
import net.minecraft.world.level.storage.LevelResource
@@ -163,6 +164,16 @@ object Cobblemon {
var statProvider: StatProvider = CobblemonStatProvider
var seasonResolver: SeasonResolver = TagSeasonResolver
@JvmStatic
val builtinPacks = listOf<CobblemonPack>(
CobblemonPack(id = "adorncompatibility", name = "Adorn Compatibility", packType = PackType.CLIENT_RESOURCES, activationBehaviour = ResourcePackActivationBehaviour.ALWAYS_ENABLED, neededMods = setOf("adorn")),
CobblemonPack(id = "gyaradosjump", name = "Gyarados Jump Patterns", packType = PackType.CLIENT_RESOURCES, activationBehaviour = ResourcePackActivationBehaviour.DEFAULT_ENABLED),
CobblemonPack(id = "regionbiasforms", name = "Region Bias Forms", packType = PackType.CLIENT_RESOURCES, activationBehaviour = ResourcePackActivationBehaviour.DEFAULT_ENABLED),
CobblemonPack(id = "uniqueshinyforms", name = "Shinies for Magikarp Jump", packType = PackType.CLIENT_RESOURCES, activationBehaviour = ResourcePackActivationBehaviour.NORMAL),
CobblemonPack(id = "repurposedstructurescobblemon", name = "Repurposed Structures Cobblemon", packType = PackType.SERVER_DATA, activationBehaviour = ResourcePackActivationBehaviour.DEFAULT_ENABLED, neededMods = setOf("repurposed_structures")),
)
fun preInitialize(implementation: CobblemonImplementation) {
this.implementation = implementation
@@ -207,7 +218,7 @@ object Cobblemon {
storage.onPlayerDataSync(it)
playerDataManager.syncAllToPlayer(it)
starterHandler.handleJoin(it)
ServerSettingsPacket(this.config.preventCompletePartyDeposit, this.config.displayEntityLevelLabel, this.config.displayEntityNameLabel).sendToPlayer(it)
ServerSettingsPacket(this.config.preventCompletePartyDeposit, this.config.displayEntityLevelLabel, this.config.displayEntityNameLabel, this.config.maxPokemonLevel).sendToPlayer(it)
}
PlatformEvents.SERVER_PLAYER_LOGOUT.subscribe {
PCLinkManager.removeLink(it.player.uuid)
@@ -286,7 +297,9 @@ object Cobblemon {
CustomPokemonProperty.register(FreezeFrameProperty)
CustomPokemonProperty.register(NoAIProperty)
CobblemonEvents.POKEMON_PROPERTY_INITIALISED.emit()
CobblemonEvents.POKEMON_PROPERTY_INITIALISED.emit(Unit)
FlowHandler.setup()
ifDedicatedServer {
isDedicatedServer = true
@@ -383,13 +396,18 @@ object Cobblemon {
BattleFormat.GEN_9_SINGLES,
BattleSide(PokemonBattleActor(UUID.randomUUID(), BattlePokemon(Pokemon().initialize()), -1F)),
BattleSide(PokemonBattleActor(UUID.randomUUID(), BattlePokemon(Pokemon().initialize()), -1F)),
true
).ifSuccessful { it.mute = true }
false
).ifSuccessful {
it.mute = true
}.ifErrored {
val errors = it.errors.joinToString("\n") { it.javaClass.name }
LOGGER.error("Failed to start dummy Showdown battle: $errors")
}
}
registerEventHandlers()
CobblemonEvents.COBBLEMON_INITIALISED.emit()
CobblemonEvents.COBBLEMON_INITIALISED.emit(Unit)
}
@@ -12,9 +12,8 @@ import net.minecraft.world.entity.schedule.Activity
object CobblemonActivities {
val activities = mutableListOf<Activity>()
val BATTLING_ACTIVITY = register(Activity("pokemon_battling"))
val NPC_BATTLING = register(Activity("npc_battling"))
val NPC_ACTION_EFFECT = register(Activity("npc_action_effect"))
val BATTLING = register(Activity("battling"))
val ACTION_EFFECT = register(Activity("action_effect"))
val NPC_CHATTING = register(Activity("npc_chatting"))
fun register(activity: Activity): Activity {
@@ -121,10 +121,17 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
val APRICORN_PRESSURE_PLATE = this.create("apricorn_pressure_plate", PressurePlateBlockInvoker.`cobblemon$create`(APRICORN_BLOCK_SET_TYPE, BlockBehaviour.Properties.of().mapColor(APRICORN_PLANKS.defaultMapColor()).noCollission().strength(0.5f).sound(SoundType.WOOD)))
@JvmField
val APRICORN_SIGN = this.create("apricorn_sign", CobblemonSignBlock(BlockBehaviour.Properties.ofFullCopy(Blocks.OAK_SIGN), APRICORN_WOOD_TYPE))
@JvmField //if you wonder why we don't copy of OAK_WALL_SIGN, then I can tell you its because it uses Properties#dropsLike to point to the SIGN loot table, but we cant use that in our setup due to a deeper rooted issue, so falling back to this and writing dedicated (duplicated) loot tables
val APRICORN_WALL_SIGN = this.create(
"apricorn_wall_sign",
CobblemonWallSignBlock(BlockBehaviour.Properties.ofFullCopy(Blocks.OAK_SIGN), APRICORN_WOOD_TYPE)
)
@JvmField
val APRICORN_WALL_SIGN = this.create("apricorn_wall_sign", CobblemonWallSignBlock(BlockBehaviour.Properties.ofFullCopy(Blocks.OAK_WALL_SIGN), APRICORN_WOOD_TYPE))
@JvmField
val APRICORN_HANGING_SIGN = this.create("apricorn_hanging_sign", CobblemonHangingSignBlock(BlockBehaviour.Properties.ofFullCopy(Blocks.OAK_WALL_HANGING_SIGN), APRICORN_WOOD_TYPE))
val APRICORN_HANGING_SIGN = this.create(
"apricorn_hanging_sign",
CobblemonHangingSignBlock(BlockBehaviour.Properties.ofFullCopy(Blocks.OAK_HANGING_SIGN), APRICORN_WOOD_TYPE)
)
@JvmField
val APRICORN_WALL_HANGING_SIGN = this.create("apricorn_wall_hanging_sign", CobblemonWallHangingSignBlock(BlockBehaviour.Properties.ofFullCopy(Blocks.OAK_HANGING_SIGN), APRICORN_WOOD_TYPE))
@JvmField
@@ -52,9 +52,11 @@ object CobblemonCommands {
BedrockParticleCommand.register(dispatcher)
OpenDialogueCommand.register(dispatcher)
NPCEditCommand.register(dispatcher)
NPCDeleteCommand.register(dispatcher)
AbandonMultiTeam.register(dispatcher)
FreezePokemonCommand.register(dispatcher)
ApplyPlayerTextureCommand.register(dispatcher)
RunMolangScriptCommand.register(dispatcher)
// Possibly lock down registration if and only if under dev environment or running in an environment
// with a certain system environment variable set
@@ -0,0 +1,103 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common
import com.bedrockk.molang.runtime.MoLangRuntime
import com.bedrockk.molang.runtime.value.MoValue
import com.cobblemon.mod.common.CobblemonNetwork.sendPacket
import com.cobblemon.mod.common.api.data.DataRegistry
import com.cobblemon.mod.common.api.events.Cancelable
import com.cobblemon.mod.common.api.molang.ExpressionLike
import com.cobblemon.mod.common.api.molang.MoLangFunctions.setup
import com.cobblemon.mod.common.api.reactive.SimpleObservable
import com.cobblemon.mod.common.api.scripting.CobblemonScripts
import com.cobblemon.mod.common.net.messages.client.data.FlowRegistrySyncPacket
import com.cobblemon.mod.common.util.asExpressionLike
import com.cobblemon.mod.common.util.cobblemonResource
import com.cobblemon.mod.common.util.endsWith
import java.util.concurrent.ExecutionException
import net.minecraft.resources.ResourceLocation
import net.minecraft.server.level.ServerPlayer
import net.minecraft.server.packs.PackType
import net.minecraft.server.packs.resources.ResourceManager
/**
* Holds all the flows that are loaded from the server's data packs. A flow is foldered under the event identifier,
* which can be Cobblemon's namespace but can also be minecraft or any other namespace someone has added hooks for.
* The value of the map is a list of MoLang scripts that will execute when that event occurs.
*
* @author Hiroku
* @since February 24th, 2024
*/
object CobblemonFlows : DataRegistry {
override val id = cobblemonResource("flows")
override val observable = SimpleObservable<CobblemonFlows>()
override val type = PackType.SERVER_DATA
override fun sync(player: ServerPlayer) {
player.sendPacket(FlowRegistrySyncPacket(clientFlows.entries))
}
val runtime by lazy { MoLangRuntime().setup() } // Lazy for if someone adds to generalFunctions in MoLangFunctions
val clientFlows = hashMapOf<ResourceLocation, MutableList<ExpressionLike>>()
val flows = hashMapOf<ResourceLocation, MutableList<ExpressionLike>>()
override fun reload(manager: ResourceManager) {
clientFlows.clear()
flows.clear()
val unsortedFlows = mutableMapOf<ResourceLocation, MutableList<Pair<String, ExpressionLike>>>()
val folderBeforeNameRegex = ".*\\/([^\\/]+)\\/[^\\/]+\$".toRegex()
manager.listResources("flows") { path -> path.endsWith(CobblemonScripts.MOLANG_EXTENSION) }.forEach { (identifier, resource) ->
resource.openAsReader().use { stream ->
stream.buffered().use { reader ->
try {
val expression = reader.readText().asExpressionLike()
val event = folderBeforeNameRegex.find(identifier.path)?.groupValues?.get(1)
?: throw IllegalArgumentException("Invalid flow path: $identifier. Should have a folder structure that includes the name of the event being flowed.")
val flowKey = ResourceLocation.fromNamespaceAndPath(identifier.namespace, event)
unsortedFlows.putIfAbsent(flowKey, mutableListOf())
unsortedFlows[flowKey]!!.add(identifier.path to expression)
} catch (exception: Exception) {
throw ExecutionException("Error loading MoLang script for flow: $identifier", exception)
}
}
}
}
unsortedFlows.forEach { (key, value) ->
value.sortBy { it.first }
if (key.path.startsWith("flows/client/")) {
clientFlows.getOrPut(key) { mutableListOf() }.addAll(value.map { it.second })
} else {
flows.getOrPut(key) { mutableListOf() }.addAll(value.map { it.second })
}
}
Cobblemon.LOGGER.info("Loaded ${flows.size} flows and ${clientFlows.size} client flows")
observable.emit(this)
}
fun run(eventResourceLocation: ResourceLocation, context: Map<String, MoValue>, cancelable: Cancelable? = null) {
if (cancelable == null) {
runtime.environment.query.functions.remove("cancel")
} else {
runtime.environment.query.addFunction("cancel") { cancelable }
}
flows[eventResourceLocation]?.forEach {
if (cancelable != null && cancelable.isCanceled) {
return
}
it.resolve(runtime, context)
}
}
}
@@ -8,25 +8,22 @@
package com.cobblemon.mod.common
import com.cobblemon.mod.common.api.data.JsonDataRegistry
import com.cobblemon.mod.common.api.net.NetworkPacket
import com.mojang.brigadier.arguments.ArgumentType
import kotlin.reflect.KClass
import net.minecraft.commands.synchronization.ArgumentTypeInfo
import net.minecraft.network.chat.Component
import net.minecraft.resources.ResourceKey
import net.minecraft.resources.ResourceLocation
import net.minecraft.server.MinecraftServer
import net.minecraft.server.level.ServerPlayer
import net.minecraft.server.packs.PackType
import net.minecraft.server.packs.resources.PreparableReloadListener
import net.minecraft.server.packs.resources.ResourceManager
import net.minecraft.tags.TagKey
import net.minecraft.world.level.GameRules
import net.minecraft.world.level.ItemLike
import net.minecraft.world.level.biome.Biome
import net.minecraft.world.level.levelgen.GenerationStep
import net.minecraft.world.level.levelgen.placement.PlacedFeature
import kotlin.reflect.KClass
interface CobblemonImplementation {
val modAPI: ModAPI
@@ -171,14 +168,6 @@ interface CobblemonImplementation {
*/
fun server(): MinecraftServer?
/**
* Handles platform independent reloading of a [JsonDataRegistry].
*
* @param registry The [JsonDataRegistry] to reload.
* @param manager The [ResourceManager] to reload from.
*/
fun <T> reloadJsonRegistry(registry: JsonDataRegistry<T>, manager: ResourceManager): HashMap<ResourceLocation, T>
/**
* Registers an item to the [ComposterBlock].
*
@@ -186,16 +175,6 @@ interface CobblemonImplementation {
* @param chance The chance % of increasing the composter level, 0 to 1 expected.
*/
fun registerCompostable(item: ItemLike, chance: Float)
/**
* Registers a builtin resource pack.
*
* @param id The unique [ResourceLocation] of this pack.
* @param title The title displayed in the resource pack GUI, the description is still a part of the pack metadata.
* @param activationBehaviour The [ResourcePackActivationBehaviour] for this pack.
*/
fun registerBuiltinResourcePack(id: ResourceLocation, title: Component, activationBehaviour: ResourcePackActivationBehaviour)
}
enum class ResourcePackActivationBehaviour {
@@ -19,7 +19,7 @@ import com.cobblemon.mod.common.api.text.gray
import com.cobblemon.mod.common.block.BerryBlock
import com.cobblemon.mod.common.block.MintBlock
import com.cobblemon.mod.common.block.MintBlock.MintType
import com.cobblemon.mod.common.client.pokedex.PokedexTypes
import com.cobblemon.mod.common.client.pokedex.PokedexType
import com.cobblemon.mod.common.entity.boat.CobblemonBoatType
import com.cobblemon.mod.common.item.*
import com.cobblemon.mod.common.item.armor.CobblemonArmorTrims
@@ -54,6 +54,9 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
override val registry: Registry<Item> = BuiltInRegistries.ITEM
override val resourceKey: ResourceKey<Registry<Item>> = Registries.ITEM
@JvmField
val NPC_EDITOR = create("npc_editor", CobblemonItem(Item.Properties().stacksTo(1)))
@JvmField
val pokeBalls = mutableListOf<PokeBallItem>()
@JvmField
@@ -155,19 +158,19 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
val pokedexes = mutableListOf<PokedexItem>()
@JvmField
val POKEDEX_RED = pokedexItem(PokedexTypes.RED)
val POKEDEX_RED = pokedexItem(PokedexType.RED)
@JvmField
val POKEDEX_YELLOW = pokedexItem(PokedexTypes.YELLOW)
val POKEDEX_YELLOW = pokedexItem(PokedexType.YELLOW)
@JvmField
val POKEDEX_GREEN = pokedexItem(PokedexTypes.GREEN)
val POKEDEX_GREEN = pokedexItem(PokedexType.GREEN)
@JvmField
val POKEDEX_BLUE = pokedexItem(PokedexTypes.BLUE)
val POKEDEX_BLUE = pokedexItem(PokedexType.BLUE)
@JvmField
val POKEDEX_PINK = pokedexItem(PokedexTypes.PINK)
val POKEDEX_PINK = pokedexItem(PokedexType.PINK)
@JvmField
val POKEDEX_BLACK = pokedexItem(PokedexTypes.BLACK)
val POKEDEX_BLACK = pokedexItem(PokedexType.BLACK)
@JvmField
val POKEDEX_WHITE = pokedexItem(PokedexTypes.WHITE)
val POKEDEX_WHITE = pokedexItem(PokedexType.WHITE)
@JvmField
val VIVICHOKE = compostableItem("vivichoke")
@@ -389,6 +392,9 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
@JvmField val BERRY_JUICE = this.create("berry_juice", BerryJuiceItem())
@JvmField
val GALARICA_NUTS = create("galarica_nuts", GalaricaNutItem())
// Medicine
@JvmField
val RARE_CANDY = candyItem("rare_candy") { _, pokemon -> pokemon.getExperienceToNextLevel() }
@@ -439,6 +445,7 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
.saturationModifier(1.2F)
.effect(MobEffectInstance(MobEffects.ABSORPTION, 900, 0), 1F)
.alwaysEdible()
.usingConvertsTo(Items.BOWL)
.build())) {
override fun finishUsingItem(stack: ItemStack, world: Level, user: LivingEntity): ItemStack {
user.removeAllEffects()
@@ -474,7 +481,7 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
@JvmField
val HEAL_POWDER = create("heal_powder", HealPowderItem())
@JvmField
val LEEK_AND_POTATO_STEW = create("leek_and_potato_stew", Item(Item.Properties().food(FoodProperties.Builder().nutrition(8).saturationModifier(0.6f).build()).stacksTo(1)))
val LEEK_AND_POTATO_STEW = create("leek_and_potato_stew", Item(Item.Properties().food(FoodProperties.Builder().nutrition(8).saturationModifier(0.6f).usingConvertsTo(Items.BOWL).build()).stacksTo(1)))
@JvmField
val REVIVE = create("revive", ReviveItem(max = false))
@JvmField
@@ -1242,13 +1249,13 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
private fun candyItem(name: String, calculator: CandyItem.Calculator): CandyItem = this.create(name, CandyItem(calculator))
private fun pokerodItem(pokeRodId: ResourceLocation): PokerodItem {
val settings = Item.Properties().stacksTo(1).durability(Items.FISHING_ROD.components().get(DataComponents.MAX_DAMAGE)!!)
val settings = Item.Properties().stacksTo(1).durability(256)
val item = create(pokeRodId.path, PokerodItem(pokeRodId, settings))
pokeRods.add(item)
return item
}
private fun pokedexItem(type: PokedexTypes): PokedexItem {
private fun pokedexItem(type: PokedexType): PokedexItem {
val item = create("pokedex_${type.name.lowercase()}", PokedexItem(type))
pokedexes.add(item)
return item
@@ -54,6 +54,7 @@ import com.cobblemon.mod.common.client.net.toast.ToastPacketHandler
import com.cobblemon.mod.common.client.net.trade.*
import com.cobblemon.mod.common.net.PacketRegisterInfo
import com.cobblemon.mod.common.net.messages.client.PlayerInteractOptionsPacket
import com.cobblemon.mod.common.net.messages.client.SetClientPlayerDataPacket
import com.cobblemon.mod.common.net.messages.client.animation.PlayPosableAnimationPacket
import com.cobblemon.mod.common.net.messages.client.battle.*
import com.cobblemon.mod.common.net.messages.client.callback.OpenMoveCallbackPacket
@@ -74,6 +75,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.pokedex.ServerConfirmedRegisterPacket
import com.cobblemon.mod.common.net.messages.client.pokemon.update.*
import com.cobblemon.mod.common.net.messages.client.pokemon.update.evolution.AddEvolutionPacket
import com.cobblemon.mod.common.net.messages.client.pokemon.update.evolution.ClearEvolutionsPacket
@@ -85,7 +87,6 @@ import com.cobblemon.mod.common.net.messages.client.spawn.SpawnNPCPacket
import com.cobblemon.mod.common.net.messages.client.spawn.SpawnPokeballPacket
import com.cobblemon.mod.common.net.messages.client.spawn.SpawnPokemonPacket
import com.cobblemon.mod.common.net.messages.client.starter.OpenStarterUIPacket
import com.cobblemon.mod.common.net.messages.client.SetClientPlayerDataPacket
import com.cobblemon.mod.common.net.messages.client.storage.RemoveClientPokemonPacket
import com.cobblemon.mod.common.net.messages.client.storage.SwapClientPokemonPacket
import com.cobblemon.mod.common.net.messages.client.storage.party.InitializePartyPacket
@@ -94,10 +95,13 @@ import com.cobblemon.mod.common.net.messages.client.storage.party.SetPartyPokemo
import com.cobblemon.mod.common.net.messages.client.storage.party.SetPartyReferencePacket
import com.cobblemon.mod.common.net.messages.client.storage.pc.*
import com.cobblemon.mod.common.net.messages.client.toast.ToastPacket
import com.cobblemon.mod.common.net.messages.client.trade.*
import com.cobblemon.mod.common.net.messages.client.ui.InteractPokemonUIPacket
import com.cobblemon.mod.common.net.messages.client.ui.PokedexUIPacket
import com.cobblemon.mod.common.net.messages.client.ui.SummaryUIPacket
import com.cobblemon.mod.common.net.messages.server.*
import com.cobblemon.mod.common.net.messages.server.battle.*
import com.cobblemon.mod.common.net.messages.server.block.AdjustBlockEntityViewerCountPacket
import com.cobblemon.mod.common.net.messages.server.callback.move.MoveSelectCancelledPacket
import com.cobblemon.mod.common.net.messages.server.callback.move.MoveSelectedPacket
import com.cobblemon.mod.common.net.messages.server.callback.party.PartyPokemonSelectedPacket
@@ -110,6 +114,7 @@ import com.cobblemon.mod.common.net.messages.server.npc.SaveNPCPacket
import com.cobblemon.mod.common.net.messages.server.pasture.PasturePokemonPacket
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
import com.cobblemon.mod.common.net.messages.server.pokedex.scanner.StartScanningPacket
import com.cobblemon.mod.common.net.messages.server.pokemon.interact.InteractPokemonPacket
import com.cobblemon.mod.common.net.messages.server.pokemon.update.SetNicknamePacket
@@ -125,7 +130,10 @@ import com.cobblemon.mod.common.net.messages.server.storage.pc.MovePartyPokemonT
import com.cobblemon.mod.common.net.messages.server.storage.pc.ReleasePCPokemonPacket
import com.cobblemon.mod.common.net.messages.server.storage.pc.SwapPCPokemonPacket
import com.cobblemon.mod.common.net.messages.server.storage.pc.UnlinkPlayerFromPCPacket
import com.cobblemon.mod.common.net.messages.server.trade.*
import com.cobblemon.mod.common.net.serverhandling.*
import com.cobblemon.mod.common.net.serverhandling.battle.*
import com.cobblemon.mod.common.net.serverhandling.block.AdjustBlockEntityViewerCountHandler
import com.cobblemon.mod.common.net.serverhandling.callback.move.MoveSelectCancelledHandler
import com.cobblemon.mod.common.net.serverhandling.callback.move.MoveSelectedHandler
import com.cobblemon.mod.common.net.serverhandling.callback.party.PartyPokemonSelectedHandler
@@ -139,6 +147,8 @@ import com.cobblemon.mod.common.net.serverhandling.npc.SaveNPCHandler
import com.cobblemon.mod.common.net.serverhandling.pasture.PasturePokemonHandler
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
import com.cobblemon.mod.common.net.serverhandling.pokedex.scanner.StartScanningHandler
import com.cobblemon.mod.common.net.serverhandling.pokemon.interact.InteractPokemonHandler
import com.cobblemon.mod.common.net.serverhandling.pokemon.update.SetNicknameHandler
import com.cobblemon.mod.common.net.serverhandling.starter.RequestStarterScreenHandler
@@ -156,19 +166,6 @@ import com.cobblemon.mod.common.net.serverhandling.storage.pc.MovePartyPokemonTo
import com.cobblemon.mod.common.net.serverhandling.storage.pc.ReleasePartyPokemonHandler
import com.cobblemon.mod.common.net.serverhandling.storage.pc.SwapPCPokemonHandler
import com.cobblemon.mod.common.net.serverhandling.storage.pc.UnlinkPlayerFromPCHandler
import com.cobblemon.mod.common.net.serverhandling.trade.AcceptTradeRequestHandler
import com.cobblemon.mod.common.net.serverhandling.trade.CancelTradeHandler
import com.cobblemon.mod.common.net.serverhandling.trade.ChangeTradeAcceptanceHandler
import com.cobblemon.mod.common.net.serverhandling.trade.OfferTradeHandler
import com.cobblemon.mod.common.net.serverhandling.trade.UpdateTradeOfferHandler
import com.cobblemon.mod.common.net.messages.server.battle.*
import com.cobblemon.mod.common.net.serverhandling.battle.*
import com.cobblemon.mod.common.net.messages.client.pokedex.ServerConfirmedRegisterPacket
import com.cobblemon.mod.common.net.messages.client.trade.*
import com.cobblemon.mod.common.net.messages.server.pokedex.scanner.FinishScanningPacket
import com.cobblemon.mod.common.net.messages.server.trade.*
import com.cobblemon.mod.common.net.serverhandling.pokedex.scanner.FinishScanningHandler
import com.cobblemon.mod.common.net.serverhandling.pokedex.scanner.StartScanningHandler
import com.cobblemon.mod.common.net.serverhandling.trade.*
import com.cobblemon.mod.common.util.server
import net.minecraft.server.level.ServerPlayer
@@ -306,6 +303,7 @@ object CobblemonNetwork {
list.add(PacketRegisterInfo(PokedexDexSyncPacket.ID, PokedexDexSyncPacket::decode, DataRegistrySyncPacketHandler()))
list.add(PacketRegisterInfo(DexEntrySyncPacket.ID, DexEntrySyncPacket::decode, DataRegistrySyncPacketHandler()))
list.add(PacketRegisterInfo(FishingBaitRegistrySyncPacket.ID, FishingBaitRegistrySyncPacket::decode, DataRegistrySyncPacketHandler()))
list.add(PacketRegisterInfo(FlowRegistrySyncPacket.ID, FlowRegistrySyncPacket::decode, DataRegistrySyncPacketHandler()))
// Effects
list.add(PacketRegisterInfo(SpawnSnowstormParticlePacket.ID, SpawnSnowstormParticlePacket::decode, SpawnSnowstormParticleHandler))
@@ -356,7 +354,7 @@ object CobblemonNetwork {
list.add(PacketRegisterInfo(CloseNPCEditorPacket.ID, CloseNPCEditorPacket::decode, CloseNPCEditorHandler))
list.add(PacketRegisterInfo(OpenNPCEditorPacket.ID, OpenNPCEditorPacket::decode, OpenNPCEditorHandler))
//Pokedex scanning
// Pokédex scanning
list.add(PacketRegisterInfo(ServerConfirmedRegisterPacket.ID, ServerConfirmedRegisterPacket::decode, ServerConfirmedRegisterHandler))
return list
}
@@ -414,7 +412,7 @@ object CobblemonNetwork {
list.add(PacketRegisterInfo(OfferTradePacket.ID, OfferTradePacket::decode, OfferTradeHandler))
list.add(PacketRegisterInfo(UpdateTradeOfferPacket.ID, UpdateTradeOfferPacket::decode, UpdateTradeOfferHandler))
// Pokedex scanning
// Pokédex scanning
list.add(PacketRegisterInfo(StartScanningPacket.ID, StartScanningPacket::decode, StartScanningHandler))
list.add(PacketRegisterInfo(FinishScanningPacket.ID, FinishScanningPacket::decode, FinishScanningHandler))
@@ -423,6 +421,9 @@ object CobblemonNetwork {
list.add(PacketRegisterInfo(UnpasturePokemonPacket.ID, UnpasturePokemonPacket::decode, UnpasturePokemonHandler))
list.add(PacketRegisterInfo(UnpastureAllPokemonPacket.ID, UnpastureAllPokemonPacket::decode, UnpastureAllPokemonHandler))
// Block entity
list.add(PacketRegisterInfo(AdjustBlockEntityViewerCountPacket.ID, AdjustBlockEntityViewerCountPacket::decode, AdjustBlockEntityViewerCountHandler))
// Move select packets
list.add(PacketRegisterInfo(MoveSelectedPacket.ID, MoveSelectedPacket::decode, MoveSelectedHandler))
list.add(PacketRegisterInfo(MoveSelectCancelledPacket.ID, MoveSelectCancelledPacket::decode, MoveSelectCancelledHandler))
@@ -46,16 +46,6 @@ object CobblemonSounds : PlatformRegistry<Registry<SoundEvent>, ResourceKey<Regi
@JvmField
val HEALING_MACHINE_ACTIVE = this.create("block.healing_machine.active")
@JvmField
val POKE_BALL_CAPTURE_STARTED = this.create("poke_ball.capture_started")
@JvmField
val POKE_BALL_CAPTURE_SUCCEEDED = this.create("poke_ball.capture_succeeded")
@JvmField
val POKE_BALL_SHAKE = this.create("poke_ball.shake")
@JvmField
val POKE_BALL_OPEN = this.create("poke_ball.open")
@JvmField
val POKE_BALL_SHINY_OPEN = this.create("poke_ball.shiny_open")
@JvmField
val POKE_BALL_HIT = this.create("poke_ball.hit")
@JvmField
@@ -108,6 +98,8 @@ object CobblemonSounds : PlatformRegistry<Registry<SoundEvent>, ResourceKey<Regi
@JvmField
val PVW_BATTLE = this.create("battle.pvw.default")
@JvmField
val MEDICINE_CANDY_USE = this.create("item.medicine.candy.use")
@JvmField
val MEDICINE_HERB_USE = this.create("item.medicine.herb.use")
@JvmField
@@ -266,6 +258,13 @@ object CobblemonSounds : PlatformRegistry<Registry<SoundEvent>, ResourceKey<Regi
RELIC_COIN_SACK_STEP
)
@JvmField
val MOVE_QUICKATTACK_TARGET = this.create("move.quickattack.target")
@JvmField
val MOVE_PURSUIT_TARGET = this.create("move.pursuit.target")
@JvmField
val MOVE_PSYCHIC_TARGET = this.create("move.psychic.target")
@JvmField
val IMPACT_NORMAL = this.create("impact.normal")
@JvmField
@@ -77,7 +77,7 @@ object CobblemonTradeOffers {
)
VillagerProfession.FISHERMAN -> listOf(
VillagerTradeOffer(VillagerProfession.FISHERMAN, 5, listOf(
VillagerTrades.ItemsForEmeralds(CobblemonItems.POKEROD_SMITHING_TEMPLATE, 12, 3, 30)
VillagerTrades.ItemsForEmeralds(CobblemonItems.POKEROD_SMITHING_TEMPLATE, 12, 1, 3, 30)
))
)
else -> emptyList()
@@ -55,6 +55,8 @@ object CobblemonCriteria : PlatformRegistry<Registry<CriterionTrigger<*>>, Resou
val CAST_POKE_ROD = this.create("cast_poke_rod", SimpleCriterionTrigger(CastPokeRodCriterionCondition.CODEC))
val REEL_IN_POKEMON = this.create("reel_in_pokemon", SimpleCriterionTrigger(ReelInPokemonCriterionCondition.CODEC))
// Advancement criteria for [grow_tumblestone.json]
val PLANT_TUMBLESTONE = this.create("plant_tumblestone", SimpleCriterionTrigger(PlantTumblestoneCriterion.CODEC))
@@ -8,26 +8,30 @@
package com.cobblemon.mod.common.advancement.criterion
import com.cobblemon.mod.common.util.asIdentifierDefaultingNamespace
import com.mojang.serialization.Codec
import com.mojang.serialization.codecs.PrimitiveCodec
import com.mojang.serialization.codecs.RecordCodecBuilder
import java.util.Optional
import net.minecraft.advancements.critereon.ContextAwarePredicate
import net.minecraft.advancements.critereon.EntityPredicate
import net.minecraft.server.level.ServerPlayer
import net.minecraft.resources.ResourceLocation
class CastPokeRodContext(val baitId: ResourceLocation)
class CastPokeRodCriterionCondition(
playerCtx: Optional<ContextAwarePredicate>,
val hasBait: Boolean
): SimpleCriterionCondition<Boolean>(playerCtx) {
playerCtx: Optional<ContextAwarePredicate>,
val baitId: String
): SimpleCriterionCondition<CastPokeRodContext>(playerCtx) {
companion object {
val CODEC: Codec<CastPokeRodCriterionCondition> = RecordCodecBuilder.create { it.group(
EntityPredicate.ADVANCEMENT_CODEC.optionalFieldOf("player").forGetter(CastPokeRodCriterionCondition::playerCtx),
PrimitiveCodec.BOOL.fieldOf("hasBait").forGetter(CastPokeRodCriterionCondition::hasBait)
).apply(it, ::CastPokeRodCriterionCondition) }
EntityPredicate.ADVANCEMENT_CODEC.optionalFieldOf("player").forGetter(CastPokeRodCriterionCondition::playerCtx),
Codec.STRING.optionalFieldOf("baitId", "empty_bait").forGetter(CastPokeRodCriterionCondition::baitId)
).apply(it, { playerCtx, baitId -> CastPokeRodCriterionCondition(playerCtx, baitId.ifEmpty { "empty_bait" }) }) }
}
override fun matches(player: ServerPlayer, context: Boolean): Boolean {
return hasBait == context
override fun matches(player: ServerPlayer, context: CastPokeRodContext): Boolean {
return (context.baitId == this.baitId.asIdentifierDefaultingNamespace() || this.baitId.equals("empty_bait"))
}
}
}
@@ -26,76 +26,25 @@ class PartyCheckCriterion(
companion object {
val CODEC: Codec<PartyCheckCriterion> = RecordCodecBuilder.create { it.group(
EntityPredicate.ADVANCEMENT_CODEC.optionalFieldOf("player").forGetter(PartyCheckCriterion::playerCtx),
ResourceLocation.CODEC.listOf().optionalFieldOf("id", listOf()).forGetter(PartyCheckCriterion::party)
ResourceLocation.CODEC.listOf().optionalFieldOf("party", listOf()).forGetter(PartyCheckCriterion::party)
).apply(it, ::PartyCheckCriterion) }
}
override fun matches(player: ServerPlayer, context: PlayerPartyStore): Boolean {
val matches = mutableListOf<ResourceLocation>()
party.forEach {
if (it == "any".asIdentifierDefaultingNamespace()) {
if (it == "any".asIdentifierDefaultingNamespace("minecraft") || it == "any".asIdentifierDefaultingNamespace()) {
matches.add(it)
}
}
val partyCount = context.count()
if (matches.containsAll(party) && party.size == partyCount && matches.size == partyCount) return true
matches.clear()
context.iterator().forEach {
if (party.contains(it.species.resourceIdentifier)) {
matches.add(it.species.resourceIdentifier)
}
}
return matches.containsAll(party) && matches.size == partyCount
return matches.containsAll(party) && matches.size == party.size
}
}
/*class PartyCheckCriterion(id: Identifier, entity: LootContextPredicate) : SimpleCriterionCondition<PartyCheckContext>(id, entity){
val party = mutableListOf<Identifier>()
override fun toJson(json: JsonObject) {
json.add("party", JsonArray(party.size).also {
party.forEach { pokemon -> it.add(pokemon.toString()) }
})
}
override fun fromJson(json: JsonObject) {
party.clear()
json.getAsJsonArray("party").forEach { element ->
party.add(element.asString.asIdentifierDefaultingNamespace())
}
}
override fun matches(player: ServerPlayer, context: PartyCheckContext): Boolean {
val playerParty = player.party()
val matches = mutableListOf<Identifier>()
party.forEach {
if (it == "any".asIdentifierDefaultingNamespace()) {
matches.add(it)
}
}
val partyCount = playerParty.count()
if (matches.containsAll(party) && party.size == partyCount && matches.size == partyCount) return true
playerParty.iterator().forEach {
if (party.contains(it.species.resourceIdentifier)) {
matches.add(it.species.resourceIdentifier)
}
}
return matches.containsAll(party) && matches.size == partyCount
}
}
open class PartyCheckContext(val party : PlayerPartyStore)*/
@@ -0,0 +1,39 @@
/*
* 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.advancement.criterion
import com.cobblemon.mod.common.util.asIdentifierDefaultingNamespace
import com.mojang.serialization.Codec
import com.mojang.serialization.codecs.RecordCodecBuilder
import java.util.Optional
import net.minecraft.advancements.critereon.ContextAwarePredicate
import net.minecraft.advancements.critereon.EntityPredicate
import net.minecraft.server.level.ServerPlayer
import net.minecraft.resources.ResourceLocation
class ReelInPokemonContext(val pokemonId : ResourceLocation, val baitId: ResourceLocation)
class ReelInPokemonCriterionCondition(
playerCtx: Optional<ContextAwarePredicate>,
val pokemonId: String,
val baitId: String
) : SimpleCriterionCondition<ReelInPokemonContext>(playerCtx) {
companion object {
val CODEC: Codec<ReelInPokemonCriterionCondition> = RecordCodecBuilder.create { it.group(
EntityPredicate.ADVANCEMENT_CODEC.optionalFieldOf("player").forGetter { it.playerCtx },
Codec.STRING.optionalFieldOf("pokemonId", "any").forGetter { it.pokemonId },
Codec.STRING.optionalFieldOf("baitId", "empty_bait").forGetter { it.baitId }
).apply(it, { playerCtx, pokemonId, baitId -> ReelInPokemonCriterionCondition(playerCtx, pokemonId, baitId.ifEmpty { "empty_bait" }) }) }
}
override fun matches(player: ServerPlayer, context: ReelInPokemonContext): Boolean {
return (context.pokemonId == this.pokemonId.asIdentifierDefaultingNamespace() || this.pokemonId == "any") && (context.baitId == this.baitId.asIdentifierDefaultingNamespace() || this.baitId == "empty_bait")
}
}
@@ -0,0 +1,119 @@
# Brain Configuration
A "Brain" is a Java Edition AI concept for more modern entities. It has tasks that are listed inside of 'activities',
and in some cases a schedule which determines which activities will occur during different times of the day. There is
also a set of core activities, and a default activity. In Minecraft, the most complex usage of the Brain AI system
is on villagers which have schedules that control their behaviour during the day and night as well as child villager play behaviours.
Cobblemon's NPCs use the Brain AI system. As part of that, Cobblemon added the concept of a Brain Configuration
that allows Java Edition brains to be configured in a more data-driven way.
By default, without any brain configuration, the default activity will be `minecraft:idle` and the core activities will be `[minecraft:core]`.
The activities would not have any tasks though.
## Possible Activities
The activities that can be used in brains is determined by code and cannot be added to using datapacks. Note that except for
when used as defaults and core activities, these are purely names and what you use them for is entirely up to you.
The activities that exist in Minecraft are:
- `minecraft:core`: The core activity intended to be used for fundamental actions like floating in water and looking at look targets.
- `minecraft:idle`: The idle activity is used when the entity is not doing anything else. This is typically used for things like wandering and other random actions.
- `minecraft:work`: The work activity is used for actions that are related to the entity's job. For villagers, this is things like farming, smithing, and other job-related tasks.
- `minecraft:play`
- `minecraft:rest`: The rest activity is used in villagers for the activity that moves them to a bed and hops into it.
- `minecraft:meet`: The meet activity is used in villagers for going to the meeting place and gossipping with other NPCs.
- `minecraft:panic`: The panic activity is used in villagers for when they are panicking and fleeing, usually from an attacker.
- `minecraft:raid`
- `minecraft:pre_raid`: The raid activity is used in villagers for what they do when a raid is about to start, like running to a safe location during a raid.
- `minecraft:hide`
- `minecraft:fight`: Intended to be used when engaging in combat.
- `minecraft:celebrate`
- `minecraft:admire_item`
- `minecraft:avoid`
- `minecraft:ride`
- `minecraft:play_dead`
- `minecraft:long_jump`
- `minecraft:ram`
- `minecraft:tongue`
- `minecraft:swim`
- `minecraft:lay_spawn`
- `minecraft:sniff`
- `minecraft:investigate`
- `minecraft:roar`
- `minecraft:emerge`
- `minecraft:dig`
The activities that were added by Cobblemon are:
- `cobblemon:battling`: For when the entity is in a Pokémon battle.
- `cobblemon:action_effect`: For when the entity is performing an action effect. Usually registered as an almost empty activity that simply prevents the entity from doing other things.
- `cobblemon:npc_chatting`: Intended for NPC entities using dialogue so that they look at their chat partner and do nothing else.
## Brain Configuration Format
A brain is configured using a series of "Brain Configurations". Each configuration is a JSON object that contains
a "type" field which determines the action to perform when configuring a brain. Many different types are available.
### script
The `script` type executes a MoLang script which will apply some changes to the brain.
- `script`: The MoLang script to execute. This will be a resource location for the `molang` datapack folder. Something like `cobblemon:some_script`.
- `condition`: A MoLang expression (with `q.entity` as the entity) that determines if the script should be executed. Defaults to `"true"`.
### add_tasks_to_activity
The 'add_tasks_to_activity' type adds a list of tasks to an activity.
- `activity`: The activity to add the tasks to. This must be a pre-existing activity - a brain configuration cannot
create new activities.
- `condition`: A MoLang expression (with `q.entity` as the entity) that determines if the tasks should be added. If this
is not present, the tasks will always be added.
- `tasksByPriority`: A map of task priorities to lists of tasks to add to the activity. Each task is a JSON object with a "type" field that determines the
task to add or in simple cases can just be the type as a simple JSON primitive to use default properties. Many different types of task config are available. See [Task Configuration](./task/README.md).
The priority of the task is used to determine the execution order each tick. This usually does not matter, but in some cases
where the execution of one task will move to a different activity or otherwise prevent another task, the priority matters a lot.
As an example, a task that moves to nearby healing machines will set a walk target which prevents the use of the healing machine,
so the use task would need to have a lower priority or be earlier in the list so that it runs sooner.
Example, making sure `heal_using_healing_machine` comes before `go_to_healing_machine`:
```json
{
"type": "add_tasks_to_activity",
"activity": "minecraft:idle",
"tasksByPriority": {
"1": [
{
"type": "cobblemon:heal_using_healing_machine",
"horizontalUseRange": "2"
},
"cobblemon:go_to_healing_machine"
]
}
}
```
Note that when specifying tasks, you can either use an object format with the "type" property, or if you want to use only
default parameters for the task you can simply state the type as a string. The above example uses both formats.
### set_core_activities
The `set_core_activities` type sets the core activities of the brain. It has only one property, `activities`, which is a list of activities.
### set_default_activity
The `set_default_activity` type sets the default activity of the brain. It has only one property, `activity`, which is the activity to set as the default.
### apply_preset
The `apply_preset` type applies a preset to the brain. Brain presets are JSON arrays under the `brain_presets` datapack folder.
This is a way to apply a set of configurations to the brain.
- `preset`: The name of the preset to apply. This is the name of the file in the `brain_presets` folder without the `.json` extension.
- `condition`: A MoLang expression (with `q.entity` as the entity) that determines if the preset should be applied. Defaults to `"true"`.
Example brain preset (`uses_healing_machine.json`):
```json
[
{
"type": "add_tasks_to_activity",
"activity": "idle",
"tasksByPriority": {
"1": [
"heal_using_healing_machine",
"go_to_healing_machine"
]
}
}
]
```
@@ -0,0 +1,31 @@
/*
* 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.struct.QueryStruct
import com.cobblemon.mod.common.api.ai.BrainConfigurationContext
import com.cobblemon.mod.common.entity.PosableEntity
import com.cobblemon.mod.common.util.asExpression
import com.cobblemon.mod.common.util.resolveBoolean
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.VillagerCalmDown
class CalmDownTaskConfig : SingleTaskConfig {
var condition = "true".asExpression()
override fun createTask(
entity: LivingEntity,
brainConfigurationContext: BrainConfigurationContext
): BehaviorControl<in LivingEntity>? {
runtime.withQueryValue("entity", (entity as? PosableEntity)?.struct ?: QueryStruct(hashMapOf()))
if (!runtime.resolveBoolean(condition)) return null
return VillagerCalmDown.create()
}
}
@@ -0,0 +1,75 @@
/*
* 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.struct.QueryStruct
import com.cobblemon.mod.common.CobblemonMemories
import com.cobblemon.mod.common.api.ai.BrainConfigurationContext
import com.cobblemon.mod.common.battles.BattleRegistry
import com.cobblemon.mod.common.entity.PosableEntity
import com.cobblemon.mod.common.entity.npc.NPCEntity
import com.cobblemon.mod.common.util.asExpression
import com.cobblemon.mod.common.util.resolveBoolean
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.declarative.BehaviorBuilder
import net.minecraft.world.entity.ai.behavior.declarative.Trigger
import net.minecraft.world.entity.ai.memory.MemoryModuleType
class ExitBattleWhenHurtTaskConfig : SingleTaskConfig {
var condition = "true".asExpression()
var includePassiveDamage = true
override fun createTask(
entity: LivingEntity,
brainConfigurationContext: BrainConfigurationContext
): BehaviorControl<in LivingEntity>? {
runtime.withQueryValue("entity", (entity as? PosableEntity)?.struct ?: QueryStruct(hashMapOf()))
if (!runtime.resolveBoolean(condition)) return null
if (entity is NPCEntity) {
fun cancelNPCBattles(npcEntity: NPCEntity): Boolean {
val battles = npcEntity.battleIds.mapNotNull(BattleRegistry::getBattle)
battles.forEach { it.end() }
return battles.isNotEmpty()
}
return if (includePassiveDamage) {
BehaviorBuilder.create {
it.group(it.present(MemoryModuleType.HURT_BY), it.present(CobblemonMemories.NPC_BATTLING))
.apply(it) { _, _ -> Trigger { world, entity, _ -> return@Trigger cancelNPCBattles(entity as NPCEntity) } }
}
} else {
BehaviorBuilder.create {
it.group(it.present(MemoryModuleType.HURT_BY_ENTITY), it.present(CobblemonMemories.NPC_BATTLING))
.apply(it) { _, _ -> Trigger { world, entity, _ -> return@Trigger cancelNPCBattles(entity as NPCEntity) } }
}
}
} else { return null }/* else if (entity is PokemonEntity) { TODO uncomment when pokemon have brain :)
fun cancelPokemonBattle(pokemonEntity: PokemonEntity): Boolean {
val battle = BattleRegistry.getBattle(pokemonEntity.battleId ?: return false)
battle?.end()
return battle != null
}
return if (includePassiveDamage) {
BehaviorBuilder.create {
it.group(it.present(MemoryModuleType.HURT_BY), it.present(CobblemonMemories.POKEMON_BATTLING))
.apply(it) { _, _ -> Trigger { world, entity, _ -> return@Trigger cancelPokemonBattle(entity as PokemonEntity) } }
}
} else {
BehaviorBuilder.create {
it.group(it.present(MemoryModuleType.HURT_BY_ENTITY), it.present(CobblemonMemories.POKEMON_BATTLING))
.apply(it) { _, _ -> Trigger { world, entity, _ -> return@Trigger cancelPokemonBattle(entity as PokemonEntity) } }
}
}
}*/
}
}
@@ -0,0 +1,44 @@
/*
* 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.struct.QueryStruct
import com.cobblemon.mod.common.api.ai.BrainConfigurationContext
import com.cobblemon.mod.common.api.ai.WrapperLivingEntityTask
import com.cobblemon.mod.common.entity.PosableEntity
import com.cobblemon.mod.common.util.asExpression
import com.cobblemon.mod.common.util.resolveBoolean
import com.cobblemon.mod.common.util.resolveFloat
import com.cobblemon.mod.common.util.resolveInt
import com.cobblemon.mod.common.util.withQueryValue
import net.minecraft.world.entity.LivingEntity
import net.minecraft.world.entity.PathfinderMob
import net.minecraft.world.entity.ai.behavior.BehaviorControl
import net.minecraft.world.entity.ai.behavior.SetWalkTargetAwayFrom
import net.minecraft.world.entity.ai.memory.MemoryModuleType
class FleeAttackerTaskConfig : SingleTaskConfig {
var condition = "true".asExpression()
var speedMultiplier = "0.5".asExpression()
var desiredDistance = "9".asExpression()
override fun createTask(
entity: LivingEntity,
brainConfigurationContext: BrainConfigurationContext
): BehaviorControl<in LivingEntity>? {
runtime.withQueryValue("entity", (entity as? PosableEntity)?.struct ?: QueryStruct(hashMapOf()))
if (!runtime.resolveBoolean(condition) || entity !is PathfinderMob) return null
val speedMultiplier = runtime.resolveFloat(speedMultiplier)
val desiredDistance = runtime.resolveInt(desiredDistance)
return WrapperLivingEntityTask(
SetWalkTargetAwayFrom.entity(MemoryModuleType.HURT_BY_ENTITY, speedMultiplier, desiredDistance, false),
PathfinderMob::class.java
)
}
}
@@ -0,0 +1,44 @@
/*
* 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.struct.QueryStruct
import com.cobblemon.mod.common.api.ai.BrainConfigurationContext
import com.cobblemon.mod.common.api.ai.WrapperLivingEntityTask
import com.cobblemon.mod.common.entity.PosableEntity
import com.cobblemon.mod.common.util.asExpression
import com.cobblemon.mod.common.util.resolveBoolean
import com.cobblemon.mod.common.util.resolveFloat
import com.cobblemon.mod.common.util.resolveInt
import com.cobblemon.mod.common.util.withQueryValue
import net.minecraft.world.entity.LivingEntity
import net.minecraft.world.entity.PathfinderMob
import net.minecraft.world.entity.ai.behavior.BehaviorControl
import net.minecraft.world.entity.ai.behavior.SetWalkTargetAwayFrom
import net.minecraft.world.entity.ai.memory.MemoryModuleType
class FleeNearestHostileTaskConfig : SingleTaskConfig {
var condition = "true".asExpression()
var speedMultiplier = "0.5".asExpression()
var desiredDistance = "9".asExpression()
override fun createTask(
entity: LivingEntity,
brainConfigurationContext: BrainConfigurationContext
): BehaviorControl<in LivingEntity>? {
runtime.withQueryValue("entity", (entity as? PosableEntity)?.struct ?: QueryStruct(hashMapOf()))
if (!runtime.resolveBoolean(condition) || entity !is PathfinderMob) return null
val speedMultiplier = runtime.resolveFloat(speedMultiplier)
val desiredDistance = runtime.resolveInt(desiredDistance)
return WrapperLivingEntityTask(
SetWalkTargetAwayFrom.entity(MemoryModuleType.NEAREST_HOSTILE, speedMultiplier, desiredDistance, false),
PathfinderMob::class.java
)
}
}
@@ -26,14 +26,14 @@ import net.minecraft.world.entity.ai.behavior.BehaviorControl
class FollowWalkTargetTaskConfig : SingleTaskConfig {
val condition: ExpressionLike = "true".asExpressionLike()
val minRunTime: Expression = "150".asExpression()
val maxRunTime: Expression = "250".asExpression()
val minRunTicks: Expression = "150".asExpression()
val maxRunTicks: Expression = "250".asExpression()
override fun createTask(entity: LivingEntity, brainConfigurationContext: BrainConfigurationContext): BehaviorControl<LivingEntity>? {
runtime.withQueryValue("entity", (entity as? PosableEntity)?.struct ?: QueryStruct(hashMapOf()))
if (!runtime.resolveBoolean(condition)) return null
return WrapperLivingEntityTask(
FollowWalkTargetTask(runtime.resolveInt(minRunTime), runtime.resolveInt(maxRunTime)),
FollowWalkTargetTask(runtime.resolveInt(minRunTicks), runtime.resolveInt(maxRunTicks)),
PathfinderMob::class.java
)
}
@@ -25,7 +25,7 @@ class GoToHealingMachineTaskConfig(
val condition: ExpressionLike = "true".asExpressionLike(),
val horizontalSearchRange: Expression = "10".asExpression(),
val verticalSearchRange: Expression = "5".asExpression(),
val speedMultiplier: Expression = "0.33".asExpression(),
val speedMultiplier: Expression = "0.35".asExpression(),
val completionRange: Expression = "1".asExpression()
) : SingleTaskConfig {
override fun createTask(
@@ -0,0 +1,25 @@
/*
* 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.BrainConfigurationContext
import com.cobblemon.mod.common.entity.ai.LookInDirectionTask
import com.cobblemon.mod.common.util.asExpression
import net.minecraft.world.entity.LivingEntity
class LookInDirectionTaskConfig : SingleTaskConfig {
var yaw: Expression = "0".asExpression()
var pitch: Expression = "0".asExpression()
override fun createTask(
entity: LivingEntity,
brainConfigurationContext: BrainConfigurationContext
) = LookInDirectionTask(yaw, pitch)
}
@@ -0,0 +1,186 @@
# Task Configuration
A task configuration is responsible for producing one or multiple tasks as part of a
[BrainConfiguration](../README.md). Tasks are the smallest unit of behaviour in a brain and are executed
as part of an activity.
A task configuration can be a simple string that represents the type of task to create, or a JSON object
which a `type` property that describes what type of task is being created and other properties that configure it.
### one_of
The 'one_of' type creates a task that randomly selects one of the tasks in the list to execute each tick.
- `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.
- `options`: A list of objects representing the different tasks that could run for a tick. Each object must have a `task`
which is a task configuration. Optionally, you can also specify a `weight` which is a number that determines the
probability of the task being selected. If no weight is specified, the task will have a weight of 1.
### all_of
The 'all_of' type creates a task that executes all of the tasks in the list each tick.
- `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.
- `tasks`: A list of task configurations to execute each tick.
### do_nothing
The 'do_nothing' type creates a task that does nothing for some period of time.
- `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.
- `minDurationTicks`: A MoLang expression that determines the minimum number of ticks to do nothing. Defaults to 40. Has `q.entity` as the entity.
- `maxDurationTicks`: A MoLang expression that determines the maximum number of ticks to do nothing. Defaults to 80. Has `q.entity` as the entity.
### random
The 'random' type creates a task that chooses one of the contained tasks when the entity is spawned. Note that this does not save forever,
so if the entity is reloaded, it will choose a new task. To make persisting randomization you have to use MoLang conditions on other task
configurations that use `q.entity.id_modulo(some_number)` to apply randomization based on the entity UUID.
For example, `q.entity.id_modulo(2)` will return 0 or 1 for an entity but will always be the same for the same entity,
so using `q.entity.id_modulo(2) == 0` as a task condition will make it occur for 50% of entities and remain after reloads.
`q.entity.id_modulo(3)` will return 0 or 1 or 2, and so on.
### follow_walk_target
The 'follow_walk_target' type creates a task that makes the entity follow a walk target. This does not choose the walk target,
it is only responsible for ensuring the entity will follow a path to whatever the current walk target is. Note that the target
does not necessarily need to be a land target.
- `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.
- `minRunTicks`: A MoLang expression that determines the minimum number of ticks to run to the target before stopping. Defaults to 150.
- `maxRunTicks`: A MoLang expression that determines the maximum number of ticks to run to the target before giving up. Defaults to 250.
### look_at_target
The 'look_at_target' type creates a task that makes the entity look at a target. This does not choose the target, it is only
responsible for ensuring the entity will look at the target position.
- `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.
- `minDurationTicks`: A MoLang expression that determines the minimum number of ticks that the entity will look at the target. Defaults to 40.
- `maxDurationTicks`: A MoLang expression that determines the maximum number of ticks that the entity will look at the target. Defaults to 80.
### stay_afloat
The 'stay_afloat' type creates a task that makes the entity stay afloat in water instead of quietly sinking and drowning.
- `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.
- `chance`: A MoLang expression that determines the chance of the entity trying to stay afloat. The higher it is, the more desperately it stays above the water. Defaults to 0.01. You don't need to change this, honestly.
### wander
The 'wander' type creates a task that makes the entity wander around randomly.
- `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.
- `shouldWander`: A MoLang expression that determines if the entity should wander. Defaults to `math.random(0, 20*8) <= 1`, which makes it wander approximately once every 8 seconds.
- `horizontalRange`: A MoLang expression that determines the maximum distance the entity will wander in a single path. Defaults to 10.
- `verticalRange`: A MoLang expression that determines the maximum vertical distance the entity will wander from its starting position. Defaults to 5.
- `speedMultiplier`: A MoLang expression that determines the speed multiplier for wandering. Defaults to 0.35 which is a standard walk speed.
- `completionRange`: A MoLang expression that determines the distance from the target location that the entity needs to be for the path to be considered complete. Defaults to 1.
- `lookTargetYOffset`: A MoLang expression that determines the vertical offset of the look target from the target walk position. Defaults to 1.5. You probably don't need to change this.
### look_at_entities
The 'look_at_entities' type creates a task that will randomly set the entity's look target to a nearby entity.
- `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.
- `maxDistance`: A MoLang expression that determines the maximum distance for an entity to be from this entity and be looked at.
### go_to_healing_machine
The 'go_to_healing_machine' type creates a task that makes the entity go to a nearby healing machine when they have a static NPC party that could be healed.
- `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.
- `horizontalSearchRange`: A MoLang expression that determines the maximum distance to search for a healing machine. Defaults to 10.
- `verticalSearchRange`: A MoLang expression that determines the maximum vertical distance to search for a healing machine. Defaults to 5.
- `speedMultiplier`: A MoLang expression that determines the speed multiplier for walking to the healing machine. Defaults to 0.35 which is a standard walk speed.
- `completionRange`: A MoLang expression that determines the distance from the target location that the entity needs to be for the path to be considered complete. Defaults to 1.
### heal_using_healing_machine
The 'heal_using_healing_machine' type creates a task that makes the entity heal its static NPC party using a healing machine if one is right next to the NPC.
- `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.
- `horizontalUseRange`: A MoLang expression that determines the maximum distance to a healing machine from which the NPC can use it. Defaults to 3.
- `verticalUseRange`: A MoLang expression that determines the maximum vertical distance to a healing machine from which the NPC can use it. Defaults to 2.
### switch_npc_to_battle
The 'switch_npc_to_battle' type creates a task that will switch NPC entities to the battle activity when it is in a battle. You'd generally put this
on the idle activity so that it automatically transitions activities when a battle starts.
### switch_npc_from_battle
The 'switch_npc_from_battle' type creates a task that will switch NPC entities from the battle activity when it is no longer in a battle. You should
put this in the battle activity so that it automatically transitions activities when a battle ends. If the NPC is in multiple battles, this
will only activate when no battles remain. It will rely on the brain schedule to decide what activity to switch back to (usually idle).
### look_at_battling_pokemon
The 'look_at_battling_pokemon' type creates a task that will set the entity's look target to switch between the battling Pokémon.
- `minDurationTicks`: A MoLang expression that determines the minimum number of ticks that the entity will look at a specific battling Pokémon. Defaults to 40.
- `maxDurationTicks`: A MoLang expression that determines the maximum number of ticks that the entity will look at a specific battling Pokémon. Defaults to 80.
### exit_battle_when_hurt
The 'exit_battle_when_hurt' type creates a task that will make the entity exit the battle when it is hurt.
- `condition`: A MoLang expression (with `q.entity` as the entity) that determines if this entire task should exist on the entity or not. This runs at the time of entity creation, not on tick.
- `includePassiveDamage`: A boolean that determines if passive damage (like poison or cacti) should trigger this task. Defaults to true.
### switch_to_chatting
The 'switch_to_chatting' type creates a task that will switch the entity to the chatting activity when a dialogue has been opened with that NPC.
### switch_from_chatting
The 'switch_from_chatting' type creates a task that will switch the entity from the chatting activity when the dialogue has been closed with that NPC.
It will rely on the brain schedule to decide what activity to switch back to (usually idle).
### look_at_speaker
The 'look_at_speaker' type creates a task that will set the entity's look target to the speaker of the dialogue.
### switch_to_action_effect
The 'switch_to_action_effect' type creates a task that will switch the entity to the action effect activity when it is performing an action effect.
### switch_from_action_effect
The 'switch_from_action_effect' type creates a task that will switch the entity from the action effect activity when it is no longer performing an action effect.
It will rely on the brain schedule to decide what activity to switch back to (usually idle).
### switch_to_fight
The 'switch_to_fight' type creates a task that will switch the entity to the fight activity when it has an attack target.
- `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.
- `activity`: The activity to switch to when the NPC is in a fight. Defaults to `minecraft:fight`.
### switch_from_fight
The 'switch_from_fight' type creates a task that will switch the entity from the fight activity when it no longer has an attack target. It will rely on the brain schedule to decide what activity to switch back to (usually idle).
### get_angry_at_attacker
The 'get_angry_at_attacker' type creates a task that will make the entity get angry at the attacker when it is attacked.
- `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.
### stop_being_angry_if_attacker_dead
The 'stop_being_angry_if_attacker_dead' type creates a task that will make the entity stop being angry at the attacker when the attacker is dead.
### attack_angry_at
The 'attack_angry_at' type creates a task that will make the entity choose the entity that it is angry at to be its attack target.
- `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.
### move_to_attack_target
The 'move_to_attack_target' type creates a task that will make the entity move to its attack target.
- `speedMultiplier`: A MoLang expression that determines the speed multiplier for moving to the attack target. Defaults to 0.5 which is an elevated speed to usual.
- `closeEnoughDistance`: A MoLang expression that determines the distance from the attack target that the entity needs to be for the path to be considered complete. Defaults to 1.
### melee_attack
The 'melee_attack' type creates a task that will make the entity perform a melee attack on its attack target when it is close enough. The damage dealt is determined by entity properties, which cannot be easily configured at time of writing.
- `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.
- `range`: A MoLang expression that determines the maximum distance from the attack target that the entity can be to perform the attack. Defaults to 1.5.
- `cooldownTicks`: A MoLang expression that determines the number of ticks to wait before performing another attack. Defaults to 30.
### switch_to_panic_when_hurt
The 'switch_to_panic_when_hurt' type creates a task that will switch the entity to the panic activity when it is hurt.
- `condition`: A MoLang expression (with `q.entity` as the entity) that determines if this entire task should exist on the entity or not. This runs at the time of entity creation, not on tick.
- `includePassiveDamage`: A boolean that determines if passive damage (like poison or cacti) should trigger this task. Defaults to false.
### switch_to_panic_when_hostiles_nearby
The 'switch_to_panic_when_hostiles_nearby' type creates a task that will switch the entity to the panic activity when hostiles are nearby. The definition of nearby depends
on the entity type and this piggy-backs off the Minecraft list of aggressive mobs and the right distances.
- `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.
### calm_down
The 'calm_down' type creates a task that will make the entity calm down when it is no longer being hurt and is far from hostiles and its attacker.
- `condition`: A MoLang expression (with `q.entity` as the entity) that determines if this entire task should exist on the entity or not. This runs at the time of entity creation, not on tick.
### flee_attacker
The 'flee_attacker' type creates a task that will make the entity flee from its attacker when it is hurt.
- `condition`: A MoLang expression (with `q.entity` as the entity) that determines if this entire task should exist on the entity or not. This runs at the time of entity creation, not on tick.
- `speedMultiplier`: A MoLang expression that determines the speed multiplier for fleeing from the attacker. Defaults to 0.5 which is an elevated speed to usual.
- `desiredDistance`: A MoLang expression that determines the distance from the attacker that the entity should try to maintain. Defaults to 9.
### flee_nearest_hostile
The 'flee_nearest_hostile' type creates a task that will make the entity flee from the nearest hostile entity when it is hurt.
- `condition`: A MoLang expression (with `q.entity` as the entity) that determines if this entire task should exist on the entity or not. This runs at the time of entity creation, not on tick.
- `speedMultiplier`: A MoLang expression that determines the speed multiplier for fleeing from the nearest hostile. Defaults to 0.5 which is an elevated speed to usual.
- `desiredDistance`: A MoLang expression that determines the distance from the nearest hostile that the entity should try to maintain. Defaults to 9.
### run_script
The 'run_script' type creates a task that will run a MoLang script every tick on this entity. This has the risk of being very laggy
if the script is doing expensive things. Remember to use `q.entity.world.game_time` and `math.mod` to do intermittent actions inside
the script to avoid lagging the game.
- `script`: A resource location identifying the script to run. This should be in the `molang` datapack folder.
### look_in_direction
The 'look_in_direction' type creates a task that will make the entity look in a specific direction at all times where they aren't being told to look elsewhere.
- `yaw`: A MoLang expression that determines the yaw angle (degrees) of the entity. Defaults to `0`.
- `pitch`: A MoLang expression that determines the pitch angle (degrees) of the entity. Defaults to `0`.
@@ -0,0 +1,49 @@
/*
* 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.value.DoubleValue
import com.cobblemon.mod.common.api.ai.BrainConfigurationContext
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMostSpecificMoLangValue
import com.cobblemon.mod.common.api.scripting.CobblemonScripts
import com.cobblemon.mod.common.entity.PosableEntity
import com.cobblemon.mod.common.util.cobblemonResource
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.declarative.BehaviorBuilder
import net.minecraft.world.entity.ai.behavior.declarative.Trigger
import net.minecraft.world.entity.ai.memory.MemoryModuleType
/**
* Runs a registered MoLang script (from the molang datapack folder) each tick.
*
* It's up to the user to not make expensive ass scripts. Remember you can access the game time
* from q.entity.level.game_time which can be used with a modulo operator to make something intermittent.
*
* @author Hiroku
* @since December 2nd, 2024
*/
class RunScript : SingleTaskConfig {
val script = cobblemonResource("dummy")
override fun createTask(
entity: LivingEntity,
brainConfigurationContext: BrainConfigurationContext
): BehaviorControl<in LivingEntity>? = BehaviorBuilder.create {
it.group(
it.registered(MemoryModuleType.LOOK_TARGET) // I think I need to have at least something here?
).apply(it) { _ ->
Trigger { world, entity, _ ->
runtime.withQueryValue("entity", (entity as? PosableEntity)?.struct ?: entity.asMostSpecificMoLangValue())
return@Trigger CobblemonScripts.run(script, runtime) == DoubleValue.ONE
}
}
}
}
@@ -8,15 +8,24 @@
package com.cobblemon.mod.common.api.ai.config.task
import com.cobblemon.mod.common.CobblemonMemories
import com.cobblemon.mod.common.api.ai.BrainConfigurationContext
import com.cobblemon.mod.common.entity.npc.ai.SwitchFromActionEffectTask
import net.minecraft.world.entity.LivingEntity
import net.minecraft.world.entity.schedule.Activity
import net.minecraft.world.entity.ai.behavior.declarative.BehaviorBuilder
import net.minecraft.world.entity.ai.behavior.declarative.Trigger
class SwitchFromActionEffectTaskConfig : SingleTaskConfig {
val activity = Activity.IDLE
override fun createTask(
entity: LivingEntity,
brainConfigurationContext: BrainConfigurationContext
) = SwitchFromActionEffectTask.create(activity)
) = BehaviorBuilder.create {
it.group(
it.absent(CobblemonMemories.ACTIVE_ACTION_EFFECT)
).apply(it) { _ ->
Trigger { level, entity, _ ->
entity.brain.updateActivityFromSchedule(level.dayTime, level.gameTime)
return@Trigger true
}
}
}
}
@@ -13,10 +13,8 @@ import com.cobblemon.mod.common.api.ai.BrainConfigurationContext
import net.minecraft.world.entity.LivingEntity
import net.minecraft.world.entity.ai.behavior.declarative.BehaviorBuilder
import net.minecraft.world.entity.ai.behavior.declarative.Trigger
import net.minecraft.world.entity.schedule.Activity
class SwitchFromChattingTaskConfig : SingleTaskConfig {
val activity = Activity.IDLE
override fun createTask(
entity: LivingEntity,
brainConfigurationContext: BrainConfigurationContext
@@ -24,8 +22,8 @@ class SwitchFromChattingTaskConfig : SingleTaskConfig {
it.group(
it.absent(CobblemonMemories.DIALOGUES)
).apply(it) { _ ->
Trigger { world, entity, _ ->
entity.brain.setActiveActivityIfPossible(activity)
Trigger { level, entity, _ ->
entity.brain.updateActivityFromSchedule(level.dayTime, level.gameTime)
return@Trigger true
}
}
@@ -13,10 +13,8 @@ import net.minecraft.world.entity.LivingEntity
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.schedule.Activity
class SwitchFromFightTaskConfig : SingleTaskConfig {
val activity = Activity.IDLE
override fun createTask(
entity: LivingEntity,
brainConfigurationContext: BrainConfigurationContext
@@ -24,8 +22,8 @@ class SwitchFromFightTaskConfig : SingleTaskConfig {
it.group(
it.absent(MemoryModuleType.ATTACK_TARGET)
).apply(it) { _ ->
Trigger { world, entity, _ ->
entity.brain.setActiveActivityIfPossible(activity)
Trigger { level, entity, _ ->
entity.brain.updateActivityFromSchedule(level.dayTime, level.gameTime)
return@Trigger true
}
}
@@ -8,18 +8,25 @@
package com.cobblemon.mod.common.api.ai.config.task
import com.cobblemon.mod.common.CobblemonMemories
import com.cobblemon.mod.common.api.ai.BrainConfigurationContext
import com.cobblemon.mod.common.entity.npc.ai.SwitchFromBattleTask
import net.minecraft.world.entity.LivingEntity
import net.minecraft.world.entity.ai.behavior.BehaviorControl
import net.minecraft.world.entity.schedule.Activity
import net.minecraft.world.entity.ai.behavior.declarative.BehaviorBuilder
import net.minecraft.world.entity.ai.behavior.declarative.Trigger
class SwitchFromNPCBattleTaskConfig : SingleTaskConfig {
val activity: Activity = Activity.IDLE
override fun createTask(
entity: LivingEntity,
brainConfigurationContext: BrainConfigurationContext
): BehaviorControl<in LivingEntity>? {
return SwitchFromBattleTask.create(activity)
return BehaviorBuilder.create {
it.group(it.absent(CobblemonMemories.NPC_BATTLING)).apply(it) { _ ->
Trigger { level, entity, _ ->
entity.brain.updateActivityFromSchedule(level.dayTime, level.gameTime)
true
}
}
}
}
}
@@ -26,7 +26,7 @@ class SwitchToActionEffectTaskConfig : SingleTaskConfig {
it.absent(CobblemonMemories.ACTIVE_ACTION_EFFECT)
).apply(it) { _ ->
Trigger { world, entity, time ->
entity.brain.setActiveActivityIfPossible(CobblemonActivities.NPC_ACTION_EFFECT)
entity.brain.setActiveActivityIfPossible(CobblemonActivities.ACTION_EFFECT)
return@Trigger true
}
}
@@ -8,21 +8,15 @@
package com.cobblemon.mod.common.api.ai.config.task
import com.bedrockk.molang.runtime.struct.QueryStruct
import com.cobblemon.mod.common.CobblemonActivities
import com.cobblemon.mod.common.CobblemonMemories
import com.cobblemon.mod.common.api.ai.BrainConfigurationContext
import com.cobblemon.mod.common.entity.PosableEntity
import com.cobblemon.mod.common.util.asExpressionLike
import com.cobblemon.mod.common.util.resolveBoolean
import com.cobblemon.mod.common.util.withQueryValue
import net.minecraft.world.entity.LivingEntity
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
class SwitchToChattingTaskConfig : SingleTaskConfig {
val condition = "true".asExpressionLike()
override fun createTask(
entity: LivingEntity,
brainConfigurationContext: BrainConfigurationContext
@@ -32,8 +26,6 @@ class SwitchToChattingTaskConfig : SingleTaskConfig {
it.registered(MemoryModuleType.WALK_TARGET)
).apply(it) { _, walkTarget ->
Trigger { world, entity, _ ->
runtime.withQueryValue("entity", (entity as? PosableEntity)?.struct ?: QueryStruct(hashMapOf()))
if (!runtime.resolveBoolean(condition)) return@Trigger false
walkTarget.erase()
entity.brain.setActiveActivityIfPossible(CobblemonActivities.NPC_CHATTING)
return@Trigger true
@@ -0,0 +1,35 @@
/*
* 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.BrainConfigurationContext
import com.cobblemon.mod.common.util.asExpression
import net.minecraft.world.entity.LivingEntity
import net.minecraft.world.entity.PathfinderMob
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.schedule.Activity
class SwitchToPanicWhenHostilesNearbyTaskConfig : SingleTaskConfig {
var condition = "true".asExpression()
override fun createTask(
entity: LivingEntity,
brainConfigurationContext: BrainConfigurationContext
) = BehaviorBuilder.create {
it.group(it.present(MemoryModuleType.NEAREST_HOSTILE))
.apply(it) { nearestHostile ->
Trigger { world, entity, _ ->
(entity as? PathfinderMob)?.navigation?.stop()
entity.brain.setActiveActivityIfPossible(Activity.PANIC)
return@Trigger true
}
}
}
}
@@ -0,0 +1,59 @@
/*
* 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.struct.QueryStruct
import com.cobblemon.mod.common.api.ai.BrainConfigurationContext
import com.cobblemon.mod.common.entity.PosableEntity
import com.cobblemon.mod.common.util.asExpression
import com.cobblemon.mod.common.util.resolveBoolean
import com.cobblemon.mod.common.util.withQueryValue
import net.minecraft.world.entity.LivingEntity
import net.minecraft.world.entity.PathfinderMob
import net.minecraft.world.entity.ai.behavior.BehaviorControl
import net.minecraft.world.entity.ai.behavior.declarative.BehaviorBuilder
import net.minecraft.world.entity.ai.behavior.declarative.Trigger
import net.minecraft.world.entity.ai.memory.MemoryModuleType
import net.minecraft.world.entity.schedule.Activity
class SwitchToPanicWhenHurtTaskConfig : SingleTaskConfig {
var condition = "true".asExpression()
var includePassiveDamage = false
override fun createTask(
entity: LivingEntity,
brainConfigurationContext: BrainConfigurationContext
): BehaviorControl<in LivingEntity>? {
runtime.withQueryValue("entity", (entity as? PosableEntity)?.struct ?: QueryStruct(hashMapOf()))
if (!runtime.resolveBoolean(condition)) return null
return if (includePassiveDamage) {
BehaviorBuilder.create {
it.group(it.present(MemoryModuleType.HURT_BY))
.apply(it) { _ ->
Trigger { world, entity, _ ->
(entity as? PathfinderMob)?.navigation?.stop()
entity.brain.setActiveActivityIfPossible(Activity.PANIC)
return@Trigger true
}
}
}
} else {
BehaviorBuilder.create {
it.group(it.present(MemoryModuleType.HURT_BY_ENTITY))
.apply(it) { _ ->
Trigger { world, entity, _ ->
(entity as? PathfinderMob)?.navigation?.stop()
entity.brain.setActiveActivityIfPossible(Activity.PANIC)
return@Trigger true
}
}
}
}
}
}
@@ -52,6 +52,14 @@ fun interface TaskConfig {
"look_at_speaker" to LookAtSpeakerTaskConfig::class.java,
"switch_to_action_effect" to SwitchToActionEffectTaskConfig::class.java,
"switch_from_action_effect" to SwitchFromActionEffectTaskConfig::class.java,
"exit_battle_when_hurt" to ExitBattleWhenHurtTaskConfig::class.java,
"switch_to_panic_when_hurt" to SwitchToPanicWhenHurtTaskConfig::class.java,
"switch_to_panic_when_hostiles_nearby" to SwitchToPanicWhenHostilesNearbyTaskConfig::class.java,
"calm_down" to CalmDownTaskConfig::class.java,
"flee_attacker" to FleeAttackerTaskConfig::class.java,
"flee_nearest_hostile" to FleeNearestHostileTaskConfig::class.java,
"run_script" to RunScript::class.java,
"look_in_direction" to LookInDirectionTaskConfig::class.java,
)
val runtime = MoLangRuntime().setup()
@@ -11,7 +11,6 @@ package com.cobblemon.mod.common.api.battles.model
import com.bedrockk.molang.runtime.MoLangRuntime
import com.bedrockk.molang.runtime.struct.QueryStruct
import com.bedrockk.molang.runtime.value.DoubleValue
import com.bedrockk.molang.runtime.value.MoValue
import com.cobblemon.mod.common.Cobblemon
import com.cobblemon.mod.common.Cobblemon.LOGGER
import com.cobblemon.mod.common.CobblemonNetwork
@@ -22,7 +21,6 @@ import com.cobblemon.mod.common.api.battles.model.actor.EntityBackedBattleActor
import com.cobblemon.mod.common.api.battles.model.actor.FleeableBattleActor
import com.cobblemon.mod.common.api.events.CobblemonEvents
import com.cobblemon.mod.common.api.events.battles.BattleFledEvent
import com.cobblemon.mod.common.api.moves.Moves
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMoLangValue
import com.cobblemon.mod.common.api.net.NetworkPacket
import com.cobblemon.mod.common.api.storage.party.PlayerPartyStore
@@ -43,6 +41,7 @@ import com.cobblemon.mod.common.battles.dispatch.WaitDispatch
import com.cobblemon.mod.common.battles.interpreter.ContextManager
import com.cobblemon.mod.common.battles.pokemon.BattlePokemon
import com.cobblemon.mod.common.battles.runner.ShowdownService
import com.cobblemon.mod.common.entity.PlatformType
import com.cobblemon.mod.common.entity.npc.NPCBattleActor
import com.cobblemon.mod.common.entity.npc.NPCEntity
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
@@ -51,17 +50,16 @@ import com.cobblemon.mod.common.net.messages.client.battle.BattleMessagePacket
import com.cobblemon.mod.common.pokemon.evolution.progress.DefeatEvolutionProgress
import com.cobblemon.mod.common.pokemon.evolution.progress.LastBattleCriticalHitsEvolutionProgress
import com.cobblemon.mod.common.pokemon.evolution.requirements.DefeatRequirement
import com.cobblemon.mod.common.pokemon.helditem.CobblemonHeldItemManager
import com.cobblemon.mod.common.util.battleLang
import com.cobblemon.mod.common.util.getPlayer
import net.minecraft.network.chat.Component
import com.cobblemon.mod.common.util.giveOrDropItemStack
import com.cobblemon.mod.common.util.itemRegistry
import net.minecraft.resources.ResourceLocation
import java.io.File
import java.util.UUID
import java.util.concurrent.CompletableFuture
import java.util.concurrent.ConcurrentLinkedDeque
import net.minecraft.network.chat.Component
import net.minecraft.resources.ResourceLocation
import net.minecraft.server.level.ServerPlayer
import net.minecraft.world.item.ItemStack
@@ -96,7 +94,6 @@ open class PokemonBattle(
.filterIsInstance<LastBattleCriticalHitsEvolutionProgress>()
.forEach { it.reset() }
}
actor.setupStruct()
}
}
@@ -271,22 +268,31 @@ open class PokemonBattle(
else -> continue
}
val experience = Cobblemon.experienceCalculator.calculate(opponentPokemon, faintedPokemon, multiplier)
if (experience > 0) {
if (experience > 0 && actor.pokemonList.all { it.health <= 0 }) {
opponent.awardExperience(opponentPokemon, experience)
}
Cobblemon.evYieldCalculator.calculate(opponentPokemon, faintedPokemon).forEach { (stat, amount) ->
pokemon.evs.add(stat, amount)
}
}
}
}
if(actor.itemsUsed.isNotEmpty() && actor.getPlayerUUIDs().count() > 0) {
if (actor.itemsUsed.isNotEmpty() && actor.getPlayerUUIDs().count() > 0) {
val player = actor.getPlayerUUIDs().first().getPlayer()
player?.level()?.itemRegistry.let { registry ->
actor.itemsUsed.mapNotNull { registry?.get(ResourceLocation.tryBySeparator(it.itemName.substringAfter('.'), '.')) }
.forEach { player?.giveOrDropItemStack(ItemStack(it))}
}
}
// Heal NPC's team if enabled
if (actor is NPCBattleActor) {
if (actor.npc.npc.autoHealParty) {
actor.npc.party?.heal()
}
}
}
// Heal Mon if wild
actors.filter { it.type == ActorType.WILD }
@@ -297,6 +303,11 @@ open class PokemonBattle(
actors.forEach { actor ->
actor.pokemonList.forEach { battlePokemon ->
battlePokemon.entity?.let { entity -> battlePokemon.postBattleEntityOperation(entity) }
if (battlePokemon.effectedPokemon.entity != null
&& battlePokemon.effectedPokemon.entity?.beamMode == 0
&& battlePokemon.effectedPokemon.entity?.platform != PlatformType.NONE) {
battlePokemon.effectedPokemon.tryRecallWithAnimation()
}
}
}
sendUpdate(BattleEndPacket())
@@ -11,6 +11,7 @@ package com.cobblemon.mod.common.api.battles.model.actor
import com.bedrockk.molang.runtime.struct.QueryStruct
import com.bedrockk.molang.runtime.value.StringValue
import com.cobblemon.mod.common.api.battles.model.PokemonBattle
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMoLangValue
import com.cobblemon.mod.common.api.net.NetworkPacket
import com.cobblemon.mod.common.battles.ActiveBattlePokemon
import com.cobblemon.mod.common.battles.ForcePassActionResponse
@@ -36,10 +37,11 @@ abstract class BattleActor(
pokemonList.forEach { it.actor = this }
}
val struct = QueryStruct(hashMapOf())
val struct = asMoLangValue()
lateinit var showdownId: String
lateinit var battle: PokemonBattle
fun isInitialized() = this::battle.isInitialized && this::showdownId.isInitialized
val activePokemon = mutableListOf<ActiveBattlePokemon>()
var canDynamax = false
@@ -138,10 +140,6 @@ abstract class BattleActor(
battle.writeShowdownAction(">$showdownId ${showdownMessages.joinToString()}")
}
open fun setupStruct() {
struct.addFunction("uuid") { StringValue(uuid.toString()) }
}
abstract fun getName(): MutableComponent
/**
@@ -9,8 +9,11 @@
package com.cobblemon.mod.common.api.data
import com.cobblemon.mod.common.Cobblemon
import com.cobblemon.mod.common.util.endsWith
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import java.io.File
import java.util.concurrent.ExecutionException
import net.minecraft.resources.ResourceLocation
import net.minecraft.server.packs.resources.ResourceManager
@@ -42,7 +45,24 @@ interface JsonDataRegistry<T> : DataRegistry {
val resourcePath: String
override fun reload(manager: ResourceManager) {
this.reload(Cobblemon.implementation.reloadJsonRegistry(this, manager))
val data = hashMapOf<ResourceLocation, T>()
manager.listResources(resourcePath) { path -> path.endsWith(JSON_EXTENSION) }.forEach { (identifier, resource) ->
if (identifier.namespace == "pixelmon") {
return@forEach
}
resource.open().use { stream ->
stream.bufferedReader().use { reader ->
val resolvedIdentifier = ResourceLocation.fromNamespaceAndPath(identifier.namespace, File(identifier.path).nameWithoutExtension)
try {
data[resolvedIdentifier] = gson.fromJson(reader, typeToken.type)
} catch (exception: Exception) {
throw ExecutionException("Error loading JSON for data: $identifier", exception)
}
}
}
}
reload(data)
}
/**
@@ -21,13 +21,13 @@ import com.cobblemon.mod.common.util.adapters.DialogueTextAdapter
import com.cobblemon.mod.common.util.adapters.ExpressionAdapter
import com.cobblemon.mod.common.util.adapters.ExpressionLikeAdapter
import com.cobblemon.mod.common.util.adapters.IdentifierAdapter
import com.cobblemon.mod.common.util.adapters.TextAdapter
import com.cobblemon.mod.common.util.adapters.TranslatedTextAdapter
import com.cobblemon.mod.common.util.cobblemonResource
import com.google.gson.GsonBuilder
import com.google.gson.reflect.TypeToken
import net.minecraft.network.chat.MutableComponent
import net.minecraft.server.level.ServerPlayer
import net.minecraft.resources.ResourceLocation
import net.minecraft.server.level.ServerPlayer
import net.minecraft.server.packs.PackType
/**
@@ -56,7 +56,7 @@ object Dialogues : JsonDataRegistry<Dialogue> {
.registerTypeAdapter(DialogueText::class.java, DialogueTextAdapter)
.registerTypeAdapter(Expression::class.java, ExpressionAdapter)
.registerTypeAdapter(ExpressionLike::class.java, ExpressionLikeAdapter)
.registerTypeAdapter(MutableComponent::class.java, TextAdapter)
.registerTypeAdapter(MutableComponent::class.java, TranslatedTextAdapter)
.registerTypeAdapter(ResourceLocation::class.java, IdentifierAdapter)
.also { gsonObservable.emit(it) }
.create()
@@ -61,7 +61,7 @@ open class ItemDropEntry : DropEntry {
if (dropMethod == ItemDropMethod.ON_PLAYER && player != null) {
world.addFreshEntity(ItemEntity(player.level(), player.x, player.y, player.z, stack))
} else if (dropMethod == ItemDropMethod.TO_INVENTORY && player != null) {
} else if (dropMethod == ItemDropMethod.TO_INVENTORY && player != null && !stack.isEmpty) {
val name = stack.hoverName
val count = stack.count
val succeeded = player.addItem(stack)
@@ -13,6 +13,7 @@ import com.cobblemon.mod.common.api.events.battles.BattleFledEvent
import com.cobblemon.mod.common.api.events.battles.BattleStartedPostEvent
import com.cobblemon.mod.common.api.events.battles.BattleStartedPreEvent
import com.cobblemon.mod.common.api.events.battles.BattleVictoryEvent
import com.cobblemon.mod.common.api.events.battles.instruction.FormeChangeEvent
import com.cobblemon.mod.common.api.events.battles.instruction.MegaEvolutionEvent
import com.cobblemon.mod.common.api.events.battles.instruction.TerastallizationEvent
import com.cobblemon.mod.common.api.events.battles.instruction.ZMoveUsedEvent
@@ -100,11 +101,13 @@ object CobblemonEvents {
// instructions
@JvmField
val MEGA_EVOLUTON = EventObservable<MegaEvolutionEvent>()
val MEGA_EVOLUTION = EventObservable<MegaEvolutionEvent>()
@JvmField
val TERASTALLIZATION = EventObservable<TerastallizationEvent>()
@JvmField
val ZPOWER_USED = EventObservable<ZMoveUsedEvent>()
@JvmField
val FORME_CHANGE = EventObservable<FormeChangeEvent>()
@JvmField
val POKEMON_SENT_PRE = CancelableObservable<PokemonSentPreEvent>()
@@ -192,6 +195,12 @@ object CobblemonEvents {
val POKEMON_GAINED = EventObservable<PokemonGainedEvent>()
@JvmField
val POKEMON_SEEN = EventObservable<PokemonSeenEvent>()
@JvmField
val POKEMON_ASPECTS_CHANGED = EventObservable<PokemonAspectsChangedEvent>()
@JvmField
val POKEDEX_DATA_CHANGED_PRE = CancelableObservable<PokedexDataChangedEvent.Pre>()
@JvmField
val POKEDEX_DATA_CHANGED_POST = EventObservable<PokedexDataChangedEvent.Post>()
// Fishing
@JvmField
@@ -8,9 +8,16 @@
package com.cobblemon.mod.common.api.events.battles
import com.bedrockk.molang.runtime.struct.QueryStruct
import com.bedrockk.molang.runtime.value.DoubleValue
import com.bedrockk.molang.runtime.value.MoValue
import com.bedrockk.molang.runtime.value.StringValue
import com.cobblemon.mod.common.api.battles.interpreter.BattleContext
import com.cobblemon.mod.common.api.battles.model.PokemonBattle
import com.cobblemon.mod.common.api.battles.model.actor.ActorType
import com.cobblemon.mod.common.battles.pokemon.BattlePokemon
import com.cobblemon.mod.common.util.asArrayValue
import java.util.function.Function
/**
* Event fired when a [BattlePokemon] faints. Exposes the [BattlePokemon] that fainted and the [BattleContext]
@@ -19,8 +26,24 @@ import com.cobblemon.mod.common.battles.pokemon.BattlePokemon
* @author Segfault Guy
* @since April 6th, 2023
*/
data class BattleFaintedEvent (
override val battle: PokemonBattle,
val killed: BattlePokemon,
val context: BattleContext
) : BattleEvent
data class BattleFaintedEvent(
override val battle: PokemonBattle,
val killed: BattlePokemon,
val context: BattleContext
) : BattleEvent {
val structContext = mutableMapOf<String, MoValue>(
"battle" to battle.struct,
"players" to battle.actors.filter { it.type == ActorType.PLAYER }.asArrayValue { it.struct },
"npcs" to battle.actors.filter { it.type == ActorType.NPC }.asArrayValue { it.struct },
"wild_pokemon" to battle.actors.filter { it.type == ActorType.WILD }.asArrayValue { it.struct },
"pokemon" to killed.struct,
"context" to QueryStruct(
hashMapOf(
"type" to Function { StringValue(context.type.name) },
"origin" to Function { context.origin?.struct ?: DoubleValue(0.0) },
"id" to Function { StringValue(context.id) },
"turn_created" to Function { DoubleValue(context.turn.toDouble()) },
)
)
)
}
@@ -8,8 +8,12 @@
package com.cobblemon.mod.common.api.events.battles
import com.bedrockk.molang.runtime.value.MoValue
import com.bedrockk.molang.runtime.value.StringValue
import com.cobblemon.mod.common.api.battles.model.PokemonBattle
import com.cobblemon.mod.common.api.battles.model.actor.ActorType
import com.cobblemon.mod.common.battles.actor.PlayerBattleActor
import com.cobblemon.mod.common.util.asArrayValue
/**
* Event fired when a [PokemonBattle] is fled by a [PlayerBattleActor].
@@ -18,8 +22,13 @@ import com.cobblemon.mod.common.battles.actor.PlayerBattleActor
* @since March 25th 2023
*/
data class BattleFledEvent (
override val battle: PokemonBattle,
val player: PlayerBattleActor
) : BattleEvent
) : BattleEvent {
val context = mutableMapOf<String, MoValue>(
"battle" to battle.struct,
"players" to battle.actors.filter { it.type == ActorType.PLAYER }.asArrayValue { it.struct },
"npcs" to battle.actors.filter { it.type == ActorType.NPC }.asArrayValue { it.struct },
"wild_pokemon" to battle.actors.filter { it.type == ActorType.WILD }.asArrayValue { it.struct }
)
}
@@ -9,7 +9,9 @@
package com.cobblemon.mod.common.api.events.battles
import com.cobblemon.mod.common.api.battles.model.PokemonBattle
import com.cobblemon.mod.common.api.battles.model.actor.ActorType
import com.cobblemon.mod.common.api.events.Cancelable
import com.cobblemon.mod.common.util.asArrayValue
import net.minecraft.network.chat.MutableComponent
/**
@@ -21,7 +23,14 @@ import net.minecraft.network.chat.MutableComponent
* @author Segfault Guy
* @since March 26th 2023
*/
data class BattleStartedPreEvent (override val battle: PokemonBattle, var reason: MutableComponent? = null) : BattleEvent, Cancelable()
data class BattleStartedPreEvent (override val battle: PokemonBattle, var reason: MutableComponent? = null) : BattleEvent, Cancelable() {
val context = mutableMapOf(
"battle" to battle.struct,
"players" to battle.actors.filter { it.type == ActorType.PLAYER }.asArrayValue { it.struct },
"npcs" to battle.actors.filter { it.type == ActorType.NPC }.asArrayValue { it.struct },
"wild_pokemon" to battle.actors.filter { it.type == ActorType.WILD }.asArrayValue { it.struct }
)
}
/**
* Event fired after a [PokemonBattle] starts.
@@ -29,4 +38,11 @@ data class BattleStartedPreEvent (override val battle: PokemonBattle, var reason
* @author Segfault Guy
* @since March 26th 2023
*/
data class BattleStartedPostEvent (override val battle: PokemonBattle) : BattleEvent
data class BattleStartedPostEvent (override val battle: PokemonBattle) : BattleEvent {
val context = mutableMapOf(
"battle" to battle.struct,
"players" to battle.actors.filter { it.type == ActorType.PLAYER }.asArrayValue { it.struct },
"npcs" to battle.actors.filter { it.type == ActorType.NPC }.asArrayValue { it.struct },
"wild_pokemon" to battle.actors.filter { it.type == ActorType.WILD }.asArrayValue { it.struct }
)
}
@@ -8,8 +8,14 @@
package com.cobblemon.mod.common.api.events.battles
import com.bedrockk.molang.runtime.value.DoubleValue
import com.bedrockk.molang.runtime.value.MoValue
import com.cobblemon.mod.common.api.battles.model.PokemonBattle
import com.cobblemon.mod.common.api.battles.model.actor.ActorType
import com.cobblemon.mod.common.api.battles.model.actor.BattleActor
import com.cobblemon.mod.common.battles.actor.PlayerBattleActor
import com.cobblemon.mod.common.entity.npc.NPCBattleActor
import com.cobblemon.mod.common.util.asArrayValue
/**
* Event fired when a battle is won by some number of [BattleActor]s.
@@ -22,4 +28,20 @@ data class BattleVictoryEvent (
val winners : List<BattleActor>,
val losers : List<BattleActor>,
val wasWildCapture : Boolean
) : BattleEvent
) : BattleEvent {
val context = mutableMapOf<String, MoValue>(
"battle" to battle.struct,
"winners" to winners.asArrayValue { it.struct },
"losers" to losers.asArrayValue { it.struct },
"was_wild_capture" to DoubleValue(wasWildCapture),
"player_winners" to winners.filter { it.type == ActorType.PLAYER }.asArrayValue { it.struct },
"player_losers" to losers.filter { it.type == ActorType.PLAYER }.asArrayValue { it.struct },
"npc_winners" to winners.filter { it.type == ActorType.NPC }.asArrayValue { it.struct },
"npc_losers" to losers.filter { it.type == ActorType.NPC }.asArrayValue { it.struct },
"wild_pokemon_winners" to winners.filter { it.type == ActorType.WILD }.asArrayValue { it.struct },
"wild_pokemon_losers" to losers.filter { it.type == ActorType.WILD }.asArrayValue { it.struct },
"players" to battle.actors.filter { it.type == ActorType.PLAYER }.asArrayValue { it.struct },
"npcs" to battle.actors.filter { it.type == ActorType.NPC }.asArrayValue { it.struct },
"wild_pokemon" to battle.actors.filter { it.type == ActorType.WILD }.asArrayValue { it.struct }
)
}
@@ -0,0 +1,38 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.events.battles.instruction
import com.bedrockk.molang.runtime.value.MoValue
import com.bedrockk.molang.runtime.value.StringValue
import com.cobblemon.mod.common.api.battles.model.PokemonBattle
import com.cobblemon.mod.common.api.battles.model.actor.ActorType
import com.cobblemon.mod.common.api.events.battles.BattleEvent
import com.cobblemon.mod.common.battles.dispatch.InterpreterInstruction
import com.cobblemon.mod.common.battles.pokemon.BattlePokemon
import com.cobblemon.mod.common.util.asArrayValue
/**
* Event that is fired when a Pokemon changes Forme in battle.
* @param battle The battle where the change occurred.
* @param pokemon The Pokemon that changed Forme.
*/
data class FormeChangeEvent(
override val battle: PokemonBattle,
val pokemon: BattlePokemon,
val formeName: String
) : BattleEvent {
val context = mutableMapOf(
"battle" to battle.struct,
"players" to battle.actors.filter { it.type == ActorType.PLAYER }.asArrayValue { it.struct },
"npcs" to battle.actors.filter { it.type == ActorType.NPC }.asArrayValue { it.struct },
"wild_pokemon" to battle.actors.filter { it.type == ActorType.WILD }.asArrayValue { it.struct },
"pokemon" to pokemon.struct,
"forme" to StringValue(formeName)
)
}
@@ -8,13 +8,25 @@
package com.cobblemon.mod.common.api.events.battles.instruction
import com.bedrockk.molang.runtime.value.MoValue
import com.bedrockk.molang.runtime.value.StringValue
import com.cobblemon.mod.common.api.battles.model.PokemonBattle
import com.cobblemon.mod.common.api.battles.model.actor.ActorType
import com.cobblemon.mod.common.battles.dispatch.InterpreterInstruction
import com.cobblemon.mod.common.battles.pokemon.BattlePokemon
import com.cobblemon.mod.common.util.asArrayValue
/**
* Event that is fired when a Pokemon Mega Evolves.
* @param battle The Pokemon Battle.
* @param pokemon The Pokemon that Mega Evolves.
*/
data class MegaEvolutionEvent(val battle: PokemonBattle, val pokemon: BattlePokemon)
data class MegaEvolutionEvent(val battle: PokemonBattle, val pokemon: BattlePokemon) {
val context = mutableMapOf<String, MoValue>(
"battle" to battle.struct,
"players" to battle.actors.filter { it.type == ActorType.PLAYER }.asArrayValue { it.struct },
"npcs" to battle.actors.filter { it.type == ActorType.NPC }.asArrayValue { it.struct },
"wild_pokemon" to battle.actors.filter { it.type == ActorType.WILD }.asArrayValue { it.struct },
"pokemon" to pokemon.struct
)
}
@@ -8,9 +8,13 @@
package com.cobblemon.mod.common.api.events.battles.instruction
import com.bedrockk.molang.runtime.value.MoValue
import com.bedrockk.molang.runtime.value.StringValue
import com.cobblemon.mod.common.api.battles.model.PokemonBattle
import com.cobblemon.mod.common.api.battles.model.actor.ActorType
import com.cobblemon.mod.common.api.types.tera.TeraType
import com.cobblemon.mod.common.battles.pokemon.BattlePokemon
import com.cobblemon.mod.common.util.asArrayValue
/**
* Event that is fired when a Pokemon Terastallizes.
@@ -22,4 +26,13 @@ data class TerastallizationEvent(
val battle: PokemonBattle,
val pokemon: BattlePokemon,
val teraType: TeraType
)
) {
val context = mutableMapOf<String, MoValue>(
"battle" to battle.struct,
"players" to battle.actors.filter { it.type == ActorType.PLAYER }.asArrayValue { it.struct },
"npcs" to battle.actors.filter { it.type == ActorType.NPC }.asArrayValue { it.struct },
"wild_pokemon" to battle.actors.filter { it.type == ActorType.WILD }.asArrayValue { it.struct },
"pokemon" to pokemon.struct,
"tera_type" to StringValue(teraType.id.toString())
)
}
@@ -8,12 +8,24 @@
package com.cobblemon.mod.common.api.events.battles.instruction
import com.bedrockk.molang.runtime.value.MoValue
import com.bedrockk.molang.runtime.value.StringValue
import com.cobblemon.mod.common.api.battles.model.PokemonBattle
import com.cobblemon.mod.common.api.battles.model.actor.ActorType
import com.cobblemon.mod.common.battles.pokemon.BattlePokemon
import com.cobblemon.mod.common.util.asArrayValue
/**
* Event that is fired when a Pokemon uses a Z-Move.
* @param battle The Pokemon Battle.
* @param pokemon The Pokemon that uses the Z-Move.
*/
data class ZMoveUsedEvent(val battle: PokemonBattle, val pokemon: BattlePokemon)
data class ZMoveUsedEvent(val battle: PokemonBattle, val pokemon: BattlePokemon) {
val context = mutableMapOf<String, MoValue>(
"battle" to battle.struct,
"players" to battle.actors.filter { it.type == ActorType.PLAYER }.asArrayValue { it.struct },
"npcs" to battle.actors.filter { it.type == ActorType.NPC }.asArrayValue { it.struct },
"wild_pokemon" to battle.actors.filter { it.type == ActorType.WILD }.asArrayValue { it.struct },
"pokemon" to pokemon.struct
)
}
@@ -8,8 +8,13 @@
package com.cobblemon.mod.common.api.events.farming
import com.bedrockk.molang.runtime.value.StringValue
import com.cobblemon.mod.common.api.apricorn.Apricorn
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMoLangValue
import com.cobblemon.mod.common.util.toArrayStruct
import com.cobblemon.mod.common.util.worldRegistry
import net.minecraft.core.BlockPos
import net.minecraft.core.registries.Registries
import net.minecraft.server.level.ServerLevel
import net.minecraft.server.level.ServerPlayer
import net.minecraft.world.level.block.state.BlockState
@@ -26,4 +31,11 @@ class ApricornHarvestEvent(
fun getBlock(): BlockState {
return world.getBlockState(pos)
}
val context = mutableMapOf(
"player" to player.asMoLangValue(),
"apricorn" to StringValue(apricorn.name),
"world" to world.worldRegistry.wrapAsHolder(world).asMoLangValue(Registries.DIMENSION),
"pos" to pos.toArrayStruct()
)
}
@@ -9,10 +9,11 @@
package com.cobblemon.mod.common.api.events.fishing
import com.cobblemon.mod.common.api.events.Cancelable
import net.minecraft.world.entity.player.Player
import net.minecraft.world.item.ItemStack
/**
* Event that is fired when a fishing rod is reeled.
* @param rod The ItemStack of the rod that is being reeled.
*/
class PokerodReelEvent(val rod: ItemStack) : Cancelable()
class PokerodReelEvent(val player: Player, val rod: ItemStack) : Cancelable()
@@ -9,6 +9,7 @@
package com.cobblemon.mod.common.api.events.pokeball
import com.cobblemon.mod.common.api.events.Cancelable
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMoLangValue
import com.cobblemon.mod.common.entity.pokeball.EmptyPokeBallEntity
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
@@ -18,4 +19,9 @@ import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
class ThrownPokeballHitEvent(
val pokeBall : EmptyPokeBallEntity,
val pokemon : PokemonEntity
) : Cancelable()
) : Cancelable() {
val context = mutableMapOf(
"pokeball" to pokeBall.struct,
"pokemon" to pokemon.asMoLangValue()
)
}
@@ -8,9 +8,14 @@
package com.cobblemon.mod.common.api.events.pokedex.scanning
import com.bedrockk.molang.runtime.value.DoubleValue
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMoLangValue
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMostSpecificMoLangValue
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import com.cobblemon.mod.common.pokedex.scanner.PokedexEntityData
import com.cobblemon.mod.common.pokedex.scanner.ScannableEntity
import net.minecraft.server.level.ServerPlayer
import net.minecraft.world.entity.LivingEntity
data class PokemonScannedEvent(val player: ServerPlayer, val scannedPokemonEntityData: PokedexEntityData, val scannedEntity: ScannableEntity) {
val pokedexEntityData: PokedexEntityData
@@ -18,4 +23,15 @@ data class PokemonScannedEvent(val player: ServerPlayer, val scannedPokemonEntit
val isOwned: Boolean
get() = scannedPokemonEntityData.ownerUUID == player.uuid
val context = mutableMapOf(
"player" to player.asMoLangValue(),
"pokemon" to scannedPokemonEntityData.struct,
"entity" to {
when (scannedEntity) {
is LivingEntity -> scannedEntity.asMostSpecificMoLangValue()
else -> DoubleValue(0.0)
}
},
)
}
@@ -8,6 +8,7 @@
package com.cobblemon.mod.common.api.events.pokemon
import com.bedrockk.molang.runtime.value.DoubleValue
import com.cobblemon.mod.common.pokemon.Pokemon
/**
@@ -16,4 +17,10 @@ import com.cobblemon.mod.common.pokemon.Pokemon
* @author Hiroku
* @since August 5th, 2022
*/
class LevelUpEvent(val pokemon: Pokemon, val oldLevel: Int, var newLevel: Int)
class LevelUpEvent(val pokemon: Pokemon, val oldLevel: Int, var newLevel: Int) {
val context = mutableMapOf(
"pokemon" to pokemon.struct,
"old_level" to DoubleValue(oldLevel.toDouble()),
"new_level" to DoubleValue(newLevel.toDouble())
)
}
@@ -0,0 +1,60 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.events.pokemon
import com.bedrockk.molang.runtime.value.DoubleValue
import com.bedrockk.molang.runtime.value.MoValue
import com.bedrockk.molang.runtime.value.StringValue
import com.cobblemon.mod.common.api.events.Cancelable
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMoLangValue
import com.cobblemon.mod.common.api.pokedex.AbstractPokedexManager
import com.cobblemon.mod.common.api.pokedex.FormDexRecord
import com.cobblemon.mod.common.api.pokedex.PokedexEntryProgress
import com.cobblemon.mod.common.pokedex.scanner.PokedexEntityData
import com.cobblemon.mod.common.pokemon.Pokemon
import com.cobblemon.mod.common.util.getPlayer
import com.mojang.datafixers.util.Either
import java.util.UUID
/**
* Event that fires when a Pokémon's information is gained or updated in the Pokédex.
*/
sealed interface PokedexDataChangedEvent {
val dataSource: Either<PokedexEntityData, Pokemon>
val knowledge: PokedexEntryProgress
val playerUUID: UUID
val record: FormDexRecord
val pokedexManager: AbstractPokedexManager
get() = record.speciesDexRecord.pokedexManager
fun getContext(): MutableMap<String, MoValue> {
return mutableMapOf(
"player" to (playerUUID.getPlayer()?.asMoLangValue() ?: DoubleValue.ZERO),
"pokemon" to dataSource.map({ DoubleValue.ZERO }, { it.struct }),
"data" to dataSource.map({ it.struct }, { DoubleValue.ZERO }),
"knowledge" to StringValue(knowledge.name.lowercase()),
"pokedex" to pokedexManager.struct
)
}
class Pre(
override val dataSource: Either<PokedexEntityData, Pokemon>,
override val knowledge: PokedexEntryProgress,
override val playerUUID: UUID,
override val record: FormDexRecord
) : PokedexDataChangedEvent, Cancelable()
class Post(
override val dataSource: Either<PokedexEntityData, Pokemon>,
override val knowledge: PokedexEntryProgress,
override val playerUUID: UUID,
override val record: FormDexRecord
) : PokedexDataChangedEvent
}
@@ -0,0 +1,17 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.events.pokemon
import com.cobblemon.mod.common.pokemon.Pokemon
import java.util.*
data class PokemonAspectsChangedEvent(
val ownerId: UUID?,
val pokemon: Pokemon,
)
@@ -8,12 +8,23 @@
package com.cobblemon.mod.common.api.events.pokemon
import com.bedrockk.molang.runtime.value.MoValue
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMoLangValue
import com.cobblemon.mod.common.entity.pokeball.EmptyPokeBallEntity
import com.cobblemon.mod.common.pokemon.Pokemon
import com.cobblemon.mod.common.util.itemRegistry
import net.minecraft.core.registries.Registries
import net.minecraft.server.level.ServerPlayer
data class PokemonCapturedEvent (
val pokemon: Pokemon,
val player: ServerPlayer,
val pokeBallEntity: EmptyPokeBallEntity
)
) {
val context = mutableMapOf<String, MoValue>(
"pokemon" to pokemon.struct,
"player" to player.asMoLangValue(),
"poke_ball" to pokeBallEntity.struct,
"item" to player.level().itemRegistry.wrapAsHolder(pokeBallEntity.pokeBall.item).asMoLangValue(Registries.ITEM)
)
}
@@ -8,6 +8,7 @@
package com.cobblemon.mod.common.api.events.pokemon
import com.bedrockk.molang.runtime.value.DoubleValue
import com.cobblemon.mod.common.pokemon.Pokemon
/**
@@ -16,4 +17,9 @@ import com.cobblemon.mod.common.pokemon.Pokemon
data class PokemonFaintedEvent(
val pokemon: Pokemon,
var faintedTimer: Int
)
) {
val context = mutableMapOf(
"pokemon" to pokemon.struct,
"fainted_timer" to DoubleValue(faintedTimer)
)
}
@@ -8,6 +8,7 @@
package com.cobblemon.mod.common.api.events.pokemon
import com.bedrockk.molang.runtime.value.StringValue
import com.cobblemon.mod.common.pokemon.Pokemon
import java.util.UUID
@@ -15,4 +16,8 @@ data class PokemonGainedEvent(
val playerId: UUID,
val pokemon: Pokemon
) {
val context = mutableMapOf(
"player_id" to StringValue(playerId.toString()),
"pokemon" to pokemon.struct
)
}
@@ -9,11 +9,9 @@
package com.cobblemon.mod.common.api.events.pokemon
import com.cobblemon.mod.common.pokemon.Pokemon
import net.minecraft.server.level.ServerPlayer
import java.util.UUID
data class PokemonSeenEvent(
val playerId: UUID,
val pokemon: Pokemon
) {
}
)
@@ -13,12 +13,12 @@ import com.cobblemon.mod.common.api.events.fishing.BaitEffectFunctionRegistryEve
import com.cobblemon.mod.common.api.spawning.fishing.FishingSpawnCause
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import com.cobblemon.mod.common.util.cobblemonResource
import com.mojang.serialization.Codec
import com.mojang.serialization.codecs.RecordCodecBuilder
import java.util.Optional
import net.minecraft.core.Registry
import net.minecraft.nbt.CompoundTag
import net.minecraft.nbt.ListTag
import net.minecraft.nbt.StringTag
import net.minecraft.network.codec.ByteBufCodecs
import net.minecraft.resources.ResourceLocation
import net.minecraft.world.entity.Entity
import net.minecraft.world.item.Item
import net.minecraft.world.item.ItemStack
@@ -34,46 +34,30 @@ data class FishingBait(
val chance: Double = 0.0,
val value: Double = 0.0
) {
fun toNbt(): CompoundTag {
val nbt = CompoundTag()
nbt.putString("Type", type.toString())
subcategory?.let { nbt.putString("Subcategory", it.toString()) }
nbt.putDouble("Chance", chance)
nbt.putDouble("Value", value)
return nbt
}
constructor(type: ResourceLocation, subcategory: Optional<ResourceLocation>, chance: Double, value: Double) : this(type, subcategory.orElse(null), chance, value)
companion object {
fun fromNbt(nbt: CompoundTag): Effect {
val type = ResourceLocation.parse(nbt.getString("Type"))
val subcategory = if (nbt.contains("Subcategory")) ResourceLocation.parse(nbt.getString("Subcategory")) else null
val chance = nbt.getDouble("Chance")
val value = nbt.getDouble("Value")
return Effect(type, subcategory, chance, value)
val CODEC = RecordCodecBuilder.create<Effect> { instance ->
instance.group(
ResourceLocation.CODEC.fieldOf("type").forGetter { it.type },
ResourceLocation.CODEC.optionalFieldOf("subcategory").forGetter { Optional.ofNullable(it.subcategory) },
Codec.DOUBLE.fieldOf("chance").forGetter { it.chance },
Codec.DOUBLE.fieldOf("value").forGetter { it.value }
).apply(instance, ::Effect)
}
}
}
fun toNbt(): CompoundTag {
val nbt = CompoundTag()
nbt.putString("Item", item.toString())
val effectsList = ListTag()
effects.forEach { effectsList.add(it.toNbt()) }
nbt.put("Effects", effectsList)
return nbt
}
companion object {
fun fromNbt(nbt: CompoundTag): FishingBait {
val item = ResourceLocation.parse(nbt.getString("Item"))
val effectsList = nbt.getList("Effects", 10) // 10 is the type for NbtCompound
val effects = mutableListOf<Effect>()
for (i in 0 until effectsList.size) {
effects.add(Effect.fromNbt(effectsList.getCompound(i)))
}
return FishingBait(item, effects)
val CODEC = RecordCodecBuilder.create<FishingBait> { instance ->
instance.group(
ResourceLocation.CODEC.fieldOf("item").forGetter { it.item },
Effect.CODEC.listOf().fieldOf("effects").forGetter {it.effects}
).apply(instance, ::FishingBait)
}
val STREAM_CODEC = ByteBufCodecs.fromCodec(CODEC)
val BLANK_BAIT = FishingBait(
cobblemonResource("blank"),
emptyList()
@@ -8,6 +8,7 @@
package com.cobblemon.mod.common.api.gui
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
import net.minecraft.client.gui.components.AbstractWidget
import net.minecraft.client.gui.components.Renderable
import net.minecraft.client.gui.components.events.GuiEventListener
@@ -22,9 +23,9 @@ abstract class ParentWidget(
pX: Int, pY: Int,
pWidth: Int, pHeight: Int,
component: Component
): Renderable, AbstractWidget(pX, pY, pWidth, pHeight, component) {
): CobblemonRenderable, AbstractWidget(pX, pY, pWidth, pHeight, component) {
private val children: MutableList<GuiEventListener> = mutableListOf()
val children: MutableList<GuiEventListener> = mutableListOf()
/**
* Adds Widget to the children list
@@ -74,7 +74,7 @@ abstract class RequestManager<T : ServerPlayerActionRequest> {
?: this.getInboundRequest(receiver.uuid, requestID)
/** Determines whether [player] can receive a [T]. */
open fun isBusy(player: ServerPlayer): Boolean = player.isInBattle() || player.isTrading()
open fun isBusy(player: ServerPlayer): Boolean = player.isInBattle() || player.isTrading() || player.party().find { it.entity?.isBusy == true } != null
/** Determines if the [target] is a valid interaction request target. */
abstract fun isValidInteraction(player: ServerPlayer, target: ServerPlayer): Boolean
@@ -176,7 +176,7 @@ abstract class RequestManager<T : ServerPlayerActionRequest> {
else if (!this.isValidInteraction(player, target ?: request.sender)) // with teams anyone can accept
request.notify(player, true, "ui.interact.failed")
// if sending player is occupied, can't accept response
else if (this.isBusy(request.sender)) // TODO enhancement: allow retries - modify client so we don't remove request when sending acceptance
else if (this.isBusy(request.sender) || this.isBusy(request.receiver)) // TODO enhancement: allow retries - modify client so we don't remove request when sending acceptance
request.notify(player, true, "ui.interact.unavailable")
// if no condition is blocking acceptance, accept
else if (this.canAccept(request))
@@ -38,8 +38,9 @@ import net.minecraft.world.phys.AABB
*/
interface PokemonSelectingItem {
fun use(player: ServerPlayer, stack: ItemStack): InteractionResultHolder<ItemStack> {
val range = player.entityInteractionRange()
val entity = player.level()
.getEntities(player, AABB.ofSize(player.position(), 16.0, 16.0, 16.0))
.getEntities(player, AABB.ofSize(player.position(), range, range, range))
.filter { player.isLookingAt(it, stepDistance = 0.1F) }
.minByOrNull { it.distanceTo(player) } as? PokemonEntity?
@@ -95,11 +96,12 @@ interface PokemonSelectingItem {
player.sendSystemMessage(battleLang("bagitem.invalid").red())
} else {
battlePokemon.actor.forceChoose(BagItemActionResponse(bagItem, battlePokemon))
val stackName = BuiltInRegistries.ITEM.getKey(stack.item)
if (!player.isCreative) {
stack.shrink(1)
battlePokemon.actor.itemsUsed.add(bagItem)
}
CobblemonCriteria.POKEMON_INTERACT.trigger(player, PokemonInteractContext(battlePokemon.effectedPokemon.species.resourceIdentifier, BuiltInRegistries.ITEM.getKey(stack.item)))
CobblemonCriteria.POKEMON_INTERACT.trigger(player, PokemonInteractContext(battlePokemon.effectedPokemon.species.resourceIdentifier, stackName))
}
}
@@ -147,4 +149,4 @@ interface PokemonSelectingItem {
return InteractionResultHolder.success(stack)
}
}
}
@@ -8,6 +8,7 @@
package com.cobblemon.mod.common.api.item.ability
import com.cobblemon.mod.common.api.Priority
import com.cobblemon.mod.common.api.abilities.*
import com.cobblemon.mod.common.item.interactive.ability.AbilityTypeChanger
import com.cobblemon.mod.common.pokemon.Pokemon
@@ -33,7 +34,7 @@ interface AbilityChanger<T : PotentialAbility> {
* @param pokemon The [Pokemon] being queried.
* @return A set containing all their legal abilities associated with [type], can be empty.
*/
fun queryPossible(pokemon: Pokemon): Set<AbilityTemplate>
fun queryPossible(pokemon: Pokemon): Set<Pair<AbilityTemplate, Priority>>
/**
* Attempts to update the ability of the given [pokemon].
@@ -22,27 +22,56 @@ import com.cobblemon.mod.common.CobblemonActivities
import com.cobblemon.mod.common.CobblemonBlockEntities
import com.cobblemon.mod.common.CobblemonMemories
import com.cobblemon.mod.common.api.battles.model.PokemonBattle
import com.cobblemon.mod.common.api.battles.model.actor.ActorType
import com.cobblemon.mod.common.api.battles.model.actor.BattleActor
import com.cobblemon.mod.common.api.dialogue.PlayerDialogueFaceProvider
import com.cobblemon.mod.common.api.dialogue.ReferenceDialogueFaceProvider
import com.cobblemon.mod.common.api.moves.animations.ActionEffectContext
import com.cobblemon.mod.common.api.moves.animations.ActionEffects
import com.cobblemon.mod.common.api.moves.animations.NPCProvider
import com.cobblemon.mod.common.api.pokedex.AbstractPokedexManager
import com.cobblemon.mod.common.api.pokedex.CaughtCount
import com.cobblemon.mod.common.api.pokedex.CaughtPercent
import com.cobblemon.mod.common.api.pokedex.PokedexEntryProgress
import com.cobblemon.mod.common.api.pokedex.PokedexManager
import com.cobblemon.mod.common.api.pokedex.SeenCount
import com.cobblemon.mod.common.api.pokedex.SeenPercent
import com.cobblemon.mod.common.api.pokemon.stats.Stats
import com.cobblemon.mod.common.api.scripting.CobblemonScripts
import com.cobblemon.mod.common.api.spawning.context.SpawningContext
import com.cobblemon.mod.common.api.storage.PokemonStore
import com.cobblemon.mod.common.api.storage.party.PartyStore
import com.cobblemon.mod.common.api.storage.party.PlayerPartyStore
import com.cobblemon.mod.common.api.storage.pc.PCPosition
import com.cobblemon.mod.common.api.storage.pc.PCStore
import com.cobblemon.mod.common.api.text.text
import com.cobblemon.mod.common.battles.BattleRegistry
import com.cobblemon.mod.common.battles.actor.PlayerBattleActor
import com.cobblemon.mod.common.client.particle.BedrockParticleOptionsRepository
import com.cobblemon.mod.common.client.particle.ParticleStorm
import com.cobblemon.mod.common.client.render.models.blockbench.wavefunction.WaveFunctions
import com.cobblemon.mod.common.entity.PosableEntity
import com.cobblemon.mod.common.entity.npc.NPCBattleActor
import com.cobblemon.mod.common.entity.npc.NPCEntity
import com.cobblemon.mod.common.entity.pokemon.PokemonBehaviourFlag
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import com.cobblemon.mod.common.entity.pokemon.ai.PokemonMoveControl
import com.cobblemon.mod.common.net.messages.client.animation.PlayPosableAnimationPacket
import com.cobblemon.mod.common.net.messages.client.effect.RunPosableMoLangPacket
import com.cobblemon.mod.common.net.messages.client.effect.SpawnSnowstormEntityParticlePacket
import com.cobblemon.mod.common.net.messages.client.effect.SpawnSnowstormParticlePacket
import com.cobblemon.mod.common.pokemon.Pokemon
import com.cobblemon.mod.common.pokemon.Species
import com.cobblemon.mod.common.util.*
import com.mojang.datafixers.util.Either
import java.util.UUID
import kotlin.math.sqrt
import net.minecraft.client.multiplayer.ClientLevel
import net.minecraft.commands.arguments.EntityAnchorArgument
import net.minecraft.core.BlockPos
import net.minecraft.core.Holder
import net.minecraft.core.Registry
import net.minecraft.core.registries.BuiltInRegistries
import net.minecraft.core.registries.Registries
import net.minecraft.nbt.CompoundTag
import net.minecraft.nbt.DoubleTag
@@ -51,15 +80,23 @@ import net.minecraft.nbt.StringTag
import net.minecraft.nbt.Tag
import net.minecraft.resources.ResourceKey
import net.minecraft.resources.ResourceLocation
import net.minecraft.server.MinecraftServer
import net.minecraft.server.level.ServerLevel
import net.minecraft.server.level.ServerPlayer
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.EntityType
import net.minecraft.world.entity.LightningBolt
import net.minecraft.world.entity.LivingEntity
import net.minecraft.world.entity.PathfinderMob
import net.minecraft.world.entity.ai.behavior.BlockPosTracker
import net.minecraft.world.entity.ai.memory.MemoryModuleType
import net.minecraft.world.entity.ai.memory.MemoryStatus
import net.minecraft.world.entity.ai.memory.WalkTarget
import net.minecraft.world.entity.player.Player
import net.minecraft.world.level.Level
import net.minecraft.world.level.Level.ExplosionInteraction
import net.minecraft.world.level.biome.Biome
import net.minecraft.world.level.block.Block
import net.minecraft.world.level.dimension.DimensionType
@@ -74,6 +111,31 @@ import net.minecraft.world.phys.Vec3
*/
object MoLangFunctions {
val generalFunctions = hashMapOf<String, java.util.function.Function<MoParams, Any>>(
"print" to java.util.function.Function { params ->
val message = params.get<MoValue>(0).asString()
Cobblemon.LOGGER.info(message)
},
"set_query" to java.util.function.Function { params ->
val variable = params.getString(0)
val value = params.get<MoValue>(1)
params.environment.query.addFunction(variable) { value }
return@Function value
},
"replace" to java.util.function.Function { params ->
val text = params.getString(0)
val search = params.getString(1)
val replace = params.getString(2)
return@Function StringValue(text.replace(search, replace))
},
"is_blank" to java.util.function.Function { params ->
val arg = params.get<MoValue>(0)
return@Function DoubleValue((arg is StringValue && (arg.value.isBlank() || arg.value.toDoubleOrNull() == 0.0)) || (arg is DoubleValue && arg.value == 0.0))
},
"run_command" to java.util.function.Function { params ->
val command = params.getString(0)
val server = server() ?: return@Function DoubleValue.ZERO
server.commands.performPrefixedCommand(server.createCommandSourceStack(), command)
},
"is_int" to java.util.function.Function { params -> DoubleValue(params.get<MoValue>(0).asString().isInt()) },
"is_number" to java.util.function.Function { params -> DoubleValue(params.get<MoValue>(0).asString().toDoubleOrNull() != null) },
"to_number" to java.util.function.Function { params -> DoubleValue(params.get<MoValue>(0).asString().toDoubleOrNull() ?: 0.0) },
@@ -108,36 +170,156 @@ object MoLangFunctions {
runtime.environment.variable = params.environment.variable
runtime.environment.context = params.environment.context
val script = params.getString(0).asIdentifierDefaultingNamespace()
CobblemonScripts.run(script, runtime) ?: DoubleValue(0)
CobblemonScripts.run(script, runtime) ?: DoubleValue.ZERO
},
"run_command" to java.util.function.Function { params ->
val command = params.getString(0)
server()?.let {
return@Function DoubleValue(it.commands.dispatcher.execute(command, it.createCommandSourceStack()))
} ?: return@Function DoubleValue.ZERO
"run_molang" to java.util.function.Function { params ->
val runtime = MoLangRuntime()
runtime.environment.query = params.environment.query
runtime.environment.variable = params.environment.variable
runtime.environment.context = params.environment.context
val expression = params.getString(0).asExpressionLike()
runtime.resolve(expression)
},
"system_time_millis" to java.util.function.Function { _ ->
DoubleValue(System.currentTimeMillis())
},
// the rest of the world use dd/MM/yyyy grow up america (this comment was generated by copilot)
"date_local_time" to java.util.function.Function { _ ->
val time = System.currentTimeMillis()
val date = java.util.Date(time)
val formatted = java.text.SimpleDateFormat("DD/MM/YYYY").format(date)
StringValue(formatted)
},
"date_of" to java.util.function.Function { params ->
val time = params.getDouble(0).toLong()
val date = java.util.Date(time)
val formatted = java.text.SimpleDateFormat("DD/MM/YYYY").format(date)
StringValue(formatted)
},
"date_is_after" to java.util.function.Function { params ->
val dateA = params.getString(0)
val dateB = params.getString(1)
val format = java.text.SimpleDateFormat("DD/MM/YYYY")
val a = format.parse(dateA)
val b = format.parse(dateB)
DoubleValue(a.after(b))
}
)
val biomeFunctions = hashMapOf<String, java.util.function.Function<MoParams, Any>>()
val worldFunctions = hashMapOf<String, java.util.function.Function<MoParams, Any>>()
val dimensionTypeFunctions = hashMapOf<String, java.util.function.Function<MoParams, Any>>()
val blockFunctions = hashMapOf<String, java.util.function.Function<MoParams, Any>>()
val biomeFunctions = mutableListOf<(Holder<Biome>) -> HashMap<String, java.util.function.Function<MoParams, Any>>>()
val worldFunctions = mutableListOf<(Holder<Level>) -> HashMap<String, java.util.function.Function<MoParams, Any>>>(
{ worldHolder ->
val world = worldHolder.value()
val map = hashMapOf<String, java.util.function.Function<MoParams, Any>>()
map.put("game_time") { _ -> DoubleValue(world.gameTime.toDouble()) }
map.put("time_of_day") {
val time = world.dayTime % 24000
return@put DoubleValue(time.toDouble())
}
map.put("server") { _ -> server()?.asMoLangValue() ?: DoubleValue.ZERO }
map.put("is_raining_at") { params ->
val x = params.getInt(0)
val y = params.getInt(1)
val z = params.getInt(2)
return@put DoubleValue(world.isRainingAt(BlockPos(x, y, z)))
}
map.put("is_chunk_loaded_at") { params ->
val x = params.getInt(0)
val y = params.getInt(1)
val z = params.getInt(2)
return@put DoubleValue(world.isLoaded(BlockPos(x, y, z)))
}
map.put("is_thundering") { _ -> DoubleValue(world.isThundering) }
map.put("is_raining") { _ -> DoubleValue(world.isRaining) }
map.put("set_block") { params ->
val x = params.getInt(0)
val y = params.getInt(1)
val z = params.getInt(2)
val block = world.blockRegistry.get(params.getString(3).asIdentifierDefaultingNamespace())
?: run {
Cobblemon.LOGGER.error("Unknown block: ${params.getString(3)}")
return@put DoubleValue.ZERO
}
world.setBlock(BlockPos(x, y, z), block.defaultBlockState(), Block.UPDATE_ALL)
}
map.put("get_block") { params ->
val x = params.getInt(0)
val y = params.getInt(1)
val z = params.getInt(2)
val block = world.getBlockState(BlockPos(x, y, z)).block
return@put world.blockRegistry.wrapAsHolder(block).asMoLangValue(Registries.BLOCK)
}
map.put("spawn_explosion") { params ->
val x = params.getDouble(0)
val y = params.getDouble(1)
val z = params.getDouble(2)
val range = params.getDouble(3).toFloat()
world.explode(null, x, y, z, range, ExplosionInteraction.valueOf(params.getStringOrNull(4)?.uppercase() ?: ExplosionInteraction.TNT.name))
}
map.put("spawn_lightning") { params ->
val x = params.getDouble(0)
val y = params.getDouble(1)
val z = params.getDouble(2)
val lightning = LightningBolt(EntityType.LIGHTNING_BOLT, world)
lightning.setPos(x, y, z)
world.addFreshEntity(lightning)
return@put DoubleValue.ONE
}
// q.entity.world.spawn_bedrock_particles(effect, x, y, z, [player]) - sends to everyone nearby or just to the player if they're set.
map.put("spawn_bedrock_particles") { params ->
val particle = params.getString(0).asResource()
val x = params.getDouble(1)
val y = params.getDouble(2)
val z = params.getDouble(3)
val player = params.getOrNull<MoValue>(4)?.let {
if (it is StringValue) world.getPlayerByUUID(UUID.fromString(it.value))
else if (it is ObjectValue<*>) it.obj
else null
} as? ServerPlayer
val pos = Vec3(x, y, z)
if (world !is ClientLevel) {
val packet = SpawnSnowstormParticlePacket(particle, pos)
if (player != null) {
packet.sendToPlayer(player)
} else {
packet.sendToPlayersAround(x, y, z, 64.0, world.dimension())
}
} else {
val effect = BedrockParticleOptionsRepository.getEffect(particle) ?: return@put DoubleValue.ZERO
ParticleStorm.createAtPosition(world, effect, pos).spawn()
}
}
map.put("get_entities_around") { params ->
val x = params.getDouble(0)
val y = params.getDouble(1)
val z = params.getDouble(2)
val range = params.getDouble(3) * 2
val entities = world.getEntities(null, AABB.ofSize(Vec3(x, y, z), range, range, range))
return@put entities
.filterIsInstance<LivingEntity>()
.map { it.asMostSpecificMoLangValue() }
.asArrayValue()
}
return@mutableListOf map
}
)
val dimensionTypeFunctions = mutableListOf<(Holder<DimensionType>) -> HashMap<String, java.util.function.Function<MoParams, Any>>>()
val blockFunctions = mutableListOf<(Holder<Block>) -> HashMap<String, java.util.function.Function<MoParams, Any>>>()
val playerFunctions = mutableListOf<(Player) -> HashMap<String, java.util.function.Function<MoParams, Any>>>(
{ player ->
val map = hashMapOf<String, java.util.function.Function<MoParams, Any>>()
map.put("username") { _ -> StringValue(player.gameProfile.name) }
map.put("uuid") { _ -> StringValue(player.gameProfile.id.toString()) }
map.put("data") { _ -> return@put if (player is ServerPlayer) Cobblemon.molangData.load(player.uuid) else DoubleValue(0) }
map.put("save_data") { _ -> if (player is ServerPlayer) Cobblemon.molangData.save(player.uuid) else DoubleValue(0) }
map.put("main_held_item") { _ -> player.level().itemRegistry.wrapAsHolder(player.mainHandItem.item).asMoLangValue(Registries.ITEM) }
map.put("off_held_item") { _ -> player.level().itemRegistry.wrapAsHolder(player.offhandItem.item).asMoLangValue(Registries.ITEM) }
map.put("face") { params -> ObjectValue(PlayerDialogueFaceProvider(player.uuid, params.getBooleanOrNull(0) != false)) }
map.put("swing_hand") { _ -> player.swing(player.usedItemHand) }
map.put("food_level") { _ -> DoubleValue(player.foodData.foodLevel) }
map.put("saturation_level") { _ -> DoubleValue(player.foodData.saturationLevel) }
// map.put("has_permission") { params -> DoubleValue(Cobblemon.permissionValidator.hasPermission(player, Permission)) }
map.put("tell") { params ->
val message = params.getString(0).text()
val overlay = params.getBooleanOrNull(1) ?: false
val overlay = params.getBooleanOrNull(1) == true
player.displayClientMessage(message, overlay)
}
map.put("teleport") { params ->
@@ -156,7 +338,12 @@ object MoLangFunctions {
environment.query = player.asMoLangValue()
environment
}
map.put("is_player") { DoubleValue.ONE }
if (player is ServerPlayer) {
map.put("run_command") { params ->
val command = params.getString(0)
player.server.commands.performPrefixedCommand(player.createCommandSourceStack(), command)
}
map.put("is_party_at_full_health") { _ ->
DoubleValue(player.party().none(Pokemon::canBeHealed)) }
map.put("can_heal_at_healer") { params ->
@@ -177,11 +364,53 @@ object MoLangFunctions {
return@put DoubleValue.ZERO
}
}
map.put("party") { player.party().struct }
map.put("pc") { player.pc().struct }
map.put("has_permission") { params -> DoubleValue(Cobblemon.permissionValidator.hasPermission(player, params.getString(0), params.getIntOrNull(1) ?: 4)) }
map.put("data") { _ -> Cobblemon.molangData.load(player.uuid) }
map.put("save_data") { _ -> Cobblemon.molangData.save(player.uuid) }
map.put("in_battle") { DoubleValue(player.isInBattle()) }
map.put("battle") { player.getBattleState()?.first?.struct ?: DoubleValue.ZERO }
map.put("get_npc_data") { params ->
val npcId = (params.get<MoValue>(0) as? ObjectValue<NPCEntity>)?.obj?.stringUUID ?: params.getString(0)
val data = Cobblemon.molangData.load(player.uuid)
if (data.map.containsKey(npcId)) {
return@put data.map[npcId]!!
} else {
val vars = VariableStruct()
data.map[npcId] = vars
return@put vars
}
}
map.put("get_npc_variable") { params ->
val npcId = (params.get<MoValue>(0) as? ObjectValue<NPCEntity>)?.obj?.stringUUID ?: params.getString(0)
val variable = params.getString(1)
val data = Cobblemon.molangData.load(player.uuid)
if (data.map.containsKey(npcId)) {
return@put (data.map[npcId] as VariableStruct).map[variable] ?: DoubleValue.ZERO
} else {
return@put DoubleValue.ZERO
}
}
map.put("set_npc_variable") { params ->
val npcId = (params.get<MoValue>(0) as? ObjectValue<NPCEntity>)?.obj?.stringUUID ?: params.getString(0)
val variable = params.getString(1)
val value = params.get<MoValue>(2)
val saveAfterwards = params.getBooleanOrNull(3) != false
val data = Cobblemon.molangData.load(player.uuid)
val npcData = data.map.getOrPut(npcId) { VariableStruct() } as VariableStruct
npcData.map[variable] = value
if (saveAfterwards) {
Cobblemon.molangData.save(player.uuid)
}
return@put DoubleValue.ONE
}
map.put("pokedex") { player.pokedex().struct }
}
map
}
)
val entityFunctions = mutableListOf<(LivingEntity) -> HashMap<String, java.util.function.Function<MoParams, Any>>>(
val entityFunctions: MutableList<(LivingEntity) -> HashMap<String, java.util.function.Function<MoParams, Any>>> = mutableListOf<(LivingEntity) -> HashMap<String, java.util.function.Function<MoParams, Any>>>(
{ entity ->
val map = hashMapOf<String, java.util.function.Function<MoParams, Any>>()
map.put("uuid") { _ -> StringValue(entity.uuid.toString()) }
@@ -190,6 +419,28 @@ object MoLangFunctions {
val source = DamageSource(entity.level().registryAccess().registryOrThrow(Registries.DAMAGE_TYPE).getHolder(DamageTypes.GENERIC).get())
entity.hurt(source, amount.toFloat())
}
map.put("walk_to") { params ->
val x = params.getDouble(0)
val y = params.getDouble(1)
val z = params.getDouble(2)
val speedMultiplier = params.getDoubleOrNull(3) ?: 0.35
if (entity is PathfinderMob) {
if (entity.brain.checkMemory(MemoryModuleType.WALK_TARGET, MemoryStatus.REGISTERED)) {
entity.brain.setMemory(MemoryModuleType.WALK_TARGET, WalkTarget(Vec3(x, y, z), speedMultiplier.toFloat(), 1))
entity.brain.setMemory(MemoryModuleType.LOOK_TARGET, BlockPosTracker(Vec3(x, y + entity.eyeHeight, z)))
} else {
entity.navigation.moveTo(x, y, z, speedMultiplier)
entity.lookControl.setLookAt(Vec3(x, y + entity.eyeHeight, z))
}
}
}
map.put("has_walk_target") { _ ->
if (entity is PathfinderMob) {
DoubleValue(entity.brain.getMemory(MemoryModuleType.WALK_TARGET).isPresent || entity.isPathFinding)
} else {
DoubleValue.ZERO
}
}
map.put("is_sneaking") { _ -> DoubleValue(entity.isShiftKeyDown) }
map.put("is_sprinting") { _ -> DoubleValue(entity.isSprinting) }
map.put("is_flying") { _ -> DoubleValue(entity.isFallFlying) }
@@ -201,10 +452,21 @@ object MoLangFunctions {
map.put("is_on_fire") { _ -> DoubleValue(entity.isOnFire) }
map.put("is_invisible") { _ -> DoubleValue(entity.isInvisible) }
map.put("is_sleeping") { _ -> DoubleValue(entity.isSleeping) }
map.put("is_riding") { _ -> DoubleValue(entity.isPassenger()) }
map.put("is_riding") { _ -> DoubleValue(entity.isPassenger) }
map.put("health") { _ -> DoubleValue(entity.health) }
map.put("distance_to_pos") { params ->
val x = params.getDouble(0)
val y = params.getDouble(1)
val z = params.getDouble(2)
return@put DoubleValue(sqrt(entity.distanceToSqr(Vec3(x, y, z))))
}
map.put("max_health") { _ -> DoubleValue(entity.maxHealth) }
map.put("name") { _ -> StringValue(entity.effectiveName().string) }
map.put("type") { _ ->
entity.registryAccess().registry(Registries.ENTITY_TYPE).get().getKey(entity.type)?.toString()?.let {
StringValue(it)
} ?: DoubleValue.ZERO
}
map.put("yaw") { _ -> DoubleValue(entity.yRot.toDouble()) }
map.put("pitch") { _ -> DoubleValue(entity.xRot.toDouble()) }
map.put("x") { _ -> DoubleValue(entity.x) }
@@ -218,7 +480,7 @@ object MoLangFunctions {
map.put("entity_size") { DoubleValue(entity.boundingBox.run { if (xsize > ysize) xsize else ysize }) }
map.put("entity_width") { DoubleValue(entity.boundingBox.xsize) }
map.put("entity_height") { DoubleValue(entity.boundingBox.ysize) }
map.put("id_modulo") { params -> DoubleValue(entity.uuid.hashCode() % params.getDouble(0)) }
map.put("horizontal_velocity") { _ -> DoubleValue(entity.deltaMovement.horizontalDistance()) }
map.put("vertical_velocity") { DoubleValue(entity.deltaMovement.y) }
map.put("is_on_ground") { _ -> DoubleValue(entity.onGround()) }
@@ -244,6 +506,67 @@ object MoLangFunctions {
return@put DoubleValue.ZERO
}
}
map.put("get_nearby_entities") { params ->
val distance = params.getDouble(0)
val entities = entity.level().getEntities(entity, AABB.ofSize(entity.position(), distance, distance, distance))
return@put entities
.filterIsInstance<LivingEntity>()
.map { it.asMostSpecificMoLangValue() }
.asArrayValue()
}
map.put("is_standing_on_blocks") { params ->
val depth = params.getDouble(0).toInt()
val blocks: MutableSet<Block> = mutableSetOf()
for (blockIndex in 1..<params.params.size) {
val blockString = params.getString(blockIndex)
val block = BuiltInRegistries.BLOCK.get(blockString.asIdentifierDefaultingNamespace("minecraft"))
blocks.add(block)
}
return@put if (entity.isStandingOn(blocks, depth)) DoubleValue.ONE else DoubleValue.ZERO
}
if (entity is PosableEntity) {
map.put("play_animation") { params ->
val animation = params.getString(0)
val packet = PlayPosableAnimationPacket(entity.id, setOf(animation), emptyList())
val target = params.getStringOrNull(1)
if (target != null) {
val targetPlayer = if (target.asUUID != null) {
entity.level().getPlayerByUUID(target.asUUID!!) as ServerPlayer
} else if (entity.level() is ServerLevel) {
entity.level().server!!.playerList.getPlayerByName(target)
} else {
null
}
if (targetPlayer != null) {
packet.sendToPlayer(targetPlayer)
return@put DoubleValue.ONE
} else {
return@put DoubleValue.ZERO
}
} else {
packet.sendToPlayersAround(entity.x, entity.y, entity.z, 64.0, entity.level().dimension())
return@put DoubleValue.ONE
}
}
}
// q.entity.spawn_bedrock_particles(effect, locator, [player]) - sends to everyone nearby or just to the player if they're set. Locator is necessary even if unused on non-posables.
map.put("spawn_bedrock_particles") { params ->
val particle = params.getString(0).asResource()
val locator = params.getString(1)
val player = params.getOrNull<MoValue>(2)?.let {
if (it is StringValue) entity.level().getPlayerByUUID(UUID.fromString(it.value))
else if (it is ObjectValue<*>) it.obj
else null
} as? ServerPlayer
val packet = SpawnSnowstormEntityParticlePacket(particle, entity.id, listOf(locator))
if (player == null) {
packet.sendToPlayersAround(entity.x, entity.y, entity.z, 64.0, entity.level().dimension())
} else {
packet.sendToPlayer(player)
}
}
map
}
)
@@ -256,6 +579,17 @@ object MoLangFunctions {
map.put("has_aspect") { params -> DoubleValue(npc.aspects.contains(params.getString(0))) }
map.put("face") { params -> ObjectValue(ReferenceDialogueFaceProvider(npc.id, params.getBooleanOrNull(0) != false)) }
map.put("in_battle") { DoubleValue(npc.isInBattle()) }
map.put("battles") { ArrayStruct(npc.battleIds.mapNotNull { BattleRegistry.getBattle(it)?.struct }.mapIndexed { index, value -> "$index" to value }.toMap()) }
map.put("stop_battles") { _ -> npc.battleIds.forEach { BattleRegistry.getBattle(it)?.stop() } }
map.put("is_doing_activity") { params ->
val identifiers = params.params.map { it.asString().asIdentifierDefaultingNamespace(namespace = "minecraft") }
val activities = identifiers.mapNotNull { identifier -> BuiltInRegistries.ACTIVITY.get(identifier) }
if (activities.isNotEmpty()) {
return@put DoubleValue(activities.any { activity -> npc.brain.isActive(activity) })
} else {
return@put DoubleValue.ZERO
}
}
map.put("run_script_on_client") { params ->
val world = npc.level()
if (world is ServerLevel) {
@@ -280,22 +614,23 @@ object MoLangFunctions {
val context = ActionEffectContext(
actionEffect = actionEffect,
providers = mutableListOf(NPCProvider(npc)),
runtime = runtime
runtime = runtime,
level = npc.level()
)
npc.actionEffect = context
npc.brain.setMemory(CobblemonMemories.ACTIVE_ACTION_EFFECT, context)
npc.brain.setActiveActivityIfPossible(CobblemonActivities.NPC_ACTION_EFFECT)
npc.brain.setActiveActivityIfPossible(CobblemonActivities.ACTION_EFFECT)
actionEffect.run(context).thenRun {
val npcActionEffect = npc.brain.getMemory(CobblemonMemories.ACTIVE_ACTION_EFFECT).orElse(null)
if (npcActionEffect == context && npc.brain.isActive(CobblemonActivities.NPC_ACTION_EFFECT)) {
if (npcActionEffect == context && npc.brain.isActive(CobblemonActivities.ACTION_EFFECT)) {
npc.brain.eraseMemory(CobblemonMemories.ACTIVE_ACTION_EFFECT)
npc.actionEffect = null
}
}
return@put DoubleValue(1)
return@put DoubleValue.ONE
}
return@put DoubleValue(0)
return@put DoubleValue.ZERO
}
map.put("put_pokemon_in_healer") { params ->
val healer = npc.level().getBlockEntity(params.get<ArrayStruct>(0).asBlockPos(), CobblemonBlockEntities.HEALING_MACHINE).orElse(null) ?: return@put DoubleValue.ZERO
@@ -312,6 +647,10 @@ object MoLangFunctions {
npc.lookAt(EntityAnchorArgument.Anchor.EYES, pos)
}
map.put("environment") { _ -> npc.runtime.environment }
map.put("party") { npc.party?.struct ?: DoubleValue.ZERO }
map.put("has_party") { DoubleValue(npc.party != null) }
map.put("is_npc") { DoubleValue.ONE }
map.put("can_battle") { DoubleValue(npc.party?.any { it.currentHealth > 0 } == true || npc.npc.party?.isStatic == false) }
map
}
)
@@ -330,17 +669,60 @@ object MoLangFunctions {
val actor = battle.actors.find { it.uuid == uuid } ?: return@put DoubleValue.ZERO
return@put actor.struct
}
map.put("stop") { _ -> battle.stop() }
map.put("actors") { battle.actors.toList().asArrayValue { it.struct } }
map
}
)
val battleActorFunctions = mutableListOf<(BattleActor) -> HashMap<String, java.util.function.Function<MoParams, Any>>>(
{ battleActor ->
val map = hashMapOf<String, java.util.function.Function<MoParams, Any>>()
map.put("is_npc") { DoubleValue(battleActor.type == ActorType.NPC) }
map.put("is_player") { DoubleValue(battleActor.type == ActorType.PLAYER) }
map.put("is_wild") { DoubleValue(battleActor.type == ActorType.WILD) }
if (battleActor is NPCBattleActor) {
map.put("npc") { battleActor.entity.struct }
} else if (battleActor is PlayerBattleActor) {
map.put("player") { battleActor.entity?.asMoLangValue() ?: DoubleValue.ZERO }
}
return@mutableListOf map
}
)
val pokemonFunctions = mutableListOf<(Pokemon) -> HashMap<String, java.util.function.Function<MoParams, Any>>>(
{ pokemon ->
val map = hashMapOf<String, java.util.function.Function<MoParams, Any>>()
map.put("id") { StringValue(pokemon.uuid.toString()) }
map.put("level") { DoubleValue(pokemon.level.toDouble()) }
map.put("max_hp") { DoubleValue(pokemon.maxHealth.toDouble()) }
map.put("current_hp") { DoubleValue(pokemon.currentHealth.toDouble()) }
map.put("friendship") { DoubleValue(pokemon.friendship.toDouble()) }
map.put("evs") {
val struct = QueryStruct(hashMapOf())
for (stat in Stats.PERMANENT) {
struct.addFunction(stat.showdownId) { DoubleValue(pokemon.evs.getOrDefault(stat).toDouble()) }
}
struct
}
map.put("ivs") {
val struct = QueryStruct(hashMapOf())
for (stat in Stats.PERMANENT) {
struct.addFunction(stat.showdownId) { DoubleValue(pokemon.ivs.getOrDefault(stat).toDouble()) }
}
struct
}
map.put("is_wild") { DoubleValue(pokemon.entity?.let { it.ownerUUID == null } == true) }
map.put("is_shiny") { DoubleValue(pokemon.shiny) }
map.put("species") { pokemon.species.struct }
map.put("form") { StringValue(pokemon.form.name) }
map.put("weight") { DoubleValue(pokemon.species.weight.toDouble()) }
map.put("matches") { params -> DoubleValue(params.getString(0).toProperties().matches(pokemon)) }
map.put("apply") { params ->
params.getString(0).toProperties().apply(pokemon)
DoubleValue.ONE
}
map.put("owner") { pokemon.getOwnerPlayer()?.asMoLangValue() ?: DoubleValue.ZERO }
map
}
)
@@ -352,6 +734,83 @@ object MoLangFunctions {
map.put("is_moving") { DoubleValue((pokemonEntity.moveControl as? PokemonMoveControl)?.hasWanted() == true) }
map.put("is_flying") { DoubleValue(pokemonEntity.getBehaviourFlag(PokemonBehaviourFlag.FLYING)) }
map.put("has_aspect") { DoubleValue(it.getString(0) in pokemonEntity.aspects) }
map.put("is_pokemon") { DoubleValue.ONE }
map
}
)
val pokemonStoreFunctions = mutableListOf<(PokemonStore<*>) -> HashMap<String, java.util.function.Function<MoParams, Any>>>(
{ store ->
val map = hashMapOf<String, java.util.function.Function<MoParams, Any>>()
map.put("add") { params ->
val pokemon = params.get<ObjectValue<Pokemon>>(0)
return@put DoubleValue(store.add(pokemon.obj))
}
map.put("add_by_properties") { params ->
val props = params.getString(0).toProperties()
val player = (store as? PlayerPartyStore)?.playerUUID?.getPlayer() // Only really know for sure when it's a player party store
val pokemon = props.create(player = player)
return@put DoubleValue(store.add(pokemon))
}
map.put("find_by_properties") { params ->
val props = params.getString(0).toProperties()
val pokemon = store.find { props.matches(it) }
return@put pokemon?.asStruct() ?: DoubleValue.ZERO
}
map.put("find_all_by_properties") { params ->
val props = params.getString(0).toProperties()
val pokemon = store.filter { props.matches(it) }
return@put ArrayStruct(pokemon.mapIndexed { index, value -> "$index" to value.asStruct() }.toMap())
}
map.put("find_by_id") { params ->
val id = params.getString(0).asUUID
val pokemon = store.find { it.uuid == id }
return@put pokemon?.asStruct() ?: DoubleValue.ZERO
}
map.put("remove_by_id") { params ->
val id = params.getString(0).asUUID
val pokemon = store.find { it.uuid == id } ?: return@put DoubleValue.ZERO
return@put DoubleValue(store.remove(pokemon))
}
map.put("average_level") { _ ->
var numberOfPokemon = 0
var totalLevel = 0
for (pokemon in store) {
totalLevel += pokemon.level
numberOfPokemon++
}
if (numberOfPokemon == 0) {
return@put DoubleValue.ZERO
}
return@put DoubleValue(totalLevel.toDouble() / numberOfPokemon)
}
map.put("count") { _ -> DoubleValue(store.count()) }
map.put("count_by_properties") { params ->
val props = params.getString(0).toProperties()
return@put DoubleValue(store.count { props.matches(it) })
}
map.put("highest_level") {
val highest = store.maxOfOrNull { it.level } ?: 0
return@put DoubleValue(highest)
}
map.put("lowest_level") {
val lowest = store.minOfOrNull { it.level } ?: 0
return@put DoubleValue(lowest)
}
map.put("heal") {
for (pokemon in store) {
pokemon.heal()
}
return@put DoubleValue.ONE
}
map.put("healing_remainder_percent") { _ ->
var totalPercent = 0.0f
for (pokemon in store) {
totalPercent += (1.0f - (pokemon.currentHealth.toFloat() / pokemon.maxHealth))
}
DoubleValue(totalPercent)
}
map.put("has_usable_pokemon") { _ -> DoubleValue(store.any { !it.isFainted() }) }
map
}
)
@@ -362,19 +821,192 @@ object MoLangFunctions {
map.put("get_pokemon") { params ->
val index = params.getInt(0)
val pokemon = party.get(index) ?: return@put DoubleValue.ZERO
val struct = VariableStruct()
pokemon.writeVariables(struct)
return@put struct
return@put pokemon.struct
}
map.put("healing_remainder_percent") { _ -> DoubleValue(party.getHealingRemainderPercent()) }
return@mutableListOf map
})
fun Holder<Biome>.asBiomeMoLangValue() = asMoLangValue(Registries.BIOME).addFunctions(biomeFunctions)
fun Holder<Level>.asWorldMoLangValue() = asMoLangValue(Registries.DIMENSION).addFunctions(worldFunctions)
fun Holder<Block>.asBlockMoLangValue() = asMoLangValue(Registries.BLOCK).addFunctions(blockFunctions)
fun Holder<DimensionType>.asDimensionTypeMoLangValue() = asMoLangValue(Registries.DIMENSION_TYPE).addFunctions(dimensionTypeFunctions)
val pcFunctions = mutableListOf<(PCStore) -> HashMap<String, java.util.function.Function<MoParams, Any>>>(
{ pc ->
val map = hashMapOf<String, java.util.function.Function<MoParams, Any>>()
map.put("get_pokemon") { params ->
val box = params.getInt(0)
val slot = params.getInt(1)
val pokemon = pc[PCPosition(box, slot)] ?: return@put DoubleValue.ZERO
return@put pokemon.struct
}
map.put("resize") { params ->
val newSize = params.getInt(0)
val lockNewSize = params.getBooleanOrNull(1) == true
pc.resize(newSize, lockNewSize)
return@put DoubleValue.ONE
}
map.put("get_box_count") { _ -> DoubleValue(pc.boxes.size.toDouble()) }
return@mutableListOf map
}
)
val spawningContextFunctions = mutableListOf<(SpawningContext) -> HashMap<String, java.util.function.Function<MoParams, Any>>>(
{ spawningContext ->
val map = hashMapOf<String, java.util.function.Function<MoParams, Any>>()
val worldValue = spawningContext.world.registryAccess().registryOrThrow(Registries.DIMENSION).wrapAsHolder(spawningContext.world).asWorldMoLangValue()
val biomeValue = spawningContext.biomeRegistry.wrapAsHolder(spawningContext.biome).asBiomeMoLangValue()
map.put("biome") { _ -> biomeValue }
map.put("world") { _ -> worldValue }
map.put("light") { _ -> DoubleValue(spawningContext.light.toDouble()) }
map.put("x") { _ -> DoubleValue(spawningContext.position.x.toDouble()) }
map.put("y") { _ -> DoubleValue(spawningContext.position.y.toDouble()) }
map.put("z") { _ -> DoubleValue(spawningContext.position.z.toDouble()) }
map.put("moon_phase") { _ -> DoubleValue(spawningContext.moonPhase.toDouble()) }
map.put("can_see_sky") { _ -> DoubleValue(spawningContext.canSeeSky) }
map.put("sky_light") { _ -> DoubleValue(spawningContext.skyLight.toDouble()) }
map.put("bucket") { _ -> StringValue(spawningContext.cause.bucket.name) }
map.put("player") { _ ->
val causeEntity = spawningContext.cause.entity ?: return@put DoubleValue.ZERO
if (causeEntity is ServerPlayer) {
return@put causeEntity.asMoLangValue()
} else {
return@put DoubleValue.ZERO
}
}
map
}
)
val serverFunctions: MutableList<(MinecraftServer) -> HashMap<String, java.util.function.Function<MoParams, Any>>> = mutableListOf(
{ server ->
val map = hashMapOf<String, java.util.function.Function<MoParams, Any>>()
map.put("get_world") { params ->
val world = server.getLevel(
ResourceKey.create(
Registries.DIMENSION,
params.getString(0).asIdentifierDefaultingNamespace(namespace = "minecraft")
)
) ?: return@put DoubleValue.ZERO
return@put world
.registryAccess()
.registryOrThrow(Registries.DIMENSION)
.wrapAsHolder(world)
.asWorldMoLangValue()
}
map.put("broadcast") { params ->
val message = params.getString(0)
server.playerList.broadcastSystemMessage(message.text(), params.getBooleanOrNull(1) == true)
return@put DoubleValue.ONE
}
map.put("get_player_by_uuid") { params ->
val uuid = UUID.fromString(params.getString(0))
val player = server.playerList.getPlayer(uuid) ?: return@put DoubleValue.ZERO
return@put player.asMoLangValue()
}
map.put("get_player_by_username") { params ->
val username = params.getString(0)
val player = server.playerList.getPlayerByName(username) ?: return@put DoubleValue.ZERO
return@put player.asMoLangValue()
}
map.put("data") { params ->
val data = Cobblemon.molangData.load(UUID(0L, 0L))
return@put data
}
map.put("save_data") {
Cobblemon.molangData.save(UUID(0L, 0L))
return@put DoubleValue.ONE
}
// Maybe later...
// map.put("stop") { params ->
// Cobblemon.LOGGER.warn("Server is being stopped from a MoLang script.")
// server.stopServer()
// }
return@mutableListOf map
}
)
val pokedexFunctions: MutableList<(AbstractPokedexManager) -> HashMap<String, java.util.function.Function<MoParams, Any>>> = mutableListOf(
{ pokedex ->
val map = hashMapOf<String, java.util.function.Function<MoParams, Any>>()
map.put("get_species_record") { params ->
val speciesId = params.getString(0).asIdentifierDefaultingNamespace()
pokedex.speciesRecords[speciesId]?.struct ?: QueryStruct(hashMapOf())
}
map.put("has_seen") { params ->
val speciesId = params.getString(0).asIdentifierDefaultingNamespace()
val formName = params.getStringOrNull(1)
if (formName == null) {
return@put DoubleValue(pokedex.getHighestKnowledgeForSpecies(speciesId).ordinal >= PokedexEntryProgress.ENCOUNTERED.ordinal)
} else {
return@put DoubleValue((pokedex.getSpeciesRecord(speciesId)?.getFormRecord(formName)?.knowledge?.ordinal ?: 0) >= PokedexEntryProgress.ENCOUNTERED.ordinal)
}
}
map.put("has_caught") { params ->
val speciesId = params.getString(0).asIdentifierDefaultingNamespace()
val formName = params.getStringOrNull(1)
if (formName == null) {
return@put DoubleValue(pokedex.getHighestKnowledgeForSpecies(speciesId) == PokedexEntryProgress.CAUGHT)
} else {
return@put DoubleValue(pokedex.getSpeciesRecord(speciesId)?.getFormRecord(formName)?.knowledge == PokedexEntryProgress.CAUGHT)
}
}
map.put("caught_count") { DoubleValue(pokedex.getGlobalCalculatedValue(CaughtCount)) }
map.put("seen_count") { DoubleValue(pokedex.getGlobalCalculatedValue(SeenCount)) }
map.put("caught_percent") { DoubleValue(pokedex.getGlobalCalculatedValue(CaughtPercent)) }
map.put("seen_percent") { DoubleValue(pokedex.getGlobalCalculatedValue(SeenPercent)) }
if (pokedex is PokedexManager) {
map.put("player_id") { StringValue(pokedex.uuid.toString()) }
map.put("see") { params ->
val pokemon = params.get<ObjectValue<Pokemon>>(0).obj
pokedex.encounter(pokemon)
return@put DoubleValue.ONE
}
map.put("catch") { params ->
val pokemon = params.get<ObjectValue<Pokemon>>(0).obj
pokedex.catch(pokemon)
return@put DoubleValue.ONE
}
}
map
}
)
val speciesFunctions: MutableList<(Species) -> HashMap<String, java.util.function.Function<MoParams, Any>>> = mutableListOf(
{ species ->
val map = hashMapOf<String, java.util.function.Function<MoParams, Any>>()
map.put("identifier") { StringValue(species.resourceIdentifier.toString()) }
map.put("name") { StringValue(species.name) }
map.put("primary_type") { StringValue(species.primaryType.name) }
map.put("secondary_type") { StringValue(species.secondaryType?.name ?: "null") }
map.put("experience_group") { StringValue(species.experienceGroup.name) }
map.put("height") { DoubleValue(species.height) }
map.put("weight") { DoubleValue(species.weight) }
map.put("base_scale") { DoubleValue(species.baseScale) }
map.put("hitbox_width") { DoubleValue(species.hitbox.width) }
map.put("hitbox_height") { DoubleValue(species.hitbox.height) }
map.put("hitbox_fixed") { DoubleValue(species.hitbox.fixed) }
map.put("catch_rate") { DoubleValue(species.catchRate) }
map
}
)
fun Holder<Biome>.asBiomeMoLangValue() = asMoLangValue(Registries.BIOME).addFunctions(biomeFunctions.flatMap { it(this).entries.map { it.key to it.value } }.toMap())
fun Holder<Level>.asWorldMoLangValue() = asMoLangValue(Registries.DIMENSION).addFunctions(worldFunctions.flatMap { it(this).entries.map { it.key to it.value } }.toMap())
fun Holder<Block>.asBlockMoLangValue() = asMoLangValue(Registries.BLOCK).addFunctions(blockFunctions.flatMap { it(this).entries.map { it.key to it.value } }.toMap())
fun MinecraftServer.asMoLangValue() = ObjectValue(this).addStandardFunctions().addFunctions(serverFunctions.flatMap { it(this).entries.map { it.key to it.value } }.toMap())
fun Holder<DimensionType>.asDimensionTypeMoLangValue() = asMoLangValue(Registries.DIMENSION_TYPE).addFunctions(dimensionTypeFunctions.flatMap { it(this).entries.map { it.key to it.value } }.toMap())
fun Player.asMoLangValue(): ObjectValue<Player> {
val value = ObjectValue(
obj = this,
@@ -385,6 +1017,33 @@ object MoLangFunctions {
return value
}
// We need to migrate the writeVariables thing to be all about query structs, variable doesn't make sense and I don't want to break fringe 1.6 compatibility issues close to release
fun Pokemon.asStruct(): ObjectValue<Pokemon> {
val queryStruct = ObjectValue(this)
queryStruct.addFunctions(pokemonFunctions.flatMap { it(this).entries.map { it.key to it.value } }.toMap())
return queryStruct
}
fun PartyStore.asMoLangValue(): ObjectValue<PartyStore> {
val value = ObjectValue(
obj = this,
stringify = { it.toString() }
)
value.addFunctions(pokemonStoreFunctions.flatMap { it(this).entries.map { it.key to it.value } }.toMap())
value.addFunctions(partyFunctions.flatMap { it(this).entries.map { it.key to it.value } }.toMap())
return value
}
fun PCStore.asMoLangValue(): ObjectValue<PCStore> {
val value = ObjectValue(
obj = this,
stringify = { it.toString() }
)
value.addFunctions(pokemonStoreFunctions.flatMap { it(this).entries.map { it.key to it.value } }.toMap())
value.addFunctions(pcFunctions.flatMap { it(this).entries.map { it.key to it.value } }.toMap())
return value
}
fun NPCEntity.asMoLangValue(): ObjectValue<NPCEntity> {
val value = ObjectValue(
obj = this,
@@ -395,6 +1054,17 @@ object MoLangFunctions {
return value
}
fun PokemonEntity.asMoLangValue(): ObjectValue<PokemonEntity> {
val value = ObjectValue(
obj = this,
stringify = { it.pokemon.uuid.toString() }
)
value.addFunctions(entityFunctions.flatMap { it(this).entries.map { it.key to it.value } }.toMap())
value.addFunctions(pokemonFunctions.flatMap { it(this.pokemon).entries.map { it.key to it.value } }.toMap()) // Convenience
value.addFunctions(pokemonEntityFunctions.flatMap { it(this).entries.map { it.key to it.value } }.toMap())
return value
}
fun PokemonBattle.asMoLangValue(): ObjectValue<PokemonBattle> {
val value = ObjectValue(
obj = this,
@@ -404,6 +1074,36 @@ object MoLangFunctions {
return value
}
fun BattleActor.asMoLangValue(): ObjectValue<BattleActor> {
val value = ObjectValue(
obj = this,
stringify = { it.toString() }
)
value.addFunctions(battleActorFunctions.flatMap { it(this).entries.map { it.key to it.value } }.toMap())
return value
}
fun SpawningContext.asMoLangValue(): ObjectValue<SpawningContext> {
val value = ObjectValue(
obj = this,
stringify = { it.toString() }
)
value.addFunctions(spawningContextFunctions.flatMap { it(this).entries.map { it.key to it.value } }.toMap())
return value
}
/**
* Different functions exist depending on
*/
fun LivingEntity.asMostSpecificMoLangValue(): ObjectValue<out LivingEntity> {
return when (this) {
is Player -> asMoLangValue()
is PokemonEntity -> struct
is NPCEntity -> struct
else -> ObjectValue(this).also { it.addStandardFunctions().addFunctions(entityFunctions.flatMap { it(this).entries.map { it.key to it.value } }.toMap()) }
}
}
fun <T> Holder<T>.asMoLangValue(key: ResourceKey<Registry<T>>): ObjectValue<Holder<T>> {
val value = ObjectValue(
obj = this,
@@ -433,6 +1133,22 @@ object MoLangFunctions {
return this
}
fun QueryStruct.addPokedexFunctions(pokedexManager: AbstractPokedexManager): QueryStruct {
val addedFunctions = pokedexFunctions
.flatMap { it.invoke(pokedexManager).entries }
.associate { it.key to it.value }
functions.putAll(addedFunctions)
return this
}
fun QueryStruct.addSpeciesFunctions(species: Species): QueryStruct {
val addedFunctions = speciesFunctions
.flatMap { it.invoke(species).entries }
.associate { it.key to it.value }
functions.putAll(addedFunctions)
return this
}
fun QueryStruct.addPokemonFunctions(pokemon: Pokemon): QueryStruct {
val addedFunctions = pokemonFunctions
.flatMap { it.invoke(pokemon).entries }
@@ -8,6 +8,12 @@
package com.cobblemon.mod.common.api.moves
import com.bedrockk.molang.runtime.MoParams
import com.bedrockk.molang.runtime.struct.QueryStruct
import com.bedrockk.molang.runtime.value.DoubleValue
import com.bedrockk.molang.runtime.value.StringValue
import com.cobblemon.mod.common.api.molang.MoLangFunctions.addFunctions
import com.cobblemon.mod.common.api.molang.ObjectValue
import com.cobblemon.mod.common.api.moves.categories.DamageCategory
import com.cobblemon.mod.common.api.reactive.SimpleObservable
import com.cobblemon.mod.common.api.types.ElementalType
@@ -25,6 +31,7 @@ import com.mojang.serialization.codecs.RecordCodecBuilder
import kotlin.math.ceil
import kotlin.properties.Delegates
import net.minecraft.network.chat.MutableComponent
import java.util.function.Function
/**
* Representing a Move based on some template and with current PP and the number of raised PP stages.
@@ -90,6 +97,21 @@ open class Move(
val maxPp: Int
get() = template.pp + raisedPpStages * template.pp / 5
val struct: QueryStruct = ObjectValue(this).also {
it.addFunctions(
hashMapOf(
"name" to Function { StringValue(name) },
"display_name" to Function { StringValue(displayName.string) },
"description" to Function { StringValue(description.string) },
"type" to Function { StringValue(type.name) },
"damage_category" to Function { StringValue(damageCategory.name) },
"power" to Function { DoubleValue(power) },
"accuracy" to Function { DoubleValue(accuracy) },
"max_pp" to Function { DoubleValue(maxPp.toDouble()) }
)
)
}
/** Raises the max PP and rescales the current PP value. Returns false if it was already maxed out. */
fun raiseMaxPP(amount: Int): Boolean {
val oldPp = maxPp
@@ -8,6 +8,8 @@
package com.cobblemon.mod.common.api.moves
import com.bedrockk.molang.runtime.struct.QueryStruct
import com.bedrockk.molang.runtime.value.DoubleValue
import com.cobblemon.mod.common.api.reactive.SimpleObservable
import com.cobblemon.mod.common.net.IntSize
import com.cobblemon.mod.common.util.DataKeys
@@ -27,6 +29,22 @@ class MoveSet : Iterable<Move> {
private val moves = arrayOfNulls<Move>(MOVE_COUNT)
fun toStruct(): QueryStruct {
val struct = QueryStruct(hashMapOf())
struct.addFunction("move") { params ->
val index = params.getInt(0) as? Int ?: return@addFunction null
return@addFunction get(index)?.struct
}
struct.addFunction("has_move") { params ->
val moveID = params.getString(0) ?: return@addFunction null
return@addFunction if(moves.any { it?.template?.name == moveID }) DoubleValue(1.0) else DoubleValue(0.0)
}
struct.addFunction("get_move") { params ->
val moveID = params.getString(0) ?: return@addFunction null
return@addFunction moves.firstOrNull { it?.template?.name == moveID }?.struct
}
return struct
}
override fun iterator() = moves.filterNotNull().iterator()
@@ -15,6 +15,7 @@ import com.cobblemon.mod.common.entity.npc.NPCEntity
import com.cobblemon.mod.common.util.asExpressionLike
import com.cobblemon.mod.common.util.resolveBoolean
import net.minecraft.world.entity.Entity
import net.minecraft.world.level.Level
import java.util.concurrent.CompletableFuture
/**
@@ -69,7 +70,8 @@ class ActionEffectContext(
val runtime: MoLangRuntime,
var canBeInterrupted: Boolean = false,
var interrupted: Boolean = false,
var currentKeyframes: MutableList<ActionEffectKeyframe> = mutableListOf()
var currentKeyframes: MutableList<ActionEffectKeyframe> = mutableListOf(),
var level: Level? = null
) {
inline fun <reified T> findOneProvider() = providers.filterIsInstance<T>().firstOrNull()
}
@@ -36,7 +36,7 @@ class AnimationActionEffectKeyframe : ConditionalActionEffectKeyframe(), EntityC
// Treat them as expressions if possible but otherwise yeah just send them as strings
val animation = animation.map {
try {
it.asExpressionLike().resolveString(context.runtime).takeIf { it != "0.0" } ?: it
it.asExpressionLike().resolveString(context.runtime).takeIf { it != "0" } ?: it
} catch (e: Exception) {
it
}

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