Compare commits

..
Author SHA1 Message Date
Landon Wills 09a0cd6c30 Start restructure of camera transformations 2025-04-27 07:46:20 -04:00
Hiroku 30f82bbad6 Merge branch 'flashback-compat' into 'main'
Fix flashback crash

See merge request cable-mc/cobblemon!1629
2025-04-26 07:45:13 +00:00
Hiroku 1823eb4979 Merge branch 'npc-stealth' into 'main'
[molang] easy access npc hiding

See merge request cable-mc/cobblemon!1573
2025-04-26 04:09:36 +00:00
Apion ae4af68797 Fix compile errors 2025-04-25 21:55:26 -04:00
Polymeta da7f4a2682 Merge branch 'oopsies-fix-cake-texture' into 'main'
Add new cooking pot recipes, fix EV yield berry effects, fix other recipes,...

See merge request cable-mc/cobblemon!1637
2025-04-25 22:27:50 +00:00
Polymeta 73c4762801 Merge branch 'new-recipes-fix-recipes-fix-baits-color-cakes' into 'main'
Add new cooking pot recipes, fix EV yield berry effects, fix other recipes,...

See merge request cable-mc/cobblemon!1636
2025-04-25 21:21:49 +00:00
Plastered_Crab 43abfa3c17 New Lure/Poke Cake item sprites for tinting 2025-04-25 14:20:07 -07:00
Plastered_Crab fb87220fe9 Add new cooking pot recipes, fix EV yield berry effects, fix other recipes, add color to Lure/Poke Cake item texture 2025-04-25 13:33:59 -07:00
Landon 2a0de32854 Merge branch 'fix-species-config' into 'main'
Fix misconfigured riding behaviours preventing world load

See merge request cable-mc/cobblemon!1635
2025-04-25 17:07:45 +00:00
Landon Wills 406097c1ff Fix misconfigured riding behaviours preventing world load 2025-04-25 12:27:28 -04:00
Landon 14ec3c00e6 Merge branch 'cleanup-camera-mixin' into 'main'
Cleanup camera mixin

See merge request cable-mc/cobblemon!1633
2025-04-25 16:26:09 +00:00
Landon 18b17b0638 Merge branch 'riding-behaviour-additions-01' into 'main'
Refine air behaviour controls. rideAltPose now returns a ResourceLocation for unique pose control. Update...

See merge request cable-mc/cobblemon!1626
2025-04-25 16:09:33 +00:00
Jackson Bowes 59c96fe30d Merge branch 'main' into 'riding-behaviour-additions-01'
# Conflicts:
#   common/src/main/kotlin/com/cobblemon/mod/common/api/riding/behaviour/types/GliderAirBehaviour.kt
2025-04-25 09:34:23 -05:00
JacksonB 565667aa1c Address MR comments 2025-04-25 09:29:17 -05:00
Polymeta 3955283425 Merge branch 'treeafying-saccharine' into 'main'
Tree-afying the Saccharine Tree to reflect vanilla tree behaviour

See merge request cable-mc/cobblemon!1631
2025-04-25 12:50:31 +00:00
AramandPolymeta beee02033c Tree-afying the Saccharine Tree to reflect vanilla tree behaviour 2025-04-25 12:50:30 +00:00
Polymeta 86902b69e1 fix duplicate mixin entry and server error when unlocking wallpapers
Signed-off-by: Polymeta <40173118+Polymeta@users.noreply.github.com>
2025-04-25 00:29:24 +01:00
JPAK 2ac102a3b6 Fix issue with pivot offset & update licenses. 2025-04-24 16:23:04 -05:00
Polymeta a54ff5f0a7 Merge branch 'fix-server-crash' into 'main'
Move client code in PlayerMixin to LocalPlayerMixin to fix crash.

See merge request cable-mc/cobblemon!1632
2025-04-24 19:53:36 +00:00
JPAK edc5ae741c Move large amounts of render code from CameraMixin to new MountedCameraRenderer.kt 2025-04-24 14:50:29 -05:00
JPAK 70bed4f299 Move client code in PlayerMixin to LocalPlayerMixin to fix crash. 2025-04-24 14:10:41 -05:00
Polymeta e24b20546d Merge branch 'first_person_poser' into 'main'
Add poser option to offset first person camera while riding. This is in...

See merge request cable-mc/cobblemon!1600
2025-04-24 11:54:47 +00:00
Polymeta eb071d4d01 Merge branch 'we_are_cooking_now' into 'main'
Cooking

See merge request cable-mc/cobblemon!1535
2025-04-24 11:42:56 +00:00
Polymeta 625a31e7e8 fix another server-side error
Signed-off-by: Polymeta <40173118+Polymeta@users.noreply.github.com>
2025-04-24 11:41:52 +01:00
Polymeta 2b14931709 licenses
Signed-off-by: Polymeta <40173118+Polymeta@users.noreply.github.com>
2025-04-24 11:15:32 +01:00
Polymeta 2c32b50182 fix server crash and small cleanup
Signed-off-by: Polymeta <40173118+Polymeta@users.noreply.github.com>
2025-04-24 11:12:41 +01:00
Plastered_Crab b5230a8d3c Merge with main and register IncenseSweetProspector 2025-04-23 16:39:14 -07:00
Plastered_Crab 5ff3d163c0 Merge branch 'main' into we_are_cooking_now
# Conflicts:
#	common/src/main/kotlin/com/cobblemon/mod/common/entity/pokemon/PokemonEntity.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/net/messages/client/spawn/SpawnPokemonPacket.kt
#	common/src/main/resources/mixins.cobblemon-common.json
2025-04-23 16:06:41 -07:00
Plastered_Crab 82e6e01978 Add Sweet Incense to the POI system and add Prospector and Influence 2025-04-23 16:01:10 -07:00
JPAK a6b5f2d64c Add thirdPersonPivotOffset to posers. Meant to be the player's location relative to the base of the pokemon when the pokemon's center is too far from the player. 2025-04-23 14:44:48 -05:00
JPAK 6408b60dde Merge branch 'main' into riding-render-and-stuff 2025-04-23 13:59:56 -05:00
Polymeta b6308e6c6c rideable pokemon are also allowed to turn their heads if no one is actually riding them
Closes #1530

Signed-off-by: Polymeta <40173118+Polymeta@users.noreply.github.com>
2025-04-22 15:28:54 +01:00
Apion 84a0ceb7e1 Remove flashback dep (again) 2025-04-21 17:45:05 -04:00
Apion ccde7ffbb1 Merge branch 'main' into flashback-compat 2025-04-21 17:41:35 -04:00
apionandApion 4e79ed9f7e Remove flashback dep 2025-04-21 17:41:09 -04:00
JacksonB ecefea005d Merge branch 'main' into riding-behaviour-additions-01 2025-04-20 23:13:46 -05:00
JacksonB 4c787f547c Bird is finally feeling how it was always meant to feel!! 2025-04-20 22:27:36 -05:00
JacksonB f0755cc73f Merge branch 'riding-debug-ui' into riding-behaviour-additions-01 2025-04-20 22:27:04 -05:00
Hiroku e215d751c4 Merge branch 'ouch_fire_blocks' into 'main'
Floating Pokemon really float, and Fire Immunity attribute

See merge request cable-mc/cobblemon!1612
2025-04-21 02:05:29 +00:00
CeejayandHiroku aac4669ec1 Floating Pokemon really float, and Fire Immunity attribute 2025-04-21 02:05:28 +00:00
Landon 7b0b41d192 Merge branch 'riding-debug-ui' into 'main'
Riding Debug UI

See merge request cable-mc/cobblemon!1623
2025-04-21 01:33:18 +00:00
JacksonB 7e38fefa14 various controller tweaks 2025-04-20 17:00:21 -05:00
plastered_crab c1491daf63 Placing honey on Saccharine Logs now gives higher chance of Hidden Abilities nearby 2025-04-20 11:09:58 -07:00
Polymeta 068b55be7b Merge branch 'josh/dynamic-light-integration' into 'main'
Josh/dynamic light integration

See merge request cable-mc/cobblemon!1621
2025-04-20 13:52:34 +00:00
JoshandPolymeta 3f6bd52d43 Josh/dynamic light integration 2025-04-20 13:52:34 +00:00
Polymeta 4ca3f25ab2 Merge branch 'translucent-culling' into 'main'
Translucent Culling Parameter

See merge request cable-mc/cobblemon!1606
2025-04-20 09:47:02 +00:00
GertimoshkaandPolymeta 70e81f1cbe Translucent Culling Parameter 2025-04-20 09:47:02 +00:00
Polymeta df8abf4ddb Merge branch 'josh/left-handed-item-fix' into 'main'
Item position adjustment to perfectly line up hand-held items

See merge request cable-mc/cobblemon!1610
2025-04-20 09:46:28 +00:00
JoshandPolymeta 26dd0b9d42 Item position adjustment to perfectly line up hand-held items 2025-04-20 09:46:28 +00:00
plastered_crab 307d8bad1d Added new Honey Log and Lure Cakes can have more bites 2025-04-20 00:16:07 -07:00
Landon Wills 866332e62c Remove composite logic from debug gui 2025-04-19 23:17:59 -04:00
Landon Wills c54466f6b1 Merge branch 'refs/heads/main' into riding-debug-ui 2025-04-19 23:14:18 -04:00
Landon Wills fb570404c0 Update licenses 2025-04-19 22:29:34 -04:00
Landon Wills d22602dac5 Update visibility of debug variables 2025-04-19 22:26:27 -04:00
Aram 63da8fed2d Removed the Sweet Sap item 2025-04-20 02:42:43 +02:00
Paul 2f16ba5470 Don't play quirks in battle GUI 2025-04-20 08:53:39 +10:00
Aram af36d4a365 Saccharine Log now has code for when you use items on it 2025-04-20 00:52:58 +02:00
Aram d153ec155b Beehive only generates in Saccharine tree if theres a flower when it grows up 2025-04-20 00:31:59 +02:00
Aram 7ca7cc089a Removed the Age in the Saccharine Stripped Log 2025-04-19 23:36:48 +02:00
Landon cbdfbc9745 Merge branch 'pc-box-name-limit' into 'main'
Adds name character length restriction to PC box name.

See merge request cable-mc/cobblemon!1620
2025-04-19 11:28:15 +00:00
Hiroku ac210e027b Merge branch 'windows-12' into 'main'
more pc stat displays

See merge request cable-mc/cobblemon!1617
2025-04-19 11:04:57 +00:00
TestandHiroku 1fc91a794f more pc stat displays 2025-04-19 11:04:57 +00:00
Landon f78b289171 Merge branch 'riding-dismount' into 'main'
Created the Pokemon Dismount Logic

See merge request cable-mc/cobblemon!1613
2025-04-19 10:47:16 +00:00
AramandLandon c46461c843 Created the Pokemon Dismount Logic 2025-04-19 10:47:16 +00:00
Deltric 386a897295 Adds name character length restriction to PC box name. 2025-04-19 05:46:22 -05:00
Hiroku 8328f741d8 Merge branch 'spawn-pool-observable' into 'main'
Observable in SpawnPool was not emitted on reload.

See merge request cable-mc/cobblemon!1618
2025-04-19 09:07:56 +00:00
Deltric 2b19943416 Observable in SpawnPool was not emitted on reload. 2025-04-19 03:30:50 -05:00
plastered_crab 5239de2cea Merge branch 'refs/heads/we_are_cooking_now(Seasoning-Bait-Testing)' into we_are_cooking_now 2025-04-18 17:13:13 -07:00
JacksonB 296355f744 Ride stat reversions 2025-04-18 12:04:38 -05:00
JacksonB e9d9a109c0 Squashed commit of the following:
commit 8960c6dddc
Author: Landon Wills <landonjwdev@gmail.com>
Date:   Fri Apr 18 03:11:19 2025 -0400

    Fix issue with ride stat calc

commit bc1f9f8cb4
Author: Landon Wills <landonjwdev@gmail.com>
Date:   Fri Apr 18 02:54:42 2025 -0400

    Add riding debug UI
2025-04-18 10:49:50 -05:00
JacksonB 8a3789fc35 Merge branch 'main' into riding-behaviour-additions-01 2025-04-18 10:45:36 -05:00
JacksonB 05fd7bec36 Line up land walk with animation walk speed 2025-04-18 10:36:21 -05:00
Paul 550b99be36 Merge remote-tracking branch 'origin/main' into lang-updates 2025-04-18 22:01:33 +10:00
Landon Wills 8960c6dddc Fix issue with ride stat calc 2025-04-18 03:11:19 -04:00
Polymeta bfbee7b1d7 Merge branch 'loot-fix' into 'main'
Improved parity with vanilla mobs' drop behavior

See merge request cable-mc/cobblemon!1576
2025-04-18 07:02:45 +00:00
Landon Wills bc1f9f8cb4 Add riding debug UI 2025-04-18 02:54:42 -04:00
Test f5d71390dd Merge branch 'dex-zoom' into 'main'
A few dex scanner fixes/improvements, closes #1328

Closes #1328

See merge request cable-mc/cobblemon!1608
2025-04-18 05:06:31 +00:00
CraterandTest 6ff5d3df06 A few dex scanner fixes/improvements, closes #1328 2025-04-18 05:06:30 +00:00
gruxor 988766894a Review resolutions 2025-04-18 00:08:43 -04:00
Polymeta 34805ea496 oop typo - allow dragon breath to be used in a restoration tank
Closes #1539

Signed-off-by: Polymeta <40173118+Polymeta@users.noreply.github.com>
2025-04-18 00:25:39 +01:00
Polymeta b670d44e21 reorder delegate molang functions to be added first so they are overridden by more specific functions
Also allow PoseableState sound molang to play without an entity present (in UIs)

Closes #1529

Signed-off-by: Polymeta <40173118+Polymeta@users.noreply.github.com>
2025-04-18 00:08:59 +01:00
Polymeta 159905eb3b Merge branch 'josh/left-handed-item-fix' into 'main'
Corrected item rotation for left hand display context

See merge request cable-mc/cobblemon!1609
2025-04-17 20:32:11 +00:00
Josh c10213480b Flip rotations when display context is left hand 2025-04-17 15:22:11 -04:00
gruxor 3d5a365a6e Added a configuration option for drops' behavior upon Pokémon death 2025-04-17 14:06:33 -04:00
gruxor 4b64b4307a Changelog update 2025-04-17 14:04:16 -04:00
gruxor 382f741db8 Improved parity with vanilla mobs' drop behavior 2025-04-17 14:04:16 -04:00
TeggyandWeblate 6d62d911d6 Translated using Weblate (Spanish)
Currently translated at 96.6% (6787 of 7021 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/es/
2025-04-17 11:38:28 +00:00
Alexis SalgueiroandWeblate a1d40084c5 Translated using Weblate (French)
Currently translated at 92.2% (6479 of 7021 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/fr/
2025-04-17 04:04:45 +00:00
TeggyandWeblate 8b1b63e110 Translated using Weblate (Spanish)
Currently translated at 96.4% (6775 of 7021 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/es/
2025-04-17 04:04:44 +00:00
JacksonB a7956531ff Forgot this 2025-04-16 18:04:54 -05:00
JacksonB 4b0919223b rideAltPose now returns a ResourceLocation for unique pose control. Update molang function naming issues. Add transformToTick field in poser jsons so that a pose can specify the transformTick of any pose transitioning to the given one. 2025-04-16 18:03:10 -05:00
Polymeta baf3cd5f30 Merge branch 'moon-ball-fix-🌕🌒🌓🌔🌑🌘🌗🌖' into 'main'
Fix the messed up Moon Phase code for the Moon Ball catch rate

See merge request cable-mc/cobblemon!1605
2025-04-16 17:16:36 +00:00
Plastered_Crab 2327f1aa2c Add this to make Polymeta happy 2025-04-16 09:46:11 -07:00
plastered_crab 62036c0ac6 Fix the messed up Moon Phase code for the Moon Ball catch rate 2025-04-16 07:57:00 -07:00
TeggyandWeblate 9e2e95e287 Translated using Weblate (Spanish)
Currently translated at 96.0% (6744 of 7021 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/es/
2025-04-16 09:42:42 +00:00
Landon 2db494ff5e Merge branch 'Dex-Species-Forms' into 'main'
Update English Lang with official values and preliminary species form support for the dex

See merge request cable-mc/cobblemon!1454
2025-04-16 04:43:43 +00:00
Konoha 7fe1415551 Clean InfoWidget form parsing. 2025-04-15 23:24:56 -04:00
Konoha ca4d4ed3be Re-Run Lang Key Scrape & Changelog 2025-04-15 09:02:29 -04:00
Konoha 700227be41 Merge branch 'main' into Dex-Species-Forms
# Conflicts:
#	common/src/main/resources/assets/cobblemon/lang/en_us.json
2025-04-15 08:39:33 -04:00
Konoha 985a4f65dc Re-Run Lang Key Scrape & Changelog 2025-04-15 08:16:41 -04:00
Konoha e117100e34 Re-Run Lang Key Scrape & Changelog 2025-04-15 08:06:10 -04:00
Konoha 93ea13fa4d Merge branch 'main' into Dex-Species-Forms 2025-04-15 07:57:01 -04:00
TeggyandWeblate 6694680c50 Translated using Weblate (Spanish)
Currently translated at 95.9% (6735 of 7021 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/es/
2025-04-15 05:11:49 +00:00
Polymeta cd14881d17 Merge branch 'immersive-tweaks' into 'main'
Foods and Recipes

See merge request cable-mc/cobblemon!1554
2025-04-14 20:45:41 +00:00
dhi_holoandPolymeta 1393cc3ef3 Foods and Recipes 2025-04-14 20:45:40 +00:00
Konoha 23ebd0573a Merge branch 'implement_pokemon' into Dex-Species-Forms
# Conflicts:
#	common/src/main/resources/assets/cobblemon/lang/en_us.json
2025-04-14 08:05:18 -04:00
Polymeta 6447c2e2eb Merge branch 'per-world-gamerule-support' into 'main'
Add per-level gamerule support for doPokemonSpawning

See merge request cable-mc/cobblemon!1593
2025-04-14 11:32:54 +00:00
TeggyandWeblate 8cafce0a4a Translated using Weblate (Spanish)
Currently translated at 95.7% (6724 of 7021 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/es/
2025-04-14 10:33:04 +00:00
BlackBeltPanda 039a18a2bf Update CHANGELOG.md 2025-04-14 04:46:06 -04:00
Watuneni iteiteandWeblate de271f81b1 Translated using Weblate (Japanese)
Currently translated at 76.4% (5365 of 7021 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/ja/
2025-04-14 06:50:20 +00:00
TeggyandWeblate feb78c5c58 Translated using Weblate (Spanish)
Currently translated at 95.3% (6698 of 7021 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/es/
2025-04-14 06:50:19 +00:00
JacksonB 8aedac3474 More gyarados tests 2025-04-14 00:05:25 -05:00
FrankTheFarmer 71736341f0 Merge branch 'main' into implement_pokemon 2025-04-14 13:55:12 +10:00
JacksonB ca133a20c0 Jet input decay, new wip behaviour, gyarados ride body tests. 2025-04-13 17:57:06 -05:00
Landon bb6e5607f1 Merge branch 'stop-head-pitch' into 'main'
Make head moving actually stop this time.

See merge request cable-mc/cobblemon!1596
2025-04-13 04:55:00 +00:00
Landon 4603f5ac7a Merge branch 'riding-animation-01' into 'main'
Riding dynamic animation, riding fixes, and controller tweaks

See merge request cable-mc/cobblemon!1599
2025-04-12 23:59:31 +00:00
Jackson BowesandLandon c683294227 Riding dynamic animation, riding fixes, and controller tweaks 2025-04-12 23:59:31 +00:00
JPAK acc601d414 Add poser option to offset first person camera while riding. This is in addition to the locator and shouldn't need to be used often. 2025-04-12 17:12:20 -05:00
JPAK f29c2343e6 Merge remote-tracking branch 'origin/stop-head-pitch' into stop-head-pitch 2025-04-12 16:41:40 -05:00
JPAK 3a2da5a87d Make head moving actually stop this time. 2025-04-12 16:41:13 -05:00
QriviateA 27d1de8e4e Merge remote-tracking branch 'origin/implement_pokemon' into implement_pokemon 2025-04-12 17:14:04 +01:00
MiaandWeblate e5d052a6bf Translated using Weblate (German)
Currently translated at 86.7% (6090 of 7021 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/de/
2025-04-12 10:41:09 +00:00
Landon 1c13ab24e8 Merge branch 'even-more-riding-tweaks' into 'main'
Even more riding tweaks

See merge request cable-mc/cobblemon!1597
2025-04-12 03:07:36 +00:00
Paul 380cf0ea71 You? You're meant to be dead! 2025-04-12 12:29:44 +10:00
Paul 8ded7334bb Refactor forcedTick handling in PosableEntityModel 2025-04-12 12:23:17 +10:00
QriviateA 8af62f800b Updated changelog 2025-04-12 01:27:10 +01:00
QriviateA a50da47a8e Updated Kangaskhan model + anims 2025-04-12 01:26:47 +01:00
QriviateA f690781b0d Updated Cinderace model + anims 2025-04-12 01:26:16 +01:00
FrankTheFarmer 6a7fc67ae1 Merge branch 'main' into implement_pokemon 2025-04-12 08:10:08 +10:00
Polymeta 0ac34bf1a4 Merge branch 'locator-rotation-player-rendering' into 'main'
Lock player model to seat locator's rotation when riding

See merge request cable-mc/cobblemon!1598
2025-04-11 19:41:47 +00:00
Landon Wills 9716ea0806 Fix rotation of player when using custom camera 2025-04-11 06:13:47 -04:00
Landon Wills ffea94f3b2 Rotate player depending on seat locator's rotation 2025-04-11 03:39:49 -04:00
Landon Wills 3061ba69e2 Riding momentum is maintained when window is not active 2025-04-11 03:17:26 -04:00
Landon Wills 741e38d606 Fix issue where same-species pokemon will sync animations on multiplayer environments 2025-04-11 02:01:28 -04:00
Landon Wills 02f2c072c9 Fix issues with pre-animation logic 2025-04-11 01:29:49 -04:00
Paul cf9d794fe1 I demand you compile 2025-04-11 11:57:23 +10:00
Paul 14a3e7afb1 Merge remote-tracking branch 'origin/main' into we_are_cooking_now
# Conflicts:
#	common/src/main/kotlin/com/cobblemon/mod/common/CobblemonItems.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/CobblemonNetwork.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/api/riding/RidingManager.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/client/render/models/blockbench/PosableState.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/entity/pokemon/PokemonEntity.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/net/messages/client/spawn/SpawnPokemonPacket.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/pokemon/riding/controllers/GliderAirController.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/pokemon/riding/controllers/VehicleLandController.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/util/DataKeys.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/util/codec/internal/ClientPokemonP3.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/util/codec/internal/PokemonP3.kt
#	common/src/main/resources/mixins.cobblemon-common.json
2025-04-11 10:08:28 +10:00
JPAK 4722defec2 Make head moving actually stop this time. 2025-04-10 13:14:32 -05:00
Polymeta c54849f415 Merge branch 'implement_pokemon' into 'main'
Few mons added for testing

See merge request cable-mc/cobblemon!1595
2025-04-10 13:46:35 +00:00
Frank The FarmerandPolymeta d44e625e9d Few mons added for testing 2025-04-10 13:46:35 +00:00
FrankTheFarmer 7b7acb97d1 Changelog 2025-04-10 23:05:56 +10:00
FrankTheFarmer 53af92f254 Implemented Metagross with locators for testing 2025-04-10 23:04:07 +10:00
FrankTheFarmer 91bce4b153 Merge branch 'main' into implement_pokemon 2025-04-10 22:32:31 +10:00
BlackBeltPanda 511130d353 Remove redundant check for player UUID in spawnersForPlayers and early return in registerPlayerSpawner 2025-04-10 05:42:10 -04:00
BlackBeltPanda 476c3e54f1 Return early in CobbledWorldSpawnerManager#onDimensionChange when DO_POKEMON_SPAWNING gamerule is equal in origin and destination levels 2025-04-10 05:40:13 -04:00
Polymeta 6a74d5982a Merge branch 'more-riding-tweaks' into 'main'
Riding tweaks / fixes

See merge request cable-mc/cobblemon!1594
2025-04-10 09:13:32 +00:00
Landon Wills 03905c77d2 Add license 2025-04-10 03:12:53 -04:00
FrankTheFarmer 4bfe8b808c Implemented Magnezone with locators for testing 2025-04-10 16:36:21 +10:00
FrankTheFarmer 8db943d2a9 Merge branch 'main' into implement_pokemon 2025-04-10 16:34:54 +10:00
FrankTheFarmer fdff6ecfa5 Implemented Magnezone with locators for testing 2025-04-10 16:33:51 +10:00
BlackBeltPanda 2eb698969d Add onDimensionChange method to CobbledWorldSpawnerManager 2025-04-10 01:52:12 -04:00
BlackBeltPanda bba60f0098 Check DO_POKEMON_SPAWNING gamerule for the correct Level in SpawnerManager#onServerTick and CobbledWorldSpawnerManager#onPLayerLogin 2025-04-10 01:50:33 -04:00
BlackBeltPanda 8ee2c95853 Add unregisterPlayerSpawner and registerPlayerSpawner methods to CobbledWorldSpawnerManager 2025-04-10 01:45:43 -04:00
BlackBeltPanda 77db2ce17a Add origin and destination ServerLevel properties to ChangeDimensionEvent 2025-04-10 01:43:59 -04:00
Landon Wills da9558f5f9 Fix camera riding momentum not occurring when in chat or screens 2025-04-10 01:40:44 -04:00
Landon Wills 5c65dffac8 Improve rendering of ridden pokemon substantially on low or inconsistent FPS 2025-04-09 23:36:21 -04:00
Landon Wills b67b37c99e Fix some issues with merge 2025-04-09 22:54:23 -04:00
Landon Wills fbb7ee31c5 Merge branch 'refs/heads/main' into water-mount-behaviours 2025-04-09 22:38:45 -04:00
Polymeta d3ef26976b Merge branch 'composite-behaviour-refactor' into 'main'
Composite behaviour refactor

See merge request cable-mc/cobblemon!1584
2025-04-09 15:58:55 +00:00
Landon Wills dac01a3730 Fix issue with crashing on packet decode before player is initialized 2025-04-09 03:30:55 -04:00
Landon Wills ddb05768e4 Remove redundant riding behaviour, rename ride style option from misc to composite 2025-04-09 03:17:31 -04:00
Polymeta 5374940d24 Merge branch 'spicy-molang' into 'main'
Added `spawn_pokemon` and `attempt_wild_battle` as available MoLang functions

Closes #1237

See merge request cable-mc/cobblemon!1586
2025-04-09 07:13:00 +00:00
SpicyandPolymeta 1fd6a660dd Added spawn_pokemon and attempt_wild_battle as available MoLang functions 2025-04-09 07:13:00 +00:00
Landon Wills fd45934775 Fix issue with canRide condition, remove duplicate riding config in aerodactyl 2025-04-09 03:09:04 -04:00
Polymeta 5e0ffd8bd3 Merge branch 'josh/item-molang-fixes' into 'main'
Small fixes for molang functions related to item rendering.

See merge request cable-mc/cobblemon!1590
2025-04-08 16:02:48 +00:00
JoshandPolymeta b4b315360d Small fixes for molang functions related to item rendering. 2025-04-08 16:02:48 +00:00
Polymeta a44c70648b actually return held item to player again
Signed-off-by: Polymeta <40173118+Polymeta@users.noreply.github.com>
2025-04-08 16:07:20 +01:00
Polymeta c41b0cdca2 Merge branch 'negative-config-values' into 'main'
Allow negative numbers in config GUI

See merge request cable-mc/cobblemon!1588
2025-04-08 12:01:45 +00:00
lionandPolymeta 88f743ee48 Allow negative numbers in config GUI 2025-04-08 12:01:44 +00:00
Polymeta 15b9afacf8 remove client logic from common code MoLang functions
Signed-off-by: Polymeta <40173118+Polymeta@users.noreply.github.com>
2025-04-08 12:59:36 +01:00
TeggyandWeblate 0ea4641536 Translated using Weblate (Spanish)
Currently translated at 95.3% (6696 of 7021 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/es/
2025-04-08 10:41:46 +00:00
Polymeta babcf7430b don't error when heldItem nbt is not present
Closes #1505

Signed-off-by: Polymeta <40173118+Polymeta@users.noreply.github.com>
2025-04-08 11:38:05 +01:00
Polymeta 3439ca2011 [skip-ci] fix tag docs formatting
Signed-off-by: Polymeta <40173118+Polymeta@users.noreply.github.com>
2025-04-08 10:55:48 +01:00
FrankTheFarmer ff5ea6fa21 Merge branch 'main' into implement_pokemon 2025-04-08 19:42:22 +10:00
Polymeta 6539f3dea1 Merge branch 'josh/3d-wearable-items' into 'main'
Start of wearable item implementation.

See merge request cable-mc/cobblemon!1579
2025-04-08 09:16:24 +00:00
FrankTheFarmer 4820d78416 Implemented Jolteon's item holding animation 2025-04-08 19:05:35 +10:00
FrankTheFarmer 2f417e953c Added placeholder cry to the eeveelution animations 2025-04-08 18:38:39 +10:00
FrankTheFarmer 8fde0ed4f6 Added rootbone and cry back to the eeveelution posers 2025-04-08 18:38:08 +10:00
FrankTheFarmer 6715874a8f Merge branch 'main' into implement_pokemon 2025-04-08 16:00:52 +10:00
RedGenesectNinja 31f88a1f68 Implemented Druddigon 2025-04-08 00:37:09 -05:00
Landon Wills 1677598ec0 Merge branch 'refs/heads/main' into water-mount-behaviours
# Conflicts:
#	common/src/main/java/com/cobblemon/mod/common/mixin/client/CameraMixin.java
2025-04-08 01:36:01 -04:00
Landon fcde1eb171 Merge branch 'hitbox-and-hit' into 'main'
Position hitbox on client to be accurate to the locator and make looking at...

See merge request cable-mc/cobblemon!1589
2025-04-08 03:26:26 +00:00
Josh a30a5644df Okay, this is it this time for real 2025-04-07 23:03:30 -04:00
JPAK a5672a38b9 Switch to using delegates to position riders. 2025-04-07 21:37:42 -05:00
JPAK 3b14ea319b Position hitbox on client to be accurate to the locator and make looking at stuff align to the camera. 2025-04-07 21:12:01 -05:00
Landon Wills 57e2765f90 Clean up some method signatures in CameraMixin 2025-04-07 21:57:20 -04:00
Josh a090c90831 Merge branch 'main' into josh/3d-wearable-items 2025-04-07 20:55:41 -04:00
FrankTheFarmer f80aa2769a Restored Treecko line cries 2025-04-08 10:55:39 +10:00
FrankTheFarmer 20aa4d43b8 Delphox wand animation tweaks 2025-04-08 09:19:10 +10:00
FrankTheFarmer 9bec3e088f Changelog moment 2025-04-08 08:42:49 +10:00
FrankTheFarmer 5b4dbe1957 Imported old placeholder walk and cry for Braixen and Delphox 2025-04-08 08:36:19 +10:00
FrankTheFarmer 48f248d481 Fixed a crash caused by cosmetic remodels for Braixen and Delphox. 2025-04-08 08:36:00 +10:00
FrankTheFarmer d726c4d0ed Merge branch 'main' into implement_pokemon
# Conflicts:
#	common/src/main/kotlin/com/cobblemon/mod/common/client/render/models/blockbench/repository/VaryingModelRepository.kt
2025-04-08 08:19:12 +10:00
Josh 5dcc9ba46d Edit CHANGELOG.md 2025-04-07 21:21:05 +00:00
Josh f8e4ea70df Removed debug models. 2025-04-07 17:09:15 -04:00
Josh 5dc1c749f3 Replaced WearableItemModel enum with WearableItem class. Instances of this class should have a corresponding 3D model in models/item/wearable/ 2025-04-07 16:35:46 -04:00
Polymeta 3accfa29b7 Merge branch 'josh/joint-transform-command' into 'main'
Changed command "changejointscale" into "transformmodelpart". Allows you to easily add model transformations in-game.

See merge request cable-mc/cobblemon!1587
2025-04-07 17:18:56 +00:00
Josh 1af1569f63 Updated CHANGELOG.md 2025-04-07 11:13:27 -04:00
FrankTheFarmer c9c421ba2a Fixed Sneasler model issues from previous update for cosmetic basket. 2025-04-07 21:00:12 +10:00
FrankTheFarmer 2436a8ddcc Fixed Tropius typo in changelog 2025-04-07 20:04:13 +10:00
FrankTheFarmer 3364944c26 Merge remote-tracking branch 'origin/implement_pokemon' into implement_pokemon 2025-04-07 19:57:12 +10:00
FrankTheFarmer 9e6a6eabc7 Fixed the wrong type of Crocs mentioned in the changelog 2025-04-07 19:55:57 +10:00
FrankTheFarmer 78def7318e Treecko my beloved. Gave json poser and fixed t-pose 2025-04-07 19:55:09 +10:00
FrankTheFarmer fdf062bd4c oops, fixed dex number for grovyle poser 2025-04-07 19:44:37 +10:00
FrankTheFarmer ef5a682adb Fixed stick related Grovyle crash and gave it a JSON poser 2025-04-07 19:41:11 +10:00
Polymeta dbd2f5d340 Merge branch 'implement_pokemon' into 'main'
Implemented many pokemon

See merge request cable-mc/cobblemon!1585
2025-04-07 09:35:47 +00:00
Frank The FarmerandPolymeta 86bf413f00 Implemented many pokemon 2025-04-07 09:35:46 +00:00
Polymeta f76d28d29e updated changelog 2025-04-07 09:35:20 +00:00
FrankTheFarmer 9c70aad64d Fixed stick related Sceptile crash and gave it a JSON poser 2025-04-07 19:17:56 +10:00
FrankTheFarmer 25de1ad180 Merge branch 'main' into implement_pokemon 2025-04-07 15:13:02 +10:00
FrankTheFarmer f967d1ec11 Merge remote-tracking branch 'origin/implement_pokemon' into implement_pokemon 2025-04-07 15:12:10 +10:00
FrankTheFarmer efd0497de1 Fixed Garchomp using battle idle in its portrait and profile 2025-04-07 15:00:47 +10:00
Landon f13e7d03a1 Merge branch 'camera-changes-third-person' into 'main'
Riding Third Person Camera

See merge request cable-mc/cobblemon!1582
2025-04-07 02:51:07 +00:00
JordanandLandon 4a025ac65e Riding Third Person Camera 2025-04-07 02:51:07 +00:00
Josh 8a0c98c9ab Renamed command to transformmodelpart 2025-04-06 18:58:13 -04:00
Josh 36c5fe2419 Properly display name of model part. 2025-04-06 18:52:15 -04:00
Josh 0c79d102cf Changed changejointscale command into transformpartcommand with can cahnge the position rotation and scale of any joint on a model. 2025-04-06 18:31:39 -04:00
Polymeta b14b25ae19 Merge branch 'SaferSendouts' into 'main'
Safer sendouts

See merge request cable-mc/cobblemon!1458
2025-04-06 20:58:09 +00:00
Kenji_64 b30c0a4a9a Adjusted Nosepass' walk speed. (Thanks Lennie and Frank!) 2025-04-06 22:21:25 +02:00
Kenji_64 c99b26a44b Added animations to Nosepass and Probopass. Made new JSON posers and replaced the Kotlin ones (thanks Lennie!) 2025-04-06 21:06:37 +02:00
Josh bd8f644b9a Add scaling as an option when creating transformedParts 2025-04-06 10:56:10 -04:00
Josh 7c84cdb05d transformedParts must add to the model part rather than replacing it with set() 2025-04-06 10:54:00 -04:00
FrankTheFarmer b19bc1e4c7 updated changelog 2025-04-06 21:21:37 +10:00
FrankTheFarmer bc5ffda1a5 Expedited crobat with locators 2025-04-06 21:19:09 +10:00
FrankTheFarmer 491d6c9fd6 Expedited salamence with locators 2025-04-06 21:19:01 +10:00
FrankTheFarmer ccc6ad77a5 Garchomp and perchance the craziest poser that ever lived 2025-04-06 19:47:02 +10:00
FrankTheFarmer 00fd9d1278 oopsies forgot portrait and profile data on honchkrow 2025-04-06 19:47:02 +10:00
FrankTheFarmer 01464f8b71 Expediting more models for reasons the government will not allow me to explain 2025-04-06 19:47:01 +10:00
FrankTheFarmer d91fe0b876 Merge branch 'main' into implement_pokemon 2025-04-06 18:56:00 +10:00
Landon Wills 0293c0e811 Update licenses 2025-04-06 04:02:10 -04:00
Landon 125975e25f Merge branch 'item-with-components-swap' into 'main'
Fixed not being able to swap held item of the same type, but have different components.

See merge request cable-mc/cobblemon!1580
2025-04-06 05:42:42 +00:00
Landon Wills c7223ae898 Fix some issues with the new composite system, move assets to new system 2025-04-06 01:35:46 -04:00
Landon baf766298a Merge branch 'riding-ground-render-revert' into 'main'
revert broken ground rendering code. Correctly set stale yrot value on return...

See merge request cable-mc/cobblemon!1583
2025-04-06 05:11:30 +00:00
Jackson BowesandLandon 83580e7e8b revert broken ground rendering code. Correctly set stale yrot value on return... 2025-04-06 05:11:30 +00:00
plastered_crab 4de32b8bf4 Tweak rarity bucket calculating 2025-04-05 21:19:40 -07:00
Landon Wills 38f5c12dce Remove some redundant casting 2025-04-05 23:59:47 -04:00
Landon Wills e6a9a27692 Forgot to remove some code I refactored 2025-04-05 23:59:21 -04:00
Landon Wills 7ff413c401 Add support for custom behaviour settings for different composite strategies 2025-04-05 23:57:30 -04:00
plastered_crab 9d6447af9a Rarity bucket bait effect combines with Luck of the Sea 2025-04-05 20:39:17 -07:00
Test 90335ccb2d hide mark scroll when unused 2025-04-05 17:26:09 -04:00
plastered_crab 7eb5f93595 Added bait effects for enchanted gold apple, gold carrot, and glistening melon slice 2025-04-05 12:47:20 -07:00
plastered_crab 3b54fa488e Added bait effects for enchanted gold apple, gold carrot, and glistening melon slice 2025-04-05 12:43:05 -07:00
plastered_crab 69e9cb3f22 Tweaks to the Rarity Bucket effect on Gapple item 2025-04-05 12:31:33 -07:00
plastered_crab 4eb268c4af More tweaks to the rarity bucket effect 2025-04-05 12:23:02 -07:00
plastered_crab 909b5b7f7f Alter Rarity Bucket Effects and block merging of rarity bucket effects 2025-04-05 12:01:30 -07:00
plastered_crab e2c28ab5a0 Merge branch 'refs/heads/we_are_cooking_now' into we_are_cooking_now(Seasoning-Bait-Testing)
# Conflicts:
#	common/src/main/kotlin/com/cobblemon/mod/common/api/spawning/influence/SpawnBaitInfluence.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/client/tooltips/FishingBaitTooltipGenerator.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/item/crafting/BaitSeasoningProcessor.kt
2025-04-05 11:09:08 -07:00
plastered_crab 890d0a2099 New Rarity Bucket bait effect can cooked into Lures/Bait + tooltips 2025-04-05 01:58:13 -07:00
Landon Wills 603f99e5f3 Refactor composite behaviours 2025-04-05 04:24:19 -04:00
plastered_crab 74075e6be9 Merge remote-tracking branch 'origin/we_are_cooking_now(Seasoning-Bait-Testing)' into we_are_cooking_now(Seasoning-Bait-Testing)
# Conflicts:
#	common/src/main/kotlin/com/cobblemon/mod/common/api/spawning/spawner/TickingSpawner.kt
2025-04-05 00:45:17 -07:00
plastered_crab b8ae6aa889 Ground work for testing a new bait type that can affect rarity of spawn buckets 2025-04-05 00:43:23 -07:00
Landon Wills 1b53a127af Add lapras assets 2025-04-05 01:39:02 -04:00
plastered_crab a499e8593a Cooking now combines similar bait effects, letting you make some effects more powerful 2025-04-04 22:10:42 -07:00
Josh 9679929694 Merge branch 'main' into 'item-with-components-swap'
# Conflicts:
#   common/src/main/kotlin/com/cobblemon/mod/common/entity/pokemon/PokemonEntity.kt
2025-04-05 02:01:27 +00:00
Landon fd6fb5db47 Merge branch 'riding-friction-change' into 'main'
Decouple minecraft friction logic for better feeling controllers. Limit speed...

See merge request cable-mc/cobblemon!1581
2025-04-05 00:21:27 +00:00
Jackson BowesandLandon a80ada8590 Decouple minecraft friction logic for better feeling controllers. Limit speed... 2025-04-05 00:21:27 +00:00
FrankTheFarmer 3f6faf7796 Merge branch 'main' into implement_pokemon 2025-04-05 09:24:40 +10:00
Plastered_Crab 08633c223e Example code for combining similar bait effects. Needs review if we want to do this. 2025-04-04 15:50:56 -07:00
Landon c4a4b9cb86 Merge branch 'multiplayer-riding' into 'main'
Multiplayer support for riding

See merge request cable-mc/cobblemon!1578
2025-04-04 21:15:55 +00:00
Josh 5af96e75eb Fixed message when swapping items.
Used `displayName` rather than `hoverName` for more dynamic text in message.
2025-04-04 13:35:09 -04:00
Sterrezo d5efdeee68 More adjustments to the cry checker script 2025-04-04 19:06:22 +02:00
Josh 023a01befd Can now swap pokemon's held items if the components are different. 2025-04-04 13:03:49 -04:00
Polymeta 4912a89e6e pokemon are allowed to turn their heads when they are not ridden
Signed-off-by: Polymeta <40173118+Polymeta@users.noreply.github.com>
2025-04-04 13:12:16 +01:00
Polymeta f2e10d1b01 Merge branch 'refs/heads/main' into multiplayer-riding
# Conflicts:
#	common/src/main/kotlin/com/cobblemon/mod/common/CobblemonNetwork.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/entity/pokemon/PokemonEntity.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/net/messages/client/spawn/SpawnPokemonPacket.kt
2025-04-04 12:54:10 +01:00
Hiroku 25eb197491 Merge branch 'ribs' into 'main'
🎀

See merge request cable-mc/cobblemon!1566
2025-04-04 10:13:58 +00:00
TestandHiroku 8de233b572 🎀 2025-04-04 10:13:58 +00:00
Landon Wills 83972ca9e6 Hook up a couple more pokemon for bird controller 2025-04-04 03:50:34 -04:00
Landon Wills 35e2190cae Reset orientation properly on landing 2025-04-04 02:33:23 -04:00
Landon Wills b966cd2db0 Fix issue with orientation tracking for rendering 2025-04-04 02:06:06 -04:00
queao 57f446260c just gonna drop these in here (added remodels for eevee and all eeveelutions) 2025-04-04 15:53:56 +10:00
Landon Wills 3e492541cc Fix issue with registry sync on riding properties 2025-04-04 01:40:27 -04:00
JazzMcNade cc2022ed59 Merge branch 'main' into SaferSendouts 2025-04-03 20:30:24 -05:00
Josh 298fdf45d5 Adjusted default position and scale values for wearables. Any additional transformations for a specific pokemon should be done in its posers. 2025-04-03 20:47:09 -04:00
Polymeta 4e9541d7f5 licenses
Signed-off-by: Polymeta <40173118+Polymeta@users.noreply.github.com>
2025-04-03 23:24:11 +01:00
Josh 1dab5b8c7c Added debug models to help with aligning wearable items on pokemon. 2025-04-03 17:03:26 -04:00
Landon Wills 2875e9efa9 Temporary fix to crashing issue due to pokemon sticking around when they shouldnt be 2025-04-03 16:27:44 -04:00
Landon Wills 2b42fff66b Fix issue with players sometimes launching at odd angles when riding 2025-04-03 16:26:54 -04:00
Landon Wills 643a33a643 Prevent crouching moving the player when riding pokemon 2025-04-03 16:26:34 -04:00
Landon Wills e348c48eff Fix reversed third person camera 2025-04-03 14:25:03 -04:00
Landon Wills 473f58cab9 No more random render flickers yippee 2025-04-03 13:49:18 -04:00
Kenji_64 d4cf44f8f0 Removed the old Three Segment Aspect 2025-04-03 18:54:29 +02:00
Kenji_64 a074ebbcce It has been du-dune: Implemented Dunsparce + Dudunsparce (2 & 3 Segment Form) 2025-04-03 18:54:00 +02:00
Landon Wills 987b8619a3 Specify side for riding state management, add multiplayer wing flap for charizard 2025-04-03 05:11:33 -04:00
Landon Wills 87632941e8 Fix issue with player not rotating on mount 2025-04-03 02:25:11 -04:00
queao 6578ed55e3 whoopsies 2025-04-03 16:12:39 +10:00
Landon Wills 041acab7ca Optimize change detection on riding sync 2025-04-03 02:06:23 -04:00
Landon Wills b3de7d1c1a Synchronize riding state to clients 2025-04-03 01:25:30 -04:00
Landon Wills afcb2dd77c Use render orientation instead of raw orientation for local players 2025-04-03 00:12:36 -04:00
Landon Wills a7bd6d2bf4 Update Garchomp, change translation in mounted player rendering 2025-04-02 23:54:22 -04:00
Landon Wills b096cb60a3 Use more precise orientation for posable model if player is local 2025-04-02 23:16:34 -04:00
Tyzillion f567ceadd8 Implemented Cosmetics for Gurdurr, Conkeldurr, Squirtle Line, Sneasler, Sandle line, Treecko line, Braixen, Delphox, and Dragonite.
Removed Shulker aspect and replaced it with cosmetic_item-shulker_shell.
Shulker shell Forretress is now a cosmetic rather than a special evo.
2025-04-02 18:03:11 -04:00
FrankTheFarmer 5de92f78c6 Changelog 👨‍🌾🔫🐲 2025-04-02 22:50:23 +10:00
FrankTheFarmer a2402f78e7 Added Sandaconda 🐍🐍🐍 2025-04-02 22:47:37 +10:00
FrankTheFarmer 1ad6d63137 Added Silicobra 🪱 2025-04-02 22:45:54 +10:00
FrankTheFarmer 39d417c651 Added Bronzong 👁🔔👁 2025-04-02 22:44:14 +10:00
FrankTheFarmer ce1bf9f4f2 Added Bronzor 🔷 2025-04-02 22:43:41 +10:00
FrankTheFarmer a6136906f8 Added Musharna 💤🐖 2025-04-02 22:42:44 +10:00
FrankTheFarmer 37a99b528e Added Munna 🐖 2025-04-02 22:40:46 +10:00
FrankTheFarmer 048b237302 Added Zebstrika ⚡🦓⚡ 2025-04-02 22:38:17 +10:00
FrankTheFarmer 131773f9c8 Added Blitzle ⚡🦓 2025-04-02 22:37:56 +10:00
FrankTheFarmer 22e55b7e77 Added Arboliva 🌵 2025-04-02 22:36:29 +10:00
FrankTheFarmer 6c288f9cc8 Added Dolliv 🫒🦵 2025-04-02 22:31:52 +10:00
FrankTheFarmer b5e86a9460 Added Smoliv 🫒 2025-04-02 22:30:53 +10:00
FrankTheFarmer f199e7c1c0 Added Froslass ✨👩‍🦳❄ 2025-04-02 22:29:05 +10:00
FrankTheFarmer 4161d96707 Added Glalie ⚪ 2025-04-02 22:27:35 +10:00
FrankTheFarmer 59927dd701 Added Snorunt 📐 2025-04-02 22:26:58 +10:00
FrankTheFarmer 220d8ddc0f Added Grumpig 🐖🔮 2025-04-02 22:25:53 +10:00
FrankTheFarmer 0dd143e67e Added Spoink 🔮🐷 2025-04-02 22:24:57 +10:00
JPAK 7f1c0c3d4c Fixed culling. It really was that easy xd 2025-04-02 07:23:26 -05:00
FrankTheFarmer d83eb62821 Added Garbodor 🤮 2025-04-02 22:22:52 +10:00
FrankTheFarmer a716fda023 Added Trubbish 🤢 2025-04-02 22:22:25 +10:00
FrankTheFarmer d14aad787c Added Orthworm 🪱♥❓🥺 2025-04-02 22:19:01 +10:00
FrankTheFarmer 2eb7b60dd1 Added Drampa 👴🐉🔥🏠 2025-04-02 22:11:41 +10:00
TeggyandWeblate bc4699e354 Translated using Weblate (Spanish)
Currently translated at 95.1% (6683 of 7021 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/es/
2025-04-02 11:09:46 +00:00
Landon Wills a4f0bf9d2f Fix issue with the world ocasionally playing hide and seek when rolling in first person 2025-04-02 01:57:40 -04:00
JacksonB f46c748e9f Add forgotten bird logic 2025-04-02 00:07:37 -05:00
Landon Wills 065479c58c Make rendering smooth for rolling players & entities 2025-04-02 00:16:05 -04:00
JacksonB eee3d46a2d Keep a render orientation that interpolates behind the last received orientation and damp the slerp by a static amount frame to frame. 2025-04-01 21:07:21 -05:00
Plastered_Crab c50b149e83 Add some notes to TickingSpawner to where we might want to alter rarity buckets if we added an effect for that 2025-04-01 16:19:53 -07:00
FrankTheFarmer d79ffc631b Merge branch 'main' into implement_pokemon 2025-04-02 08:41:27 +10:00
Plastered_Crab 63252f4d35 Swap placeholder sugar Seasoning Item with Golden Apple 2025-04-01 15:10:42 -07:00
Plastered_Crab 1c024f881e Swap placeholder sugar Seasoning Item with Golden Apple 2025-04-01 14:49:57 -07:00
Plastered_Crab 93f0337399 Got Seasoning-only Bait effects working 2025-04-01 14:44:33 -07:00
Hiroku d7b43fcbfc Merge branch 'spicy-molang' into 'main'
Added `pokemon` as an available Molang function for the `battleActor` functions

See merge request cable-mc/cobblemon!1577
2025-04-01 20:21:18 +00:00
Plastered_Crab 7e8fb07f55 Clean up doo doo commented out code 2025-04-01 12:13:53 -07:00
Plastered_Crab 7a8856c34c Fix Poke Bait fishing bait losing their Component data upon getting a bite 2025-04-01 12:12:19 -07:00
Landon Wills c82e011f73 Pull together riding branches, trying to fix render stuttering 2025-04-01 13:18:50 -04:00
Spicy bf1b996962 Added pokemon as an available Molang function for the battleActor functions 2025-04-01 09:12:16 -05:00
Guilherme Pereira 63d516953a fix cakes not loading additional data upon reentering the world 2025-04-01 10:33:14 -03:00
Landon Wills fc46cdcda0 Merge remote-tracking branch 'refs/remotes/origin/camera-changes' into test
# Conflicts:
#	common/src/main/java/com/cobblemon/mod/common/mixin/client/CameraMixin.java
#	common/src/main/kotlin/com/cobblemon/mod/common/client/render/player/MountedPlayerRenderer.kt
2025-04-01 09:24:11 -04:00
Landon Wills 4e7b029afb Merge remote-tracking branch 'refs/remotes/origin/multiplayer-roll-sync' into test 2025-04-01 09:22:19 -04:00
Landon Wills 5430f02770 Add much more context to pose provider, optimize velocity tracking, add sync to server 2025-04-01 09:20:51 -04:00
Landon Wills 6a51abe3ee Axe more of the old system, fix some issues with deserialization 2025-04-01 06:48:21 -04:00
Landon Wills 008652b442 Forgot a change 2025-04-01 06:32:11 -04:00
Landon Wills c1e088eb33 Hook new riding infrastructure up to serialization, axe the old controllers 2025-04-01 06:31:33 -04:00
Landon Wills 1669a2f428 Make all riding behaviour settings encodable 2025-04-01 05:44:18 -04:00
Landon Wills 2ba63f4641 Redirect PokemonEntity and mixins to new riding system 2025-04-01 05:29:17 -04:00
plastered_crab 07faf6600f Just some testing with some Seasoning-Only bait effects items (items that can't go on rod but can cook for bait effects) 2025-04-01 01:56:01 -07:00
Landon Wills 41b9e9001d Refactor riding system 2025-04-01 03:48:45 -04:00
JacksonB 679920b786 Rolling is now displayed on remote clients while riding. 2025-03-31 23:15:44 -05:00
Landon Wills f058d6e635 More work on controllers. Poses borked again 2025-03-31 20:46:11 -04:00
Plastered_Crab 08e79d71bf Added in code to trigger bites on a Lure Cake if it's effects are used to spawn something 2025-03-31 17:11:14 -07:00
Landon Wills f9377b7489 Some progress on data transfer for ride controllers (currently not functional) 2025-03-31 17:55:59 -04:00
TeggyandWeblate 9270119675 Translated using Weblate (Spanish)
Currently translated at 95.1% (6682 of 7021 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/es/
2025-03-31 15:23:52 +00:00
Polymeta e59b5094ad correctly warp world as holder inside spawnfilters
Signed-off-by: Polymeta <40173118+Polymeta@users.noreply.github.com>
2025-03-31 11:50:54 +01:00
JacksonB c8ec4e6f1f commit to not lose anything because paranoid the computer explodes 2025-03-31 00:20:21 -05:00
Josh a2fef9f1be Moved WearableItemModel functions out of HeldItemRenderer.kt 2025-03-30 21:24:13 -04:00
Josh 3d4df2c098 Fixed item rendering not falling back to the item locator if other locators are not present. 2025-03-30 21:11:05 -04:00
Josh 7557cab03d Fixed item visibility button not showing the right icon when opening summary or switching pokemon. 2025-03-30 20:55:28 -04:00
TeggyandWeblate 0058906022 Translated using Weblate (Spanish)
Currently translated at 95.1% (6678 of 7021 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/es/
2025-03-31 00:16:23 +00:00
Josh f1018b1da9 Simplified HeldItemRenderer to use only one render function that renders an Item on a PosableModel. And fixed the item lighting in the summary menu. 2025-03-30 20:03:07 -04:00
FrankTheFarmer 7cd1870f23 Merge branch 'main' into implement_pokemon 2025-03-31 07:42:53 +10:00
Landon Wills cbcc6abe40 Fix issue with poses not changing properly in multiplayer riding 2025-03-30 17:04:36 -04:00
Josh 5af4e3bddb Added placeholder models for wearable items and logic to register the models. 2025-03-30 02:03:44 -04:00
plastered_crab 6c836663f4 Cakes now get bites taken out of them when their influence gets used for spawning 2025-03-29 18:24:03 -07:00
Landon Wills 64c9d47b0f Fix multiplayer issue where pokemon other player's were riding would not rotate 2025-03-29 21:10:42 -04:00
Josh 1f519cae50 Fixed rotation of items rending in PokemonOnShoulderRenderer and ModelWidget 2025-03-29 20:01:04 -04:00
Landon Wills c0d2803f61 Fix multiplayer issues with clients not recognizing ridden pokemon on login 2025-03-29 15:55:34 -04:00
Landon Wills e249d5238f Fix issue with orientation not getting reset on ride dismount 2025-03-29 02:34:00 -04:00
Landon Wills e32e505e95 Fix issue with sprint not getting recognized on RunUpToJetFlightCompositeController 2025-03-29 02:14:40 -04:00
Landon 7642a84108 Merge branch 'ride-controller-server-crash-fix' into 'multiplayer-riding'
Ride controller server crash fix

See merge request cable-mc/cobblemon!1575
2025-03-29 04:58:25 +00:00
JacksonB b6e20d69cc fix to crouch but sprint during riding is still broken 2025-03-28 15:18:10 -05:00
JacksonB 9d04e20a30 Remove client only code causing server crash and replace with proper code. 2025-03-28 14:51:33 -05:00
Landon Wills d2624813f7 Merge branch 'refs/heads/bug-fixes' into multiplayer-riding 2025-03-28 13:36:22 -04:00
Landon Wills a2789e70ed Use readString in readExpression to be a bit more clear on it's function 2025-03-28 13:35:05 -04:00
Guilherme Pereira eeae26492e Merge branch 'we_are_cooking_now' into candle-cake 2025-03-28 07:25:47 -03:00
Guilherme Pereira 9e67a82816 Merge branch 'we_are_cooking_now' into cooking-pot-jei 2025-03-28 06:56:21 -03:00
Guilherme Pereira c09295231c remove dead code and print statements 2025-03-28 06:19:03 -03:00
Guilherme Pereira 6c7d61c9f2 prevent cooking pot cooked items stacking above their stack limit 2025-03-28 06:12:55 -03:00
Guilherme Pereira 01f8a5c6d7 fix some cooking pot crashes 2025-03-28 06:12:15 -03:00
Landon Wills f6f607904e Merge branch 'refs/heads/bug-fixes' into multiplayer-riding 2025-03-28 01:53:19 -04:00
Landon Wills 22ea0296c0 Fix issues with riding controller packet decoding 2025-03-28 01:52:03 -04:00
Landon Wills 24ae2f5324 Fix issue with registering species on servers 2025-03-28 01:51:38 -04:00
Landon Wills 9284497cec Refactor Rollable interface, fix issue with mixins crossing sides, causing server to fail to load 2025-03-28 00:21:26 -04:00
Landon Wills 36cb12952a Move more functions out of Rollable to mouse handling 2025-03-27 21:55:29 -04:00
Landon Wills 2700dc7f39 Refactor function to get angular velocity out of Rollable 2025-03-27 21:23:12 -04:00
KyoandWeblate 14d2a76211 Translated using Weblate (Vietnamese)
Currently translated at 100.0% (7021 of 7021 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/vi/
2025-03-27 12:41:50 +00:00
Watuneni iteiteandWeblate 7669000962 Translated using Weblate (Japanese)
Currently translated at 76.3% (5358 of 7021 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/ja/
2025-03-27 12:41:46 +00:00
Sterrezo 716d1b848e Fixed and renamed cries for Galarian Ponyta, Galarian Rapidash and Alolan Raichu 2025-03-26 16:19:26 +01:00
Sterrezo 4878fc517d Updated and cleaned up the cry checker script 2025-03-26 16:00:57 +01:00
Sterrezo 4d9d543110 STOP BREAKING THE SPREADSHEET
fixed script
2025-03-26 14:26:15 +01:00
Polymeta c9d27d46b6 license header
Signed-off-by: Polymeta <40173118+Polymeta@users.noreply.github.com>
2025-03-26 11:39:18 +00:00
amo f11f88c71a npc hide logic 2025-03-26 02:07:10 +00:00
FrankTheFarmer 718a9b922b Merge branch 'main' into implement_pokemon 2025-03-26 08:28:53 +10:00
Polymeta b68756378c Merge branch 'Box-count-command' into 'main'
Added /boxcount

See merge request cable-mc/cobblemon!1565
2025-03-25 17:01:22 +00:00
Polymeta 1ff1880951 Merge branch 'main' into 'Box-count-command'
# Conflicts:
#   common/src/main/kotlin/com/cobblemon/mod/common/api/permission/CobblemonPermissions.kt
2025-03-25 16:59:25 +00:00
Polymeta fea2d32de8 Merge branch 'spectate-command' into 'main'
Added a spectate battle command.

See merge request cable-mc/cobblemon!1264
2025-03-25 16:56:49 +00:00
Conan e3e6d4452c # 2025-03-25 14:12:49 +01:00
Conan f687e8e658 Merge branch 'main' of https://gitlab.com/cable-mc/cobblemon into spectate-command
# Conflicts:
#	common/src/main/kotlin/com/cobblemon/mod/common/CobblemonCommands.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/api/permission/CobblemonPermissions.kt
#	common/src/main/resources/assets/cobblemon/lang/en_us.json
2025-03-25 14:07:49 +01:00
GenotypeXD-Dev e2a152aeb3 Model Fixes didnt push 2025-03-24 19:34:11 -06:00
GenotypeXD-Dev 3e21226b27 Implemented Hawlucha + fixed z fighting on Noibat and scaled down to 0.6 2025-03-24 19:30:16 -06:00
queao c46c5b806c IT'S TIIIIIIIIIIME (implemented noibat and noivern - implementation work done by genotype) 2025-03-24 18:49:07 +10:00
FrankTheFarmer 3c37d93046 Merge branch 'main' into implement_pokemon 2025-03-24 16:40:53 +10:00
TeggyandWeblate 8912911800 Translated using Weblate (Spanish)
Currently translated at 94.3% (6621 of 7021 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/es/
2025-03-22 01:16:22 +00:00
Paul 660be08eea Overhauled cooking and fishing baits, added ride boosts, added aprijuice stat handling, probably added lots of bugs 2025-03-21 14:28:22 +10:00
阿鱼andWeblate 62ecfaf54a Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (7021 of 7021 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/zh_Hans/
2025-03-20 23:47:02 +00:00
TeggyandWeblate 6684177236 Translated using Weblate (Spanish)
Currently translated at 94.2% (6615 of 7021 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/es/
2025-03-20 23:47:00 +00:00
Watuneni iteiteandWeblate deca5cf55b Translated using Weblate (Japanese)
Currently translated at 76.1% (5350 of 7021 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/ja/
2025-03-20 23:46:59 +00:00
ShiroFenixlm a6d17659f8 Added removeListOfBoxes to PCStore 2025-03-19 23:31:43 -04:00
ShiroFenixlm 997a6de23b Remove and Set now only delete empty boxes unless forced 2025-03-19 21:52:08 -04:00
ShiroFenixlm c948b6d885 Added force remove button 2025-03-18 19:40:53 -04:00
Paul 769a9ac845 Merge remote-tracking branch 'origin/we_are_cooking_now' into we_are_cooking_now 2025-03-18 15:11:46 +10:00
FrankTheFarmer 7b2790de50 Changelog setup for 1.7 implementation stuff 2025-03-18 09:20:30 +10:00
FrankTheFarmer 7f2bb84c85 Merge branch 'main' into implement_pokemon 2025-03-18 09:12:06 +10:00
阿鱼andWeblate 0f75797759 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (7021 of 7021 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/zh_Hans/
2025-03-17 21:03:49 +00:00
ShiroFenixlm 5508980384 Final Cleanup, i hope 2025-03-17 15:24:02 -04:00
ShiroFenixlm e39dee01e5 Cleanup 2025-03-17 15:16:06 -04:00
ShiroFenixlm a81412e176 Merge remote-tracking branch 'origin/Box-count-command' into Box-count-command
# Conflicts:
#	common/src/main/kotlin/com/cobblemon/mod/common/command/ChangePCBoxesCommand.kt
2025-03-17 15:15:01 -04:00
ShiroFenixlm 09f9dd91aa Fixed some issues and added error handling when removing too many boxes 2025-03-17 15:08:07 -04:00
ShiroFenixlm 2efc3c72ac Fixed some issues and added error handling when removing too many boxes 2025-03-17 15:02:57 -04:00
ShiroFenix a92fb03093 Updated command logic to improve legibility 2025-03-17 12:56:15 -04:00
ShiroFenix ad5847983f Updated command logic to improve legibility 2025-03-17 12:55:59 -04:00
WhiteFenix19 bb25300513 Updated command logic to improve legibility 2025-03-17 12:32:46 -04:00
WhiteFenix19 de33804eb4 Updated command logic to improve legibility 2025-03-17 12:19:47 -04:00
WhiteFenix19 de042f71dd Updated command logic to improve legibility 2025-03-17 12:18:28 -04:00
WhiteFenix19 5a1e85bbf4 Added /boxcount command 2025-03-17 00:47:00 -04:00
ShiroFenix 3489e0df74 Revert "Added /boxcount"
This reverts commit afe8eec343
2025-03-17 03:59:02 +00:00
ShiroFenix afe8eec343 Added /boxcount 2025-03-17 03:43:32 +00:00
FrankTheFarmer 331e1371d4 Illegal imports of Dragonite and Gyarados models with locators for testing 2025-03-16 09:42:56 +10:00
FrankTheFarmer bdd57ba1a4 Merge branch 'main' into implement_pokemon 2025-03-16 08:53:37 +10:00
Alexis SalgueiroandWeblate c194aefce5 Translated using Weblate (French)
Currently translated at 91.5% (6425 of 7021 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/fr/
2025-03-15 14:17:58 +00:00
Aiser(CCHusky)andWeblate f4798c8783 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (7021 of 7021 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/zh_Hans/
2025-03-15 14:17:57 +00:00
chronicenandWeblate 2178a5f10e Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (7021 of 7021 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/zh_Hans/
2025-03-15 14:17:57 +00:00
Gertimoshka f5e3945cf6 Spawning Influence Prospector can now have 2 methods of providing data 2025-03-15 14:00:03 +02:00
BuildTools bb121cbee7 Made Lure Cakes use Poi System to allow better range of effect 2025-03-15 12:40:39 +02:00
Paul cee9adc782 Merge remote-tracking branch 'origin/main' into we_are_cooking_now
# Conflicts:
#	common/src/main/kotlin/com/cobblemon/mod/common/CobblemonNetwork.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/client/particle/ParticleStorm.kt
2025-03-15 13:37:59 +10:00
TeggyandWeblate bc145a56d5 Translated using Weblate (Spanish)
Currently translated at 93.6% (6575 of 7021 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/es/
2025-03-14 17:00:49 +00:00
FrankTheFarmer 670e7e9ca1 Merge branch 'main' into implement_pokemon 2025-03-13 13:55:26 +10:00
Nico MerenqandWeblate 476ef3bb2f Translated using Weblate (Russian)
Currently translated at 73.9% (5189 of 7021 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/ru/
2025-03-12 13:19:09 +00:00
Alexis SalgueiroandWeblate 460050289b Translated using Weblate (French)
Currently translated at 90.7% (6373 of 7021 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/fr/
2025-03-10 15:04:25 +00:00
Paul 0a2e9f6530 Removed some unused stuff 2025-03-10 17:37:17 +10:00
Nico MerenqandWeblate 01fd4dcc68 Translated using Weblate (Russian)
Currently translated at 73.8% (5182 of 7021 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/ru/
2025-03-09 18:06:58 +00:00
Nico MerenqandWeblate 0392eb3b7e Translated using Weblate (Russian)
Currently translated at 73.6% (5172 of 7021 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/ru/
2025-03-09 15:29:58 +00:00
Paul 038a21556e Merge remote-tracking branch 'origin/main' into we_are_cooking_now 2025-03-09 21:01:24 +10:00
阿鱼andWeblate 493f423a2f Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (7021 of 7021 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/zh_Hans/
2025-03-09 10:54:04 +00:00
阿鱼andWeblate cbcfa1bbfb Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (7021 of 7021 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/zh_Hans/
2025-03-09 10:45:17 +00:00
Nico MerenqandWeblate 17a3ff15db Translated using Weblate (Russian)
Currently translated at 73.6% (5171 of 7021 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/ru/
2025-03-09 10:30:06 +00:00
阿鱼andWeblate 9c14cccc98 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 99.9% (7017 of 7021 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/zh_Hans/
2025-03-09 10:30:05 +00:00
Paul 57539775e0 A lot of bait and cake cleanup, implemented world sliced spawning influences and made the lure cake block apply them 2025-03-09 20:08:44 +10:00
Paul eb71a20a19 Merge remote-tracking branch 'origin/main' into we_are_cooking_now
# Conflicts:
#	common/src/main/resources/cobblemon-common.accesswidener
2025-03-09 17:56:20 +10:00
Weblate 850cfbe755 Update translation files
Updated by "Remove blank strings" add-on in Weblate.

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/
2025-03-08 22:51:12 +00:00
TeggyandWeblate 28afa6a9e8 Translated using Weblate (Spanish)
Currently translated at 93.1% (6538 of 7021 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/es/
2025-03-08 22:51:08 +00:00
阿鱼andWeblate 7a76d95ce7 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 98.7% (6936 of 7021 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/zh_Hans/
2025-03-08 22:51:07 +00:00
TeggyandWeblate 54707d0618 Translated using Weblate (Spanish)
Currently translated at 92.1% (6470 of 7021 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/es/
2025-03-08 15:08:19 +00:00
Aiser(CCHusky)andWeblate 307c400e28 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 98.6% (6929 of 7021 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/zh_Hans/
2025-03-08 15:08:18 +00:00
阿鱼andWeblate 5c9b3ab25d Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 98.6% (6929 of 7021 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/zh_Hans/
2025-03-08 15:08:18 +00:00
阿鱼andWeblate 532e991fb2 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 98.1% (6890 of 7021 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/zh_Hans/
2025-03-08 11:31:35 +00:00
Nico MerenqandWeblate b1bf817329 Translated using Weblate (Russian)
Currently translated at 73.6% (5171 of 7021 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/ru/
2025-03-08 11:31:34 +00:00
TeggyandWeblate c091f90487 Translated using Weblate (Spanish)
Currently translated at 91.7% (6445 of 7021 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/es/
2025-03-08 08:23:13 +00:00
阿鱼andWeblate a49d4715ff Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 97.0% (6816 of 7021 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/zh_Hans/
2025-03-08 08:23:12 +00:00
阿鱼andWeblate 652b15532e Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 96.9% (6807 of 7021 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/zh_Hans/
2025-03-07 04:18:30 +00:00
TeggyandWeblate e4064897b0 Translated using Weblate (Spanish)
Currently translated at 91.5% (6430 of 7021 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/es/
2025-03-07 04:18:29 +00:00
阿鱼andWeblate f9ca8222da Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 96.7% (6793 of 7021 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/zh_Hans/
2025-03-06 12:30:15 +00:00
FrankTheFarmer 3ae349aea5 Merge branch 'main' into implement_pokemon 2025-03-06 18:28:14 +10:00
JazzMcNade 91864b13d0 Moved GetSendOutPosition into ActiveBattlePokemon.kt 2025-03-06 01:45:58 -06:00
阿鱼andWeblate 67480a945f Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 95.5% (6708 of 7021 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/zh_Hans/
2025-03-06 06:42:04 +00:00
Alexis SalgueiroandWeblate e6e811e6e6 Translated using Weblate (French)
Currently translated at 90.0% (6320 of 7021 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/fr/
2025-03-06 06:41:58 +00:00
Watuneni iteiteandWeblate 4635c531b9 Translated using Weblate (Japanese)
Currently translated at 73.7% (5178 of 7021 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/ja/
2025-03-06 06:41:56 +00:00
Watuneni iteiteandWeblate 3bdfac9a46 Translated using Weblate (Japanese)
Currently translated at 71.7% (5039 of 7021 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/ja/
2025-03-05 13:53:19 +00:00
chronicenandWeblate 2b7a71cb1c Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 91.4% (6424 of 7021 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/zh_Hans/
2025-03-05 13:53:19 +00:00
阿鱼andWeblate d47a500a0e Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 91.4% (6424 of 7021 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/zh_Hans/
2025-03-05 13:53:19 +00:00
FrankTheFarmer 13650f98f9 Merge remote-tracking branch 'origin/implement_pokemon' into implement_pokemon 2025-03-05 14:23:08 +10:00
FrankTheFarmer d3379557fd 2 more Gen 5 monkeys jumping on the bed 2025-03-05 14:22:28 +10:00
FrankTheFarmer 143c2683fe Added placeholder animations to Pansage and Simisage 2025-03-05 14:21:54 +10:00
FrankTheFarmer 72d64d36e5 Changed panpour scale and hitbox size to match that of the other monkeys 2025-03-05 14:21:17 +10:00
Wi2tert c0b52c38e3 "implemented": Panpour、Simipour 💧🐒 2025-03-05 12:11:22 +08:00
JazzMcNade adc8e9921a Updated Changelog 2025-03-04 21:54:23 -06:00
JazzMcNade 5e5473acae Muted timing console logging 2025-03-04 21:50:28 -06:00
FrankTheFarmer 12a0ee309e Merge branch 'main' into implement_pokemon 2025-03-05 08:01:14 +10:00
阿鱼andWeblate 33e6dbb4c1 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 87.4% (6143 of 7021 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/zh_Hans/
2025-03-04 15:50:25 +00:00
RedGenesectNinja 824e37effd Implemented Pansage and Simisage 2025-03-03 23:12:27 -06:00
JazzMcNade 3509944f1a Comment, fixed indentation 2025-03-03 20:53:42 -06:00
JazzMcNade 8a5489f805 Merge branch 'main' into SaferSendouts 2025-03-03 20:44:26 -06:00
JPAK 922ee95fd2 Camera changes for riding. Need to find a better system for being "unlocked" (in third person only) to make the animations feel better. 2025-03-03 16:22:13 -06:00
Alexis SalgueiroandWeblate 482c57dd2e Translated using Weblate (French)
Currently translated at 89.1% (6259 of 7021 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/fr/
2025-03-03 19:14:47 +00:00
Alexis SalgueiroandWeblate 503c62d78d Translated using Weblate (French)
Currently translated at 87.8% (6169 of 7021 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/fr/
2025-03-03 09:30:43 +00:00
Seonho LeeandWeblate 708d0ab6d3 Translated using Weblate (Korean)
Currently translated at 70.0% (4915 of 7021 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/ko/
2025-03-03 09:30:42 +00:00
TeggyandWeblate 19727542bd Translated using Weblate (Spanish)
Currently translated at 91.4% (6424 of 7021 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/es/
2025-02-28 22:02:07 +00:00
Alexis SalgueiroandWeblate c4e6714a95 Translated using Weblate (French)
Currently translated at 87.6% (6153 of 7021 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/fr/
2025-02-28 02:41:41 +00:00
TeggyandWeblate c116e612c6 Translated using Weblate (Spanish)
Currently translated at 90.4% (6354 of 7021 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/es/
2025-02-28 02:41:41 +00:00
Fiestorra ISVandWeblate 215a055ce6 Translated using Weblate (Spanish)
Currently translated at 90.4% (6354 of 7021 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/es/
2025-02-28 02:41:40 +00:00
Fiestorra ISVandWeblate 9c0b6b8d26 Translated using Weblate (Spanish)
Currently translated at 87.3% (6134 of 7021 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/es/
2025-02-25 22:27:22 +00:00
Fiestorra ISVandWeblate 5c4462ee94 Translated using Weblate (Spanish)
Currently translated at 100.0% (6391 of 6391 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/es/
2025-02-25 18:48:01 +00:00
TeggyandWeblate 04edd6f9e2 Translated using Weblate (Spanish)
Currently translated at 100.0% (6391 of 6391 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/es/
2025-02-25 18:48:01 +00:00
Polymeta 52821cc051 Merge branch 'main' into lang-updates 2025-02-25 18:38:33 +00:00
Watuneni iteiteandWeblate 0029deb029 Translated using Weblate (Japanese)
Currently translated at 81.6% (5218 of 6391 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/ja/
2025-02-23 23:03:25 +00:00
TeggyandWeblate c6360e2a36 Translated using Weblate (Spanish)
Currently translated at 100.0% (6391 of 6391 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/es/
2025-02-23 23:03:24 +00:00
Fiestorra ISVandWeblate 2e77c647b6 Translated using Weblate (Spanish)
Currently translated at 100.0% (6391 of 6391 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/es/
2025-02-23 23:03:22 +00:00
Guilherme Pereira ee28cf554a add cooking progress sprite to campfire pot jei 2025-02-23 08:18:34 -03:00
Polymeta 30dcb9a4da initial mixin sorting
Signed-off-by: Polymeta <40173118+Polymeta@users.noreply.github.com>
2025-02-21 23:15:14 +00:00
Polymeta ffc9fdfa6d Merge branch 'refs/heads/main' into we_are_cooking_now
# Conflicts:
#	common/src/main/kotlin/com/cobblemon/mod/common/CobblemonNetwork.kt
#	common/src/main/resources/cobblemon-common.accesswidener
#	common/src/main/resources/mixins.cobblemon-common.json
2025-02-21 23:02:08 +00:00
Watuneni iteiteandWeblate c3d3b19788 Translated using Weblate (Japanese)
Currently translated at 81.3% (5200 of 6391 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/ja/
2025-02-21 08:11:08 +00:00
Fiestorra ISVandWeblate 219cd61beb Translated using Weblate (Spanish)
Currently translated at 100.0% (6391 of 6391 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/es/
2025-02-21 08:11:07 +00:00
TeggyandWeblate 207e5a9142 Translated using Weblate (Spanish)
Currently translated at 100.0% (6391 of 6391 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/es/
2025-02-19 13:03:51 +00:00
apion 4f86c6f322 Flashback no longer crashes the game 2025-02-18 20:02:36 -05:00
Watuneni iteiteandWeblate c721fb534d Translated using Weblate (Japanese)
Currently translated at 81.2% (5191 of 6391 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/ja/
2025-02-18 15:00:29 +00:00
iván SeguraandWeblate dba2622fd7 Translated using Weblate (Spanish)
Currently translated at 100.0% (6391 of 6391 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/es/
2025-02-18 15:00:28 +00:00
Guilherme Pereira 33c8ecd908 add seasonings to cooking pot jei integration 2025-02-18 01:51:49 -03:00
Guilherme Pereira 93367fb0e8 add jei integration to cooking pot 2025-02-17 23:18:06 -03:00
Guilherme Pereira 694f74be13 add candle cake 2025-02-17 17:11:49 -03:00
JazzMcNade 3b7d56ff45 Merge branch 'main' into SaferSendouts 2025-02-16 20:53:08 -06:00
Guilherme Pereira 79d097b17c add support for diferent cake variants 2025-02-16 19:14:50 -03:00
Guilherme Pereira 7ef30653bb refactor cake rendering 2025-02-16 17:14:35 -03:00
Guilherme Pereira 1ecb13f7fc Merge branch 'main' into we_are_cooking_now 2025-02-16 13:14:27 -03:00
iván SeguraandWeblate da68675133 Translated using Weblate (Spanish)
Currently translated at 100.0% (6391 of 6391 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/es/
2025-02-16 12:57:27 +00:00
Kenji_64 975cdf050f Fixed Charcadet's cry sound event not being there and head pivot 2025-02-15 15:34:34 +01:00
iván SeguraandWeblate 9aea5a7daf Translated using Weblate (Spanish)
Currently translated at 100.0% (6391 of 6391 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/es/
2025-02-15 13:26:10 +00:00
Test d19878edf6 refactor pot 2025-02-14 16:00:56 -05:00
Test 4f98d1e054 Merge branch 'we_are_cooking_now' of https://gitlab.com/cable-mc/cobblemon into we_are_cooking_now
# Conflicts:
#	common/src/main/kotlin/com/cobblemon/mod/common/CobblemonItems.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/api/cooking/CookingComponentColorHelper.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/client/render/block/CampfireBlockEntityRenderer.kt
2025-02-13 18:54:15 -05:00
Test 7b8e07aef3 refactor pot 2025-02-13 18:44:11 -05:00
Gustavo PuerariandWeblate 10402575fb Translated using Weblate (Portuguese (Brazil))
Currently translated at 68.3% (4369 of 6391 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/pt_BR/
2025-02-13 23:43:36 +00:00
João Pedro Silva AfonsoandWeblate 0f82ade57c Translated using Weblate (Portuguese (Brazil))
Currently translated at 68.3% (4369 of 6391 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/pt_BR/
2025-02-13 23:43:35 +00:00
Gustavo PuerariandWeblate 450b041118 Translated using Weblate (Portuguese (Brazil))
Currently translated at 65.1% (4166 of 6391 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/pt_BR/
2025-02-11 21:12:32 +00:00
Weblate 770c349ac4 Update translation files
Updated by "Remove blank strings" add-on in Weblate.

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/
2025-02-10 00:41:50 +00:00
Gustavo PuerariandWeblate f76648b6f2 Translated using Weblate (Portuguese (Brazil))
Currently translated at 59.8% (3826 of 6391 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/pt_BR/
2025-02-10 00:41:46 +00:00
Gustavo PuerariandWeblate 56e60667db Translated using Weblate (Portuguese (Brazil))
Currently translated at 51.5% (3297 of 6391 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/pt_BR/
2025-02-07 00:29:47 +00:00
Guilherme Pereira 1442bf5c34 fix merge 2025-02-06 03:47:13 -03:00
Guilherme Pereira 2ac37f6c4d Merge branch 'main' into we_are_cooking_now 2025-02-06 03:46:51 -03:00
Guilherme Pereira 9795dce227 remove campfire pot trap 2025-02-06 03:34:02 -03:00
Gustavo PuerariandWeblate c4a60951c5 Translated using Weblate (Portuguese (Brazil))
Currently translated at 49.7% (3178 of 6391 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/pt_BR/
2025-02-05 07:22:58 +00:00
KyoandWeblate 814eee8125 Translated using Weblate (Vietnamese)
Currently translated at 100.0% (6391 of 6391 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/vi/
2025-02-03 09:44:44 +00:00
Gustavo PuerariandWeblate 2a9ff3bfbd Translated using Weblate (Portuguese (Brazil))
Currently translated at 47.9% (3064 of 6391 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/pt_BR/
2025-02-03 09:44:43 +00:00
Konoha 8fe2042127 Merge Basculin game evolutions 2025-02-02 08:17:05 -05:00
Konoha 538ad883ab Correct Spewpa evo tag reference in evolution to tag format 2025-02-02 08:02:49 -05:00
Konoha 136cb86492 Correct the consumption of held items on non-applicable item evolutions 2025-02-01 08:22:12 -05:00
Konoha e4eb1251d1 Fix Goomy & Bergmite branch evolutions, branching stone anticondition conflict. 2025-02-01 07:51:39 -05:00
Weblate 83350cb0db Update translation files
Updated by "Remove blank strings" add-on in Weblate.

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/
2025-01-31 22:57:44 +00:00
Patch Notes GuyandWeblate 778761dbee Translated using Weblate (Vietnamese)
Currently translated at 99.1% (6335 of 6391 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/vi/
2025-01-31 22:57:39 +00:00
Gustavo PuerariandWeblate e9881b748a Translated using Weblate (Portuguese (Brazil))
Currently translated at 46.4% (2971 of 6391 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/pt_BR/
2025-01-31 22:57:25 +00:00
Guilherme Pereira d9cf802a9e fix saccharine trees natural world generation 2025-01-31 11:27:59 -03:00
Weblate dabaeefa23 Update translation files
Updated by "Remove blank strings" add-on in Weblate.

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/
2025-01-31 09:41:51 +00:00
Patch Notes GuyandWeblate 0e0bec2712 Added translation using Weblate (Vietnamese) 2025-01-31 09:41:47 +00:00
Gustavo PuerariandWeblate 48fe160334 Translated using Weblate (Portuguese (Brazil))
Currently translated at 45.1% (2887 of 6391 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/pt_BR/
2025-01-31 03:10:48 +00:00
Valerie Rice 1bc83d9045 poison frog man (only the little one) 2025-01-28 16:22:21 +10:00
Gustavo PuerariandWeblate 7d599e12d0 Translated using Weblate (Portuguese (Brazil))
Currently translated at 42.7% (2731 of 6391 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/pt_BR/
2025-01-27 23:30:11 +00:00
Konoha 98775ffc1e Merge branch 'main' into Dex-Species-Forms
# Conflicts:
#	common/src/main/resources/assets/cobblemon/lang/en_us.json
2025-01-27 09:26:48 -05:00
Guilherme Pereira 3fbf2595cc add wool particles to cake breaking 2025-01-26 13:58:57 -03:00
Guilherme Pereira 6665285253 refactor cakes 2025-01-25 19:06:11 -03:00
Guilherme Pereira 61ae29b745 add candied apple, fried rice and potato mochi 2025-01-21 18:29:15 -03:00
Guilherme Pereira a17bf5eeeb update licenses 2025-01-21 17:42:03 -03:00
Guilherme Pereira c71d91a46d add mochis 2025-01-21 17:40:44 -03:00
Konoha bbeb3d45f0 Merge branch 'implement_pokemon' into Dex-Species-Forms 2025-01-21 11:37:28 -05:00
Guilherme Pereira c86103fd31 add player edible cake 2025-01-20 18:49:18 -03:00
Plastered_Crab 5190bbe723 Prep for adding new cooking recipe items 2025-01-18 22:08:16 -08:00
Plastered_Crab 3663ce2555 Merge remote-tracking branch 'origin/we_are_cooking_now' into we_are_cooking_now 2025-01-18 15:00:46 -08:00
Plastered_Crab b5fc52d9b1 Merge branch 'main' into we_are_cooking_now
# Conflicts:
#	common/src/main/kotlin/com/cobblemon/mod/common/api/tags/CobblemonBlockTags.kt
#	common/src/main/resources/data/cobblemon/recipe/cooking_pot/whipped_dream_from_cooking_pot.json
#	common/src/main/resources/data/minecraft/tags/block/logs.json
#	common/src/main/resources/data/minecraft/tags/item/logs.json
#	common/src/main/resources/data/minecraft/tags/item/logs_that_burn.json
2025-01-18 14:59:52 -08:00
Konoha 8fd854f7f7 Merge branch 'main' into Dex-Species-Forms 2025-01-18 16:48:07 -05:00
Konoha f449cf27c5 Merge branch 'implement_pokemon' into Dex-Species-Forms 2025-01-18 10:59:31 -05:00
Guilherme Pereira ca79b70815 add shapes to lure cakes 2025-01-17 13:05:37 -03:00
Guilherme Pereira 898c956f17 add rendering for the inner part of the cake 2025-01-16 17:01:37 -03:00
Guilherme Pereira 2ce48c9dff add custom lure cake color based on seasonings 2025-01-16 10:36:33 -03:00
Guilherme Pereira f64ec12a6a update licenses 2025-01-15 19:55:56 -03:00
Guilherme Pereira 474d3f3b55 add campfire pot bubbles color 2025-01-15 19:54:26 -03:00
Guilherme Pereira c87e6a391d refactor cooking pot renderer 2025-01-15 18:34:43 -03:00
Guilherme Pereira 192fd4dba7 make campfire pot bubbles disapear on lid close 2025-01-15 17:22:10 -03:00
plastered_crab c26786c644 Put water back to how it was 2025-01-14 21:19:22 -08:00
Plastered_Crab ebb0277d80 Merge remote-tracking branch 'origin/we_are_cooking_now' into we_are_cooking_now
# Conflicts:
#	common/src/main/kotlin/com/cobblemon/mod/common/client/render/block/CampfireBlockEntityRenderer.kt
2025-01-14 17:20:34 -08:00
Plastered_Crab 2a73efa479 Create custom render type to allow Cooking Pot water pane to show particles through it (wip) 2025-01-14 17:19:53 -08:00
Guilherme Pereira 6e68d22d4a update campfire pot models (again) 2025-01-14 20:39:49 -03:00
Guilherme Pereira dee08e6572 fix cooking pot rotation 2025-01-14 18:38:34 -03:00
Guilherme Pereira 2383686e42 update campfire pot models 2025-01-14 17:54:16 -03:00
Guilherme Pereira b8de9c415e Merge branch 'we_are_cooking_now' of gitlab.com:cable-mc/cobblemon into we_are_cooking_now 2025-01-14 16:59:09 -03:00
Guilherme Pereira f0269a3638 fix cooking pot items not being properly synched with the client 2025-01-14 16:58:54 -03:00
Plastered_Crab dbbbd309dc Added TransparentColorMixer method 2025-01-14 11:06:07 -08:00
plastered_crab b7a905ad79 Remove old bubbles 2025-01-14 06:59:23 -08:00
plastered_crab 60c8049459 More water bubble changes for cooking pot 2025-01-14 06:13:50 -08:00
plastered_crab 8c395b6fee Reduce and raise the particles for bubbling water in cooking pot 2025-01-13 22:21:14 -08:00
plastered_crab e9935a41e3 Start to add particles for bubbling water in cooking pot 2025-01-13 21:45:14 -08:00
Guilherme Pereira f0ecd4d50d add seasoning color to cooking pot water 2025-01-13 23:30:07 -03:00
Guilherme Pereira c0661022ab i hate bubbles 2025-01-13 21:50:30 -03:00
Guilherme Pereira e7305a3dfb improve seasonings spin on the cooking pot 2025-01-13 20:24:41 -03:00
Guilherme Pereira 86f52f176a make cooking pot seasonings spin 2025-01-13 20:01:25 -03:00
Guilherme Pereira beb9796e75 add water liquid to open cooking pot 2025-01-13 19:20:20 -03:00
Guilherme Pereira 6bb55adebc add campfire pot open/close variants 2025-01-13 13:41:37 -03:00
Guilherme Pereira 011bc85d18 Merge branch 'main' into we_are_cooking_now 2025-01-12 19:44:19 -03:00
Guilherme Pereira fad75c498b make cooking pot drop items on remove 2025-01-10 14:22:00 -03:00
Guilherme Pereira 915c69b443 improve cooking pot sounds 2025-01-10 11:06:49 -03:00
Guilherme Pereira 05b574543c add more constants to cooking pot 2025-01-10 10:30:01 -03:00
Guilherme Pereira 5198b2a709 render preview item on cooking pot 2025-01-10 09:35:14 -03:00
Guilherme Pereira 509973a027 add button to open/close the cooking pot lid 2025-01-10 07:58:58 -03:00
Guilherme Pereira 0253475f50 make cooking pot work similar to a furnace 2025-01-09 14:00:25 -03:00
Guilherme Pereira 6961c92c8d fix container data of cooking pot 2025-01-08 17:41:43 -03:00
Plastered_Crab 906d7b361d Lure Cakes now show their Bait Effects on their tooltip 2025-01-07 15:45:32 -08:00
Plastered_Crab 54121199b6 Merge remote-tracking branch 'origin/we_are_cooking_now' into we_are_cooking_now 2025-01-07 15:29:39 -08:00
Plastered_Crab 78b3e0a1aa Lure Cakes now are grey (colors coming later) and get eaten in bits as pokemon spawn 2025-01-07 15:29:17 -08:00
Guilherme Pereira aa45795944 add cooking pot sounds 2025-01-07 19:55:57 -03:00
Guilherme Pereira 353209c72c Merge branch 'we_are_cooking_now' of gitlab.com:cable-mc/cobblemon into we_are_cooking_now 2025-01-07 18:28:39 -03:00
Guilherme Pereira d07eaefdd4 lil cooking pot refactoring 2025-01-07 18:28:21 -03:00
Sterrezo 2ead9f6f02 Added campfire pot sounds 2025-01-07 21:58:05 +01:00
Plastered_Crab 472a349709 Merge remote-tracking branch 'origin/we_are_cooking_now' into we_are_cooking_now 2025-01-07 12:40:06 -08:00
Plastered_Crab 9043520364 Lure Cakes now store CookingComponent data, render, and can use BaitEffects 2025-01-07 12:39:41 -08:00
Guilherme Pereira 88ea77e2f3 ad quality tooltip to aprijuices 2025-01-07 15:56:49 -03:00
Guilherme Pereira a609e2d561 add separate aprijuice tooltip generator 2025-01-07 15:28:52 -03:00
Guilherme Pereira 6f1c791df4 add shift click functionality to cooking pot 2025-01-07 08:47:53 -03:00
plastered_crab dc41e7b50f Lure cakes work now with new (maybe temporary) spawn context "bait" 2025-01-06 23:00:33 -08:00
Plastered_Crab 1b22da8bd9 Merge remote-tracking branch 'origin/we_are_cooking_now' into we_are_cooking_now 2025-01-06 17:27:28 -08:00
Plastered_Crab 773eb9e1c3 So close to having Lure Cakes spawning pokemon 2025-01-06 17:27:07 -08:00
Guilherme Pereira 87deea9748 make cooking pot items persistent 2025-01-06 21:13:47 -03:00
Guilherme Pereira 556636f41e Merge branch 'we_are_cooking_now' of gitlab.com:cable-mc/cobblemon into we_are_cooking_now 2025-01-06 20:48:27 -03:00
Guilherme Pereira daab3dd3dd fix bait vanishing 2025-01-06 20:48:17 -03:00
Plastered_Crab 5535390298 Lure Cakes are real!! 2025-01-06 15:13:19 -08:00
Guilherme Pereira f54eaf3101 make baits update sprite and tooltip while crafting on the cooking pot 2025-01-06 19:18:57 -03:00
Guilherme Pereira 1d86ace385 no more food waste 2025-01-06 18:32:49 -03:00
Guilherme Pereira 4a02a0a67d add leaf color based on quality to aprijuices 2025-01-06 17:33:14 -03:00
Guilherme Pereira 7f193c11e1 add flavor tooltip to aprijuices 2025-01-06 16:26:44 -03:00
plastered_crab 9f90a08276 Added preliminary foundation for Lure/Bait spawns 2025-01-06 09:58:30 -08:00
Guilherme Pereira f49a114f0f make aprijuice mix colors base on flavors 2025-01-06 14:00:30 -03:00
Guilherme Pereira 281fc300a6 fix merge 2025-01-06 14:00:20 -03:00
plastered_crab ea7078b749 Merge branch 'refs/heads/main' into we_are_cooking_now
# Conflicts:
#	common/src/main/kotlin/com/cobblemon/mod/common/CobblemonItems.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/CobblemonNetwork.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/client/CobblemonBakingOverrides.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/item/interactive/PokerodItem.kt
#	common/src/main/resources/assets/cobblemon/lang/en_us.json
#	common/src/main/resources/data/cobblemon/tags/block/flowers.json
#	common/src/main/resources/data/minecraft/tags/block/flowers.json
#	fabric/src/main/kotlin/com/cobblemon/mod/fabric/CobblemonFabric.kt
2025-01-06 08:03:32 -08:00
plastered_crab 03aabb55ca Merge remote-tracking branch 'origin/we_are_cooking_now' into we_are_cooking_now 2025-01-06 07:33:30 -08:00
plastered_crab 078da5b213 Adjust tooltip info for "seasoning" ingredients 2025-01-06 07:33:19 -08:00
Guilherme Pereira 22af77c7e6 add aprijuice item color provider 2025-01-06 12:21:32 -03:00
Guilherme Pereira 7ee7a6624f add dynamic rendering for poke baits based on seasonings 2025-01-06 10:19:43 -03:00
plastered_crab 85c9fcd28e Added test tooltip info for "seasoning" ingredients to show flavor data (thank you Tim) 2025-01-05 23:16:51 -08:00
plastered_crab 619da2e19a All berry seasoning files are done now! So many flavors! 2025-01-05 21:49:06 -08:00
plastered_crab c457cdfe5e Edit the seasoning files to include accurate berry flavors 2025-01-05 18:19:24 -08:00
plastered_crab a87c319d10 Fishing Bait combining works now! Fish be warned! 2025-01-04 23:53:18 -08:00
plastered_crab db5bdb0ef1 You can now combine fishing bait! (kind of) 2025-01-04 18:38:20 -08:00
JazzMcNade 50c567d264 Clean up, scale look radius with size 2025-01-04 18:35:14 -06:00
plastered_crab adc79a34d1 Gordon Ramsey is with me like the movie Ghost 2025-01-04 02:52:00 -08:00
plastered_crab 8776dffed4 What's that? are we close to cooking with Seasoning Slots?? I think so! 2025-01-04 01:49:57 -08:00
plastered_crab 77f5434b78 Started work on potential CookingComponent 2025-01-04 00:49:41 -08:00
JazzMcNade d4964e41d3 Clean up, fixed fluid handling 2025-01-03 22:04:23 -06:00
JazzMcNade 41b1c169c3 Merge branch 'main' into SaferSendouts 2025-01-03 20:49:13 -06:00
JazzMcNade 49e2001004 clean up 2025-01-03 20:48:28 -06:00
Konoha bf5fd5eed8 Merge remote-tracking branch 'origin/main' 2025-01-03 19:19:26 -05:00
Konoha facead5f0b Preliminary species form support for Pokedex 2025-01-03 19:12:31 -05:00
plastered_crab 0191373ff5 Slight tweak to RICE placement in shallow water 🌾 2025-01-03 12:09:41 -08:00
plastered_crab 0daf995c70 The RICE it grooooooows in water babyyy 🌾 2025-01-03 09:13:29 -08:00
plastered_crab dd9437c663 Fix the bounding box shape of the RICE and allow it to be waterlogged🌾 2025-01-03 01:29:17 -08:00
plastered_crab 752675ffb0 Can you smell what the RICE is cooking?!? 🌾🌾🍚🍙🌾🌾 2025-01-03 00:24:50 -08:00
JazzMcNade 66393f9293 Merge branch 'main' into SaferSendouts 2025-01-02 21:11:07 -06:00
Plastered_Crab 5bcc0fb343 Alcremie Sweets are cookable + honey bottles return glass bottles when cooked with 2025-01-02 16:34:59 -08:00
Plastered_Crab 2cd726c003 Aprijuice is coming (for real this time) 2025-01-02 16:12:00 -08:00
Plastered_Crab f911ad57b9 Aprijuice is coming 🚨🚨🚨 2025-01-02 16:10:21 -08:00
Plastered_Crab bc2a547b86 Yeah boi we cooking with some recipes now 🧑🏻‍🍳 2025-01-02 13:53:48 -08:00
Plastered_Crab d5ba9bc3f5 Shapeless recipes go brrrr 🧑🏻‍🍳 2025-01-02 11:37:32 -08:00
plastered_crab 3dc8493b76 Start to getting Cooking Pot Shapeless recipes working 2025-01-01 20:13:56 -08:00
Plastered_Crab 0b991c4ae3 Let's gooooooo! Cooking Pot seasoning slots and renderer working so good now 🧑🏻‍🍳 2025-01-01 13:14:17 -08:00
Plastered_Crab 1352508070 Yeah baby CookingPot stays rendered now and Components work properly now 😎 2025-01-01 12:49:58 -08:00
plastered_crab 87d467ec67 My God I'm dumb. It works now lmao 2025-01-01 00:37:17 -08:00
plastered_crab c020deb728 Please god end this suffering. Why won't this work 💀 2024-12-31 23:15:39 -08:00
JazzMcNade 7b3b6146a1 Single raycast to avoid spawning in walls, setPositionSafely can no longer path into a wall 2024-12-30 20:44:32 -06:00
plastered_crab d5e15f7bf2 Attempting to store data on Campfire Block Entity via Components 2024-12-30 17:04:09 -08:00
JazzMcNade e1452244c2 Merge branch 'main' into SaferSendouts 2024-12-30 12:50:24 -06:00
plastered_crab 59622a1bfb Additional fixes for crafting grid syncing 2024-12-30 10:50:12 -08:00
Conan 8913d3df11 Reworked SpectateBattleHandler.kt 2024-12-30 18:23:58 +01:00
plastered_crab 1c237503a0 Cooking Pot syncs with crafting slots finally 2024-12-29 22:22:43 -08:00
plastered_crab 138a83c844 More fixes and syncing 2024-12-29 16:57:39 -08:00
plastered_crab e8c86f4b4e Cooking Pot clears crafting slots when result item is taken 2024-12-29 16:45:16 -08:00
plastered_crab 344d2ae3e6 plz pot 2024-12-29 16:08:58 -08:00
plastered_crab 19a571147b I hate this pot 2024-12-29 14:59:34 -08:00
plastered_crab 2f369fb6ee More work trying to get the Cooking Pot to behave 2024-12-29 14:24:31 -08:00
Conan 3a55965704 Merge branch 'main' of https://gitlab.com/cable-mc/cobblemon into spectate-command
# Conflicts:
#	common/src/main/kotlin/com/cobblemon/mod/common/CobblemonCommands.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/api/permission/CobblemonPermissions.kt
2024-12-29 12:30:54 +01:00
plastered_crab c1d16f5185 Redo how crafting slots are initialized for Cooking Pot (result = 0 crafting 1-9) and add more debug 2024-12-28 22:36:11 -08:00
plastered_crab 2382895a42 Add minecraft:potion id for crafting medicinal brew 2024-12-27 18:09:39 -08:00
plastered_crab 68adae082b Additional recipes for the Cooking Pot 2024-12-27 17:12:49 -08:00
Erusel eac1b573c9 trying to debugs these ***** slots (i think ?) 2024-12-27 22:42:38 +01:00
JazzMcNade 5358414a0c Merge branch 'main' into SaferSendouts 2024-12-24 15:27:25 -06:00
JazzMcNade d691373919 Capped collision box size. Added trace to help prevent attempts to send outs going into walls 2024-12-15 20:14:30 -06:00
JazzMcNade 038f13e6fa Merge branch 'main' into SaferSendouts 2024-12-15 00:52:31 -06:00
Erusel a29a17a28b Added Cooking Pot ( globally ) 2024-12-13 00:09:33 +01:00
JazzMcNade dd288a3b0c SetPositionSafely now implements BFS WIP 2024-12-08 21:39:17 -06:00
Erusel 4805659a68 Started furnace like crafting 2024-12-03 09:42:54 +01:00
Erusel fbdcfb20ed Cooking Pot now keep items inside 2024-11-30 12:11:28 +01:00
Erusel 4a2b186ef7 Merge remote-tracking branch 'origin/we_are_cooking_now' into we_are_cooking_now 2024-11-30 12:10:48 +01:00
Plastered_Crab fa41b30a4c Add 2 test overlays for Poke Bait 2024-11-29 18:42:38 -08:00
Plastered_Crab 505282986e Add better texture for Poke Bait 2024-11-29 17:13:15 -08:00
Plastered_Crab 9e6e74db7c Add test recipe for Poke Bait 2024-11-29 14:03:01 -08:00
Plastered_Crab cf68e88103 Add test Poke Bait sprite for testing new combining bait system 2024-11-29 12:44:59 -08:00
Plastered_Crab 84ae73d0d1 Add test Pokepuff sprites for testing 2024-11-29 12:35:38 -08:00
Erusel 9bb0f13793 Added cooking pot to the block group 2024-11-29 16:51:16 +01:00
Erusel 912485067b Working cooking pot recipe book 2024-11-29 12:10:59 +01:00
Plastered_Crab 128f7c15a6 Add debug chaos to try to help see why registering recipes doesnt work 2024-11-28 00:44:05 -08:00
Erusel 5d67d0fdfc - i want to die 2024-11-28 03:12:45 +01:00
Erusel 3f90d19801 - Added Cooking Pot block
- Added Sweety things
- Started cooking pot handled things
2024-11-26 22:28:05 +01:00
Conan 7112c74bf2 Reworked spectate command. 2024-11-09 22:37:11 +01:00
Conan faa1906290 Added a spectate battle command. 2024-11-09 17:30:01 +01:00
Plastered_Crab 897e1651c5 Remove unneeded file 2024-11-05 14:49:17 -08:00
Plastered_Crab 9c5bb2fcdb Start to implementing Sweet Incense block 2024-11-05 12:14:47 -08:00
Plastered_Crab 8ee8d84c8b Add missing bugwort textures and blockstates 2024-11-04 15:43:56 -08:00
Plastered_Crab b25fbf42ab Bugwort plants now grow and behave properly 2024-11-04 15:40:23 -08:00
Plastered_Crab f9f3392901 Leaves drip honey down below to other leaves more often 2024-11-04 11:33:14 -08:00
Plastered_Crab 35249f5804 Stripped Saccharine Logs now give Sweet Sap again 2024-11-03 23:34:12 -08:00
Plastered_Crab b32fdeda9c Merge remote-tracking branch 'origin/we_are_cooking_now' into we_are_cooking_now 2024-11-03 23:07:07 -08:00
tmetcalfe89 1d033701ed fix leaf block
keys in the ignition, bonemeal on, redundant props removed
2024-11-03 22:53:31 -08:00
Plastered_Crab 6422cffde3 Merge branch 'main' into we_are_cooking_now 2024-11-03 14:35:58 -08:00
Plastered_Crab e8588370e5 Remove not needed tag additions for leaves 2024-11-03 13:39:11 -08:00
Plastered_Crab a96692e5cf Bees now like the Saccharine Leaves again and added more old files back that were missing 2024-11-03 13:24:58 -08:00
Nick 81c272778f Merge branch 'we_are_cooking_now' of gitlab.com:cable-mc/pokemon-cobbled into we_are_cooking_now 2024-11-02 01:11:33 -07:00
Nick 31351116b5 Include a configuration for maxShiftBy 2024-11-02 01:11:18 -07:00
Plastered_Crab fd18e4d7f1 Remove unneeded tags in saccharine_leaves json block tag 2024-11-02 00:35:32 -07:00
Plastered_Crab 7eb5364ba7 Add BeeEntityMixin to mixins.cobblemon-common json file 2024-11-02 00:10:03 -07:00
Plastered_Crab 97b679bbe0 Add saccharine_leaves block tags 2024-11-01 23:32:14 -07:00
Plastered_Crab 85dc3ad1d7 Add Saccharine Trees to bee_growables list 2024-11-01 23:18:40 -07:00
Plastered_Crab a90e9544be More remappings and trying to get Bees to fertilize Saccharine Leaves again 2024-11-01 17:14:46 -07:00
Plastered_Crab 6261163728 Add old Abstract CookingPot ScreenHandler to new branch to be remapped 2024-10-31 16:42:52 -07:00
Plastered_Crab 9288ae8776 More work fixing up some remappings 2024-10-31 16:35:13 -07:00
Plastered_Crab f887f678f1 - Add back more missing files from old branch that need re-mapped 2024-10-28 12:20:26 -07:00
Plastered_Crab 59ba74606e - Add textures for real real this time 2024-10-25 14:44:44 -07:00
Plastered_Crab 130b1c99db - Add textures for missing Saccharine items and add missing recipes for Saccharine items. Set stage for re-adding bugwort, saccharine saplings, cooking pot, etc 2024-10-25 14:24:00 -07:00
Plastered_Crab adc4b424c5 Merge branch 'main' into we_are_cooking_now 2024-10-25 12:22:57 -07:00
Erusel 4ad140f7a3 saccharines bases blocks 2024-09-06 20:48:52 +02:00
2181 changed files with 147992 additions and 39428 deletions
+11
View File
@@ -0,0 +1,11 @@
### Additions
- Added the Campfire Pot, made from apricorns and placed onto campfires.
- This pot can be used to make bait for fishing, Poké Cakes, Lure Cakes, local specialties, and potions (less efficiently than a brewing stand).
- There is a different pot for each apricorn colour because at this point I think we may have an addiction.
- Added Aprijuice, made from the Campfire Pot using apricorns with seasoning to give flavours.
- Aprijuice can be fed to ride-able Pokémon to improve their riding characteristics, depending on the flavour and the Pokémon's nature.
### Datapack and Addon Changes
- Renamed the fishing_baits datapack folder to spawn_bait_effects.
- Added `seasonings` datapack folder for controlling usable items in the campfire pot and what colour and flavour they apply.
- Added campfire pot recipe type, which you could use to make anything work as fishing bait.
+12
View File
@@ -0,0 +1,12 @@
### Additions
- Added functionality for marks.
- Added data for all marks and all title ribbons from Pokémon.
- Added marks screen within the summary UI.
- Added `/givemark <player> <partySlot> <mark>` command to give a mark to a Pokémon.
- Added `/takemark <player> <partySlot> <mark>` command to remove a mark from a Pokémon.
- Added `/giveallmarks <player> <partySlot>` command to give all available marks to a Pokémon.
### MoLang & Datapacks
- Added Flows for `bobber_spawn_pokemon_post`, `pokemon_entity_spawn`, and `fossil_revived`.
- Added `marks` datapack folder.
- Added MoLang functions `entity.is_in_rain`, `pokemon.add_marks(Mark...)`, `pokemon.add_potential_marks(Mark...)`, `pokemon.add_marks_with_chance(Mark...)`, `pokemon.apply_potential_marks`, and `world.is_snowing_at(x, y, z)`.
+1
View File
@@ -6,6 +6,7 @@
- Added filter functionality in PC UI, which supports `PokemonProperties` (e.g. `shiny=yes` shows all shiny Pokémon).
- Added `/changewallpaper <player> <boxNumber> <wallpaper>` command to change a box wallpaper through commands.
- Added `/renamebox <player> <boxNumber> <name>` command to rename a PC box through commands.
- Added IVs and EVs stat displays in PC.
### Developer
- Added `RenamePCBoxEvent.Pre` and `RenamePCBoxEvent.Post` events to prevent players from renaming a box or changing their input.
+140 -2
View File
@@ -2,6 +2,7 @@
## [1.7.0 (Month xth, 2025)](#1-7-0)
### Additions
- Added `/spectateBattle <player>` command to spectate battles without having to manually walk up to the target.
- Added an in-game configuration screen, allowing all settings from `main.json` to be edited directly in-game.
- Added `/cobblemonconfig reload` command to reload `main.json` configuration. **Note:** Some settings require a server restart to take effect; use this command cautiously.
- Added `blacklisted_items_to_hold` and `whitelisted_items_to_hold` tags to allow for controlling which items players can give to their Pokémon. If the whitelist is empty, it will consider all item as allowed (unless they are in the blacklist).
@@ -10,14 +11,129 @@
- Added cosmetic item functionality for Pokémon. Certain cosmetic items can be given to applicable Pokémon via the interact menu.
- Added the various log blocks as cosmetic items for Timburr and Komala.
- Added `visibility/hidden`, `visibility/hat` and `visibility/face` tags to control where and how certain items are rendered.
- Added Pokémon markings, toggleable within the summary.
- Added `/boxcount` command to change PC boxes amount
- Added cosmetics for Gurdurr, Conkeldurr, Squirtle Line, Sneasler, Sandile line, Treecko line, Braixen, Delphox, and Dragonite.
- Added cosmetics for Gurdurr, Conkeldurr, Squirtle Line, Sneasler, Sandle line, Treecko line, Braixen, Delphox, and Dragonite.
- Added `/transformmodelpart (position|rotation|scale) <modelPart> <transform: x y z>` command that can add transformations to a pokemon's model part.
- The player executing the command must be facing the target pokemon entity. Transformations are not persistent and will revert when resources are reloaded.
- Added lang keys for all moves and abilities up to Generation 9.
- Fixed Moon Ball moon phase logic to actually work correctly
- Added `translucent_cull` boolean option into resolver's layer to allow for translucent textures with culling
- Added [LambDynamicLights](https://modrinth.com/mod/lambdynamiclights) support for items held by Pokémon.
### Pokémon Added
#### Gen 2
- Dunsparce
#### Gen 3
- Spoink
- Grumpig
- Snorunt
- Glalie
#### Gen 4
- Bronzor
- Bronzong
- Croagunk
- Froslass
#### Gen 5
- Pansage
- Simisage
- Pansear
- Simisear
- Panpour
- Simipour
- Munna
- Musharna
- Blitzle
- Zebstrika
- Trubbish
- Garbodor
#### Gen 6
- Noibat
- Noivern
#### Gen 7
- Drampa
#### Gen 8
- Silicobra
- Sandaconda
#### Gen 9
- Smoliv
- Dolliv
- Arboliva
- Orthworm
- Dudunsparce
### Animation updates for the following Pokémon
- Garchomp
- Tropius
- Torpius
- Nosepass
- Probopass
- Sneasler
- Braixen
- Delphox
- Cinderace
- Kangaskhan
### Model updates for the following Pokémon
- Gyarados
- Dragonite
- Eevee
- Vaporeon
- Jolteon
- Flareon
- Espeon
- Umbreon
- Leafeon
- Glaceon
- Sylveon
- Treecko
- Grovyle
- Sceptile
- Honchkrow
- Garchomp
- Pidgeot
- Nosepass
- Probopass
- Kangaskhan
- Cinderace
- Magnezone
- Metagross
- Added Syrupy Apples.
### Changes
- Renamed `chargeGainedPerTick` config to `secondsToChargeHealingMachine`.
- Made Blocks of Gold count as Big Nuggets when held by a Pokémon (for Fling functionality)
- Players can now eat Sweet and Tart Apples, Whipped Dreams, and the Alcremie Sweets.
- Updated Sweet and Tart Apple sprites
- Updated the following recipes: Air Balloon, Assault Vest, Binding Band, Black Belt, Blunder Policy, Choice Band, Choice Scarf, Cleanse Tag, Covert Cloak, Destiny Knot, Eject Button, Expert Belt, Focus Band, Focus Sash, Magnet, Metronome, Muscle Band, Power Anklet, Power Band, Power Belt, Power Bracer, Power Lens, Power Weight, Protective Pads, Protein, Punching Glove, Reaper Cloth, Rocky Helmet, Room Service, Sachet, Safety Goggles, Silk Scarf, Spell Tag, Utility Umbrella, Weakness Policy, Zinc
- Added alternate ingredient options to the following recipes: Cell Battery, Charcoal Stick, Dragon Fang, Miracle Seed, Mystic Water, Never Melt Ice, Twisted Spoon, Damp Rock, Heat Rock, Icy Rock, Smooth Rock
- Grouped together some recipes within the Recipe Book. Groups include: the seven basic Poké Balls, the seven basic Ancient Poké Balls, Gilded Chests, Pokedexes, and the Weather Rocks.
- Updated some item tags to better integrate behaviours between Cobblemon, Vanilla Minecraft, and other mods
- Removed Cooked Meat, Raw Meat, Protein Ingredients, and Zinc Ingredients, the first two are now using `c` namespace tags, the latter have better integrated use of tags within their recipes which removes need for custom tags.
- Added our seeds tag into `#c:seeds`, which is now made use of for the Miracle Seed recipe.
- Tweaked the Natural Materials Vanilla file to fit with the changes to tags
- Substantially optimised spawning checks mainly by front-loading biome filtering.
- When using the `cobblemon` or `generation_9` capture calculators a critical capture with a single shake will always play for successful captures when you've already registered the Pokémon as caught in your Pokédex.
- Improved the performance of saving Pokédex and player data.
- Pokémon hitbox now scales with entity attribute `generic.scale`.
- Removed Shulker aspect and replaced it with cosmetic_item-shulker_shell.
- Shulker shell Forretress is now a cosmetic rather than a special evo and thus all shulker Forretress will revert back to normal until a shulker shell is put in their cosmetic slot.
- Updated `doPokemonSpawning` gamerule to support per-dimension configurations.
- The Pokedex now displays a form name of a "normal" Pokémon for when the base form is still a named form.
- Improved the zoom functionality of the Pokédex Scanner by giving the levels logarithmic scaling.
- Added a subtle rotation effect to the Pokédex Scanner's wheel when zooming.
- Improved parity with vanilla mobs' drop behavior; loot and XP drop on death instead of after the entire death sequence finishes.
- Quirk animations no longer play in the battle GUI since they were pretty distracting.
- A number of Pokemon that float above the ground visually (Gastly, Klingklang, etc.) are no longer considered to be touching the ground
### Fixes
- Fixed Particles sometimes facing the wrong direction (looking at you, Swords Dance)
@@ -40,11 +156,15 @@
- Fixed field name in evolution requirements for Spewpa Pokeball.
- Fixed LevelUpCriterion logic to correctly check that the Pokémon is a preEvo.
- Fixed `hide_additional_tooltip` vanilla flag not properly hiding tooltips on pokerod and bait items
- Removed a number of scenarios in which a Pokémon battle may send out a Pokémon into collision geometry.
- Fixed NPCs using Pokémon outside of their pool when a Pokémon name had a typo.
- Fixed an issue with datapacked species features not being applied properly when relogging.
- Fixed Pokémon marked as silent still playing shiny sounds and effects.
- Fixed an issue with newer versions of Fabric API where underground Pokémon were spawning in The End.
- Fixed spawning not working well when you're at high points surrounded by lower altitude spawning areas, such as flying.
- Fixed certain Pokémon with forms not having appropriate stock Pokédex entries.
- Fixed issue with Pokédex Scanner that caused the open/close overlay to have the wrong opacity values
- Fixed dragon's breath not being usable on the restoration tank when it should be
### Developer
- A finished battle now has winners and losers set inside of `PokemonBattle` instead of them always being empty.
@@ -62,7 +182,16 @@
- Updated NPCEntity beam positioning to properly account for the baseScale property.
- Updated NPCEntity pokeball throw positioning to properly account for the baseScale property.
- Fixed `[Pokemon].copyFrom` error causing forms, IVs, and EVs to not be applied properly when using `[Pokemon].loadFromJSON` or `[Pokemon].loadFromNBT`
- Added new item class, `WearableItem`. Instances of this class should have a corresponding 3D model. These models render when the items display context is `HEAD`.
- Pokemon now have a fireImmune attribute in their behaviour that can be set to true to ignore all fire damage (lava, magma blocks, etc.)
`JSON
{
"behaviour": {
"fireImmune": true
}
}
`
### MoLang & Datapacks
- The following usages for item predicates can now use item conditions like advancements do, you can learn about them in the [Minecraft wiki](https://minecraft.wiki/w/Advancement_definition#minecraft:filled_bucket)
- The `requiredContext` for an item interaction evolution
@@ -72,7 +201,15 @@
- Added `interpolate` boolean property to animated textures to allow gradual colour changes between frames.
- Fixed species additions not being capable of changing implemented status.
- Added support for action effects that are triggered by `|-activate|` Showdown instructions. `activate_{effect_id}` is the syntax.
- Added Molang functions for rendering items `render_item(item_id, locator_name)` and `clear_items()`.
- Added MoLang functions for rendering items `render_item(item_id, locator_name)` and `clear_items()`.
- Fixed location spawn filter components causing crashes
- Added `pokemon` as an available MoLang function for the `battleActor` functions.
- Added `spawn_pokemon` as an available MoLang function for the `worldHolder` functions.
- Added `attempt_wild_battle` as an available MoLang function.
- Added `pokemon` as an available Molang function for the `battleActor` functions.
- Fixed `heldItem` property inside spawn files not working and causing crashes
- Fixed `spawn_bedrock_particles` MoLang causing crashes when used in a server environment
- The Pokédex form lang key definition now follows `cobblemon.ui.pokedex.info.form.{species}-{formname}` instead of `cobblemon.ui.pokedex.info.form.{formname}`.
## [1.6.1 (January 26th, 2025)](#1-6-1)
@@ -178,6 +315,7 @@
- Geodude
- Graveler
- Golem
- Magnezone
### Cry updates for the following Pokémon
- Sceptile
+3 -2
View File
@@ -1,8 +1,9 @@
import utilities.isSnapshot
import utilities.version
import java.time.OffsetDateTime
import java.time.ZoneOffset
import java.time.format.DateTimeFormatter
import utilities.isSnapshot
import utilities.version
/*
*
@@ -0,0 +1,24 @@
/*
* 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.cobblemon.mod.common.api.orientation.OrientationController;
import net.minecraft.util.Mth;
import net.minecraft.util.SmoothDouble;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.phys.Vec3;
import org.jetbrains.annotations.Nullable;
import org.joml.Matrix3f;
import org.joml.Vector3f;
import java.util.function.Function;
public interface OrientationControllable {
OrientationController getOrientationController();
}
@@ -1,143 +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;
import net.minecraft.util.Mth;
import net.minecraft.util.SmoothDouble;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.phys.Vec3;
import org.jetbrains.annotations.Nullable;
import org.joml.Matrix3f;
import org.joml.Vector3f;
import java.util.function.Function;
public interface Rollable {
// From Minecraft's Camera
Vector3f FORWARDS = new Vector3f(0.0F, 0.0F, -1.0F);
Vector3f UP = new Vector3f(0.0F, 1.0F, 0.0F);
Vector3f LEFT = new Vector3f(-1.0F, 0.0F, 0.0F);
@Nullable Matrix3f getOrientation();
Rollable updateOrientation(Function<Matrix3f, Matrix3f> update);
/**
* @return The forward vector (0, 0, -1) after the rotation matrix is applied.
*/
default Vector3f getForwardVector() {
if (getOrientation() == null) return new Vector3f(FORWARDS);
return getOrientation().transform(FORWARDS, new Vector3f());
}
/**
* @return The left vector (-1, 0, 0) after the rotation matrix is applied.
*/
default Vector3f getLeftVector() {
if (getOrientation() == null) return new Vector3f(LEFT);
return getOrientation().transform(LEFT, new Vector3f());
}
/**
* @return The up vector (0, 1, 0) after the rotation matrix is applied.
*/
default Vector3f getUpVector() {
if (getOrientation() == null) return new Vector3f(UP);
return getOrientation().transform(UP, new Vector3f());
}
/**
*
* @param yaw change in degrees
* @return The Rollable object this method was called on
*/
default Rollable rotateYaw(float yaw) {
return updateOrientation(prev -> prev.rotateY((float) Math.toRadians(-yaw)));
}
/**
*
* @param pitch change in degrees
* @return The Rollable object this method was called on
*/
default Rollable rotatePitch(float pitch) {
return updateOrientation(prev -> prev.rotateX((float) Math.toRadians(-pitch)));
}
/**
*
* @param roll change in degrees
* @return The Rollable object this method was called on
*/
default Rollable rotateRoll(float roll) {
return updateOrientation(prev -> prev.rotateZ((float) Math.toRadians(-roll)));
}
/**
* Order matters when rotating an object. If you need a different order, individually call rotateYaw, rotatePitch, and rotateRoll
*
* @param yaw change in degrees
* @param pitch change in degrees
* @param roll change in degrees
* @return The Rollable object this method was called on
*/
default Rollable rotate(float yaw, float pitch, float roll) {
return rotateYaw(yaw).rotatePitch(pitch).rotateRoll(roll);
}
/**
* @return The pitch angle in degrees as a float.
* Value is between [-180, 180] with 0 being South, 90 being West, 180/-180 being North, and -90 being East
*/
default float getYaw() {
return (float) Mth.wrapDegrees(-Math.toDegrees(FORWARDS.angleSigned(getForwardVector(), UP)) + 180);
}
/**
* @return The yaw angle in degrees as a float.
* Value is between [-90, 90] with 0 being straight forward, 90 being straight down, and -90 being straight up
*/
default float getPitch() {
return (float) Mth.wrapDegrees(-Math.toDegrees(Math.asin(getForwardVector().y)));
}
/**
* @return The roll angle in degrees as a float.
* Value is between [-180, 180] with 0 being no roll (normal), 90 being 90 degrees CW, 180/-180 being 180 degrees CW/CCW, and -90 being 90 degrees CCW
*/
default float getRoll() {
//Cobblemon.LOGGER.info("{}", (float) Math.toDegrees(getUpVector().angleSigned(UP, getForwardVector())));
return (float) Mth.wrapDegrees(-Math.toDegrees(getUpVector().angleSigned(UP, getForwardVector())));
}
/**
* Get the angular velocity in degrees per second as a Vec3
*/
Vec3 angRollVel( double deltaTime );
public Vec3 rotationOnMouseXY(
double yMouse,
double xMouse,
SmoothDouble yMouseSmoother,
SmoothDouble xMouseSmoother,
double sensitivity,
double deltaTime
);
boolean shouldRoll();
boolean useAngVelSmoothing();
void clearRotation();
}
@@ -13,10 +13,12 @@ import com.cobblemon.mod.common.client.render.layer.PokemonOnShoulderRenderer;
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity;
import com.cobblemon.mod.common.pokemon.FormData;
import com.cobblemon.mod.common.pokemon.lighthing.LightingData;
import dev.lambdaurora.lambdynlights.LambDynLights;
import dev.lambdaurora.lambdynlights.api.DynamicLightHandler;
import dev.lambdaurora.lambdynlights.api.DynamicLightHandlers;
import net.minecraft.core.BlockPos;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.item.ItemStack;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -53,15 +55,19 @@ public class LambDynamicLightsCompat {
private static int resolvedPokemonLightLevel(PokemonEntity pokemon) {
var underwater = !pokemon.level().getFluidState(BlockPos.containing(pokemon.getX(), pokemon.getEyeY(), pokemon.getZ())).isEmpty();
return extractFormLightLevel(pokemon.getForm(), underwater).orElse(0);
ItemStack item = pokemon.getShownItem();
int itemLightLevel = item.isEmpty()?0:LambDynLights.getLuminanceFromItemStack(item, underwater);
int formLightLevel = extractFormLightLevel(pokemon.getForm(), underwater).orElse(0);
return Math.max(itemLightLevel, formLightLevel);
}
private static int resolvedShoulderLightLevel(Player player) {
final var shoulderDataPair = PokemonOnShoulderRenderer.shoulderDataOf(player);
var underwater = !player.level().getFluidState(BlockPos.containing(player.getX(), player.getEyeY(), player.getZ())).isEmpty();
final Optional<Integer> leftLightLevel = extractShoulderLightLevel(shoulderDataPair.getFirst(), underwater);
final Optional<Integer> rightLightLevel = extractShoulderLightLevel(shoulderDataPair.getSecond(), underwater);
return Math.max(leftLightLevel.orElse(0), rightLightLevel.orElse(0));
final int leftLightLevel = extractShoulderLightLevel(PokemonOnShoulderRenderer.shoulderDataFrom(player.getShoulderEntityLeft()), underwater);
final int rightLightLevel = extractShoulderLightLevel(PokemonOnShoulderRenderer.shoulderDataFrom(player.getShoulderEntityRight()), underwater);
return Math.max(leftLightLevel, rightLightLevel);
}
private static Optional<Integer> extractFormLightLevel(@NotNull FormData form, boolean underwater) {
@@ -71,11 +77,16 @@ public class LambDynamicLightsCompat {
return Optional.of(form.getLightingData().getLightLevel());
}
private static Optional<Integer> extractShoulderLightLevel(@Nullable PokemonOnShoulderRenderer.ShoulderData shoulderData, boolean underwater) {
private static int extractShoulderLightLevel(@Nullable PokemonOnShoulderRenderer.ShoulderData shoulderData, boolean underwater) {
if (shoulderData == null) {
return Optional.empty();
return 0;
}
return extractFormLightLevel(shoulderData.getForm(), underwater);
ItemStack item = shoulderData.getShownItem();
int itemLightLevel = item.isEmpty()?0:LambDynLights.getLuminanceFromItemStack(item, underwater);
int formLightLevel = extractFormLightLevel(shoulderData.getForm(), underwater).orElse(0);
return Math.max(itemLightLevel, formLightLevel);
}
private static boolean liquidGlowModeSupport(@NotNull LightingData.LiquidGlowMode liquidGlowMode, boolean underwater) {
@@ -0,0 +1,62 @@
/*
* 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.block.SaccharineLeafBlock;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockState;
import org.objectweb.asm.Opcodes;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Desc;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.ModifyVariable;
import org.spongepowered.asm.mixin.injection.Slice;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
@Mixin(targets = "net.minecraft.world.entity.animal.Bee$BeeGrowCropGoal")
public abstract class BeeEntityMixin {
@Unique
private BlockState cobblemon$result = null;
@Inject(method = "tick()V", at = @At(
value = "INVOKE",
target = "Lnet/minecraft/world/level/block/BonemealableBlock;performBonemeal(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/util/RandomSource;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;)V",
shift = At.Shift.BY,
by = 2
),
locals = LocalCapture.CAPTURE_FAILHARD
)
private void injectCustomGrowth(CallbackInfo ci, int i, BlockPos blockPos, BlockState blockState, Block block) {
if (block instanceof SaccharineLeafBlock) {
int age = blockState.getValue(SaccharineLeafBlock.Companion.getAGE());
if (age < 2) {
this.cobblemon$result = blockState.setValue(SaccharineLeafBlock.Companion.getAGE(), age + 1);
}
}
}
@ModifyVariable(method = "tick", at = @At(value = "LOAD", ordinal = 0), index = 5)
private BlockState applyCustomBlockState(BlockState before) {
if(this.cobblemon$result != null && before == null) {
BlockState result = this.cobblemon$result;
this.cobblemon$result = null;
return result;
}
return before;
}
}
@@ -8,31 +8,112 @@
package com.cobblemon.mod.common.mixin;
import net.minecraft.client.player.LocalPlayer;
import com.cobblemon.mod.common.OrientationControllable;
import com.cobblemon.mod.common.api.orientation.OrientationController;
import com.cobblemon.mod.common.api.riding.Seat;
import com.cobblemon.mod.common.client.entity.PokemonClientDelegate;
import com.cobblemon.mod.common.client.render.MatrixWrapper;
import com.cobblemon.mod.common.client.render.models.blockbench.FloatingState;
import com.cobblemon.mod.common.client.render.models.blockbench.PosableModel;
import com.cobblemon.mod.common.client.render.models.blockbench.repository.VaryingModelRepository;
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity;
import com.mojang.authlib.GameProfile;
import net.minecraft.client.CameraType;
import net.minecraft.client.Minecraft;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.client.player.AbstractClientPlayer;
import net.minecraft.client.player.LocalPlayer;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.ClipContext;
import net.minecraft.world.phys.HitResult;
import net.minecraft.world.phys.Vec3;
import org.jetbrains.annotations.NotNull;
import org.joml.Matrix3f;
import org.joml.Vector3f;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import java.util.Map;
@Mixin(LocalPlayer.class)
public abstract class LocalPlayerMixin {
public abstract class LocalPlayerMixin extends AbstractClientPlayer implements OrientationControllable {
@Shadow
private float jumpRidingScale;
public LocalPlayerMixin(ClientLevel clientLevel, GameProfile gameProfile) {
super(clientLevel, gameProfile);
}
@Inject(method = "getJumpRidingScale", at = @At("HEAD"), cancellable = true)
public void modifyJumpRidingScale(CallbackInfoReturnable<Float> cir) {
LocalPlayer player = (LocalPlayer) (Object) this;
if (player.isPassenger() && player.getVehicle() instanceof PokemonEntity) {
PokemonEntity ride = (PokemonEntity) player.getVehicle();
//Use custom jump bar logic if the current ride does not jump using it.
if( !ride.getRiding().canJump(ride, player))
{
cir.setReturnValue(ride.setRideBar());
if (player.isPassenger() && player.getVehicle() instanceof PokemonEntity pokemonEntity) {
var rideValue = pokemonEntity.<Float>ifRidingAvailableSupply(null, (behaviour, settings, state) -> {
if (behaviour.canJump(settings, state, pokemonEntity, player)) return null;
return behaviour.setRideBar(settings, state, pokemonEntity, player);
});
if (rideValue != null) {
cir.setReturnValue(rideValue);
}
}
}
}
@Override
public HitResult pick(double hitDistance, float partialTicks, boolean hitFluids) {
Entity vehicle = this.getVehicle();
if (vehicle instanceof PokemonEntity pokemonEntity) {
int seatIndex = pokemonEntity.getPassengers().indexOf(this);
Seat seat = pokemonEntity.getSeats().get(seatIndex);
PokemonClientDelegate delegate = (PokemonClientDelegate) pokemonEntity.getDelegate();
MatrixWrapper locator = delegate.getLocatorStates().get(seat.getLocator());
if (locator == null) {
super.pick(hitDistance, partialTicks, hitFluids);
}
Vec3 locatorOffset = new Vec3(locator.getMatrix().getTranslation(new Vector3f()));
OrientationController controller = this.getOrientationController();
float currEyeHeight = this.getEyeHeight();
Vector3f offset = new Vector3f(new Vector3f(0f, currEyeHeight - (this.getBbHeight() / 2), 0f));
if (Minecraft.getInstance().options.getCameraType() == CameraType.FIRST_PERSON) {
PosableModel model = VaryingModelRepository.INSTANCE.getPoser(pokemonEntity.getPokemon().getSpecies().getResourceIdentifier(), new FloatingState());
offset.add(cobblemon$getFirstPersonOffset(model, seat));
}
Matrix3f orientation = controller.isActive() && controller.getOrientation() != null ? controller.getOrientation() : new Matrix3f();
Vec3 rotatedEyeHeight = new Vec3(orientation.transform(offset));
Vec3 eyePosition = locatorOffset.add(pokemonEntity.position()).add(rotatedEyeHeight);
Vec3 viewVector = this.getViewVector(partialTicks);
Vec3 viewDistanceVector = eyePosition.add(viewVector.x * hitDistance, viewVector.y * hitDistance, viewVector.z * hitDistance);
return this.level()
.clip(
new ClipContext(
eyePosition, viewDistanceVector, ClipContext.Block.OUTLINE, hitFluids ? net.minecraft.world.level.ClipContext.Fluid.ANY : net.minecraft.world.level.ClipContext.Fluid.NONE, this
)
);
}
return super.pick(hitDistance, partialTicks, hitFluids);
}
@Unique
private static @NotNull Vector3f cobblemon$getFirstPersonOffset(PosableModel model, Seat seat) {
Map<String, Vec3> cameraOffsets = model.getFirstPersonCameraOffset();
if (cameraOffsets.containsKey(seat.getLocator())) {
return cameraOffsets.get(seat.getLocator()).toVector3f();
} else {
return new Vector3f(0f, 0f, 0f);
}
}
}
@@ -10,11 +10,11 @@ package com.cobblemon.mod.common.mixin;
import com.cobblemon.mod.common.Cobblemon;
import com.cobblemon.mod.common.CobblemonItems;
import com.cobblemon.mod.common.Rollable;
import com.cobblemon.mod.common.OrientationControllable;
import com.cobblemon.mod.common.api.events.CobblemonEvents;
import com.cobblemon.mod.common.api.events.item.LeftoversCreatedEvent;
import com.cobblemon.mod.common.api.orientation.OrientationController;
import com.cobblemon.mod.common.api.pokemon.PokemonSpecies;
import com.cobblemon.mod.common.api.riding.Rideable;
import com.cobblemon.mod.common.api.storage.party.PartyStore;
import com.cobblemon.mod.common.api.storage.party.PlayerPartyStore;
import com.cobblemon.mod.common.api.tags.CobblemonItemTags;
@@ -31,45 +31,37 @@ import com.cobblemon.mod.common.util.DataKeys;
import com.cobblemon.mod.common.world.gamerules.CobblemonGameRules;
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
import net.minecraft.client.Minecraft;
import net.minecraft.client.player.LocalPlayer;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.Tag;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.util.SmoothDouble;
import net.minecraft.world.damagesource.DamageSource;
import net.minecraft.world.entity.EntityDimensions;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.Pose;
import net.minecraft.world.entity.item.ItemEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.food.FoodProperties;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.level.Level;
import net.minecraft.world.phys.Vec3;
import org.jetbrains.annotations.Nullable;
import org.joml.Matrix3f;
import org.objectweb.asm.Opcodes;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.ModifyArg;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.UUID;
import java.util.function.Function;
import java.util.*;
import java.util.stream.Collectors;
@Mixin(Player.class)
public abstract class PlayerMixin extends LivingEntity implements Rollable, ScannableEntity {
public abstract class PlayerMixin extends LivingEntity implements ScannableEntity, OrientationControllable {
@Shadow public abstract CompoundTag getShoulderEntityLeft();
@@ -87,7 +79,10 @@ public abstract class PlayerMixin extends LivingEntity implements Rollable, Scan
@Shadow public abstract void displayClientMessage(Component message, boolean overlay);
@Unique private Matrix3f orientation = null;
@Shadow @Final private static Map<Pose, EntityDimensions> POSES;
@Shadow @Final public static EntityDimensions STANDING_DIMENSIONS;
@Unique
private final OrientationController cobblemon$orientationController = new OrientationController(this);
protected PlayerMixin(EntityType<? extends LivingEntity> p_20966_, Level p_20967_) {
super(p_20966_, p_20967_);
@@ -115,6 +110,19 @@ public abstract class PlayerMixin extends LivingEntity implements Rollable, Scan
}
}
@Inject(method = "tick", at = @At("HEAD"))
private void cobblemon$updateRenderOrientation(CallbackInfo ci) {
this.cobblemon$orientationController.tick();
}
@Override
public EntityDimensions getDefaultDimensions(Pose pose) {
if (this.getVehicle() instanceof PokemonEntity) {
return STANDING_DIMENSIONS;
}
return POSES.getOrDefault(pose, STANDING_DIMENSIONS);
}
@Inject(
method = "removeEntitiesOnShoulder",
at = @At(
@@ -241,7 +249,7 @@ public abstract class PlayerMixin extends LivingEntity implements Rollable, Scan
@Override
public void absMoveTo(double x, double y, double z, float yaw, float pitch) {
if (shouldRoll()) {
if (cobblemon$orientationController.getActive()) {
this.absMoveTo(x, y, z);
this.setYRot(yaw % 360.0f);
this.setXRot(pitch % 360.0f);
@@ -254,120 +262,21 @@ public abstract class PlayerMixin extends LivingEntity implements Rollable, Scan
}
}
@Inject(method = "tick", at = @At("HEAD"))
public void tick(CallbackInfo ci) {
if (this.shouldRoll()) {
// Proof of concept for yaw movement
if (this.getMainHandItem().is(Items.STICK)) {
this.rotateYaw(2);
}
else if (this.getMainHandItem().is(Items.BLAZE_ROD)) {
this.rotateYaw(-2);
}
}
}
@Override
public Matrix3f getOrientation() {
return orientation;
}
@Override
public Rollable updateOrientation(Function<Matrix3f, Matrix3f> update) {
//Disabled to allow non mouse inputs to modify roll
if (!shouldRoll()) return this;
if (this.orientation == null) {
this.orientation = new Matrix3f();
this.rotate(getYRot() - 180, getXRot(), 0);
}
this.orientation = update.apply(this.orientation);
setYRot(this.getYaw());
setXRot(this.getPitch());
return this;
}
@Override
public boolean shouldRoll() {
LocalPlayer player = Minecraft.getInstance().player;
if (!this.equals(player)) return false;
if (player.isHolding(Items.DIAMOND)) return true;
var playerVehicle = player.getVehicle();
if (playerVehicle == null) return false;
if (!(playerVehicle instanceof PokemonEntity pokemonEntity)) return false;
return pokemonEntity.getRiding().shouldRoll(pokemonEntity);
}
@Override
public Vec3 rotationOnMouseXY(
double yMouse,
double xMouse,
SmoothDouble yMouseSmoother,
SmoothDouble xMouseSmoother,
double sensitivity,
double deltaTime
) {
LocalPlayer player = Minecraft.getInstance().player;
if (!this.equals(player)) return Vec3.ZERO;
var playerVehicle = player.getVehicle();
if (playerVehicle == null) return Vec3.ZERO;
if (!(playerVehicle instanceof PokemonEntity pokemonEntity)) return Vec3.ZERO;
return pokemonEntity.getRiding().rotationOnMouseXY(
pokemonEntity,
player,
yMouse,
xMouse,
yMouseSmoother,
xMouseSmoother,
sensitivity,
deltaTime
);
}
@Override
public boolean useAngVelSmoothing() {
LocalPlayer player = Minecraft.getInstance().player;
if (!this.equals(player)) return true;
var playerVehicle = player.getVehicle();
if (playerVehicle == null) return true;
if (!(playerVehicle instanceof PokemonEntity pokemonEntity)) return true;
return pokemonEntity.getRiding().useAngVelSmoothing(pokemonEntity);
}
@Override
public Vec3 angRollVel( double deltaTime ) {
var ret = new Vec3(0.0, 0.0, 0.0);
LocalPlayer player = Minecraft.getInstance().player;
if (!this.equals(player)) return ret;
var playerVehicle = player.getVehicle();
if (playerVehicle == null) return ret;
if (!(playerVehicle instanceof PokemonEntity pokemonEntity)) return ret;
return pokemonEntity.getRiding().angRollVel( pokemonEntity, player, deltaTime );
}
@Override
public void clearRotation() {
this.orientation = null;
}
@WrapOperation(
method = "rideTick()V",
at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;wantsToStopRiding()Z")
)
public boolean delegateDismountToController(Player instance, Operation<Boolean> original) {
if (this.getVehicle() instanceof Rideable vehicle) {
return vehicle.getRiding().dismountOnShift() && original.call(instance);
if (this.getVehicle() instanceof PokemonEntity pokemonEntity) {
return pokemonEntity.ifRidingAvailableSupply(false, (behaviour, settings, state) -> {
return behaviour.dismountOnShift(settings, state, pokemonEntity) && original.call(instance);
});
}
return original.call(instance);
}
@Override
public OrientationController getOrientationController() {
return cobblemon$orientationController;
}
}
@@ -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 net.minecraft.stats.RecipeBookSettings;
import net.minecraft.world.inventory.RecipeBookType;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.util.Map;
@Mixin(RecipeBookSettings.class)
public class RecipeBookSettingsMixin {
@Shadow @Final public Map<RecipeBookType, RecipeBookSettings.TypeSettings> states;
@Inject(method = "<init>", at = @At("TAIL"))
private void cobblemon$init(CallbackInfo ci) {
states.put(RecipeBookType.valueOf("COOKING_POT"), new RecipeBookSettings.TypeSettings(true, true));
}
}
@@ -0,0 +1,46 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.mixin;
import net.minecraft.world.inventory.RecipeBookType;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Mutable;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.gen.Invoker;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.util.ArrayList;
import java.util.List;
@Mixin(value = RecipeBookType.class)
public class RecipeBookTypeMixin {
@Final
@Mutable
@Shadow
private static RecipeBookType[] $VALUES; // moj
@Invoker("<init>")
private static RecipeBookType cobblemon$createBookType(String name, int ordinal) {
throw new AssertionError();
}
@Inject(
method = "<clinit>",
at = @At("TAIL")
)
private static void cobblemon$addRecipeBookType(CallbackInfo ci) {
ArrayList<RecipeBookType> types = new ArrayList<>(List.of($VALUES));
types.add(cobblemon$createBookType("COOKING_POT", $VALUES.length));
$VALUES = types.toArray(RecipeBookType[]::new);
}
}
@@ -0,0 +1,101 @@
/*
* 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.CobblemonNetwork;
import com.cobblemon.mod.common.OrientationControllable;
import com.cobblemon.mod.common.api.net.NetworkPacket;
import com.cobblemon.mod.common.api.orientation.OrientationController;
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity;
import com.cobblemon.mod.common.mixin.accessor.ChunkMapAccessor;
import com.cobblemon.mod.common.mixin.accessor.TrackedEntityAccessor;
import com.cobblemon.mod.common.net.messages.client.orientation.ClientboundUpdateOrientationPacket;
import com.cobblemon.mod.common.net.messages.client.pokemon.update.ClientboundUpdateRidingStatePacket;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import net.minecraft.network.protocol.Packet;
import net.minecraft.server.level.ChunkMap;
import net.minecraft.server.level.ServerEntity;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.server.network.ServerPlayerConnection;
import net.minecraft.world.entity.Entity;
import org.joml.Matrix3f;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.util.Set;
import java.util.function.Consumer;
@Mixin(ServerEntity.class)
public abstract class ServerEntityMixin {
@Shadow
@Final
private Consumer<Packet<?>> broadcast;
@Shadow
@Final
private Entity entity;
@Unique
private Matrix3f cobblemon$lastSentOrientation;
@Unique
private boolean cobblemon$lastSentActive;
@Inject(method = "sendChanges", at = @At("TAIL"))
private void cobblemon$sendChanges(CallbackInfo ci) {
cobblemon$sendOrientationChanges();
cobblemon$sendRidingStateChanges();
}
private void cobblemon$sendRidingStateChanges() {
if (!(this.entity instanceof PokemonEntity pokemonEntity)) return;
if (pokemonEntity.getRidingState() == null) return;
if (pokemonEntity.getRiding() == null) return;
var ridingBehaviour = pokemonEntity.getRiding();
var ridingState = pokemonEntity.getRidingState();
var previousRidingState = pokemonEntity.getPreviousRidingState();
if (previousRidingState != null && !ridingState.shouldSync(previousRidingState)) return;
cobblemon$broadcast(new ClientboundUpdateRidingStatePacket(pokemonEntity.getId(), ridingBehaviour.getKey(), pokemonEntity.getRidingState(), null));
}
private void cobblemon$sendOrientationChanges() {
if (!(this.entity instanceof OrientationControllable controllable)) return;
OrientationController controller = controllable.getOrientationController();
Matrix3f currOrientation = controller.getOrientation();
boolean currActive = controller.getActive();
if (currOrientation == null || currOrientation.equals(cobblemon$lastSentOrientation) && (currActive == cobblemon$lastSentActive))
return;
cobblemon$lastSentOrientation = new Matrix3f(currOrientation);
cobblemon$lastSentActive = currActive;
cobblemon$broadcast(new ClientboundUpdateOrientationPacket(currOrientation, currActive, entity.getId()));
}
private void cobblemon$broadcast(NetworkPacket<?> packet) {
if (!(entity.level() instanceof ServerLevel level)) return;
ChunkMap chunkMap = level.getChunkSource().chunkMap;
Int2ObjectMap<?> entityMap = ((ChunkMapAccessor) chunkMap).getEntityMap();
Object tracked = entityMap.get(entity.getId());
if (!(tracked instanceof TrackedEntityAccessor tracker)) return;
Set<ServerPlayerConnection> seenBy = tracker.getSeenBy();
for (ServerPlayerConnection conn : seenBy) {
ServerPlayer player = conn.getPlayer();
if (player == entity) continue;
CobblemonNetwork.INSTANCE.sendPacketToPlayer(player, packet);
}
}
}
@@ -0,0 +1,46 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.mixin;
import com.cobblemon.mod.common.OrientationControllable;
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity;
import net.minecraft.server.level.ServerPlayer;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(ServerPlayer.class)
public abstract class ServerPlayerMixin {
@Inject(method = "rideTick", at = @At("HEAD"))
private void cobblemon$updateOrientationControllerRideTick(CallbackInfo ci) {
if (!(this instanceof OrientationControllable controllable)) return;
var shouldUseCustomOrientation = cobblemon$shouldUseCustomOrientation((ServerPlayer)(Object)this);
controllable.getOrientationController().setActive(shouldUseCustomOrientation);
}
@Unique
private boolean cobblemon$shouldUseCustomOrientation(ServerPlayer player) {
var playerVehicle = player.getVehicle();
if (playerVehicle == null) return false;
if (!(playerVehicle instanceof PokemonEntity pokemonEntity)) return false;
return pokemonEntity.ifRidingAvailableSupply(false, (behaviour, settings, state) -> {
return behaviour.shouldRoll(settings, state, pokemonEntity);
});
}
@Inject(method = "stopRiding", at = @At("HEAD"))
public void cobblemon$resetOrientationOnDismount(CallbackInfo ci) {
if (!(this instanceof OrientationControllable controllable)) return;
controllable.getOrientationController().setActive(false);
}
}
@@ -0,0 +1,20 @@
/*
* 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.accessor;
import net.minecraft.client.Camera;
import net.minecraft.world.level.BlockGetter;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
@Mixin(Camera.class)
public interface CameraAccessor {
@Accessor("level")
BlockGetter getLevel();
}
@@ -0,0 +1,20 @@
/*
* 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.accessor;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import net.minecraft.server.level.ChunkMap;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
@Mixin(ChunkMap.class)
public interface ChunkMapAccessor {
@Accessor("entityMap")
Int2ObjectMap<?> getEntityMap();
}
@@ -0,0 +1,22 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.mixin.accessor;
import net.minecraft.client.gui.components.StateSwitchingButton;
import net.minecraft.client.gui.screens.recipebook.RecipeBookComponent;
import net.minecraft.network.chat.Component;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Mutable;
import org.spongepowered.asm.mixin.gen.Accessor;
@Mixin(RecipeBookComponent.class)
public interface RecipeBookComponentAccessor {
@Accessor("filterButton")
StateSwitchingButton getFilterButton();
}
@@ -0,0 +1,21 @@
/*
* 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.accessor;
import net.minecraft.server.network.ServerPlayerConnection;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
import java.util.Set;
@Mixin(targets = "net.minecraft.server.level.ChunkMap$TrackedEntity")
public interface TrackedEntityAccessor {
@Accessor("seenBy")
Set<ServerPlayerConnection> getSeenBy();
}
@@ -8,10 +8,20 @@
package com.cobblemon.mod.common.mixin.client;
import com.cobblemon.mod.common.Rollable;
import com.cobblemon.mod.common.Cobblemon;
import com.cobblemon.mod.common.OrientationControllable;
import com.cobblemon.mod.common.api.riding.Rideable;
import com.cobblemon.mod.common.client.MountedPokemonAnimationRenderController;
import com.cobblemon.mod.common.client.render.camera.MountedCameraRenderer;
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity;
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
import com.llamalad7.mixinextras.sugar.Local;
import net.minecraft.client.Camera;
import net.minecraft.client.Minecraft;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.phys.Vec3;
import org.joml.Matrix3f;
import org.joml.Quaternionf;
import org.joml.Vector3f;
@@ -25,73 +35,127 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(Camera.class)
public abstract class CameraMixin {
@Shadow @Final private static float DEFAULT_CAMERA_DISTANCE;
@Shadow
private Entity entity;
@Shadow
@Final
private Quaternionf rotation;
@Shadow
@Final
private Vector3f forwards;
@Shadow
@Final
private Vector3f up;
@Shadow
@Final
private Vector3f left;
@Shadow
private float xRot;
@Shadow
private float yRot;
@Shadow private Entity entity;
@Shadow @Final private Quaternionf rotation;
@Shadow @Final private Vector3f forwards;
@Shadow @Final private Vector3f up;
@Shadow @Final private Vector3f left;
@Shadow private float xRot;
@Shadow private float yRot;
@Shadow
private float eyeHeight;
@Shadow
private float eyeHeightOld;
@Shadow public abstract float getXRot();
@Shadow
protected abstract void setPosition(Vec3 pos);
@Shadow public abstract float getYRot();
@Unique
private float returnTimer = 0;
@Unique
private float rollAngleStart = 0;
@Unique
Minecraft minecraft = Minecraft.getInstance();
@Unique private float returnTimer = 0;
@Unique private float rollAngleStart = 0;
@Unique Minecraft minecraft = Minecraft.getInstance();
@Unique boolean disableRollableCameraDebug = false;
@Unique
boolean disableRollableCameraDebug = false;
@Inject(method = "setRotation", at = @At("HEAD"), cancellable = true)
public void open_camera$setRotation(float f, float g, CallbackInfo ci) {
if (!(this.entity instanceof Rollable rollable) || disableRollableCameraDebug) return;
if (!rollable.shouldRoll() && rollable.getOrientation() != null) {
if(this.returnTimer < 1) {
public void cobblemon$setRotation(float f, float g, CallbackInfo ci) {
if (!(this.entity instanceof OrientationControllable controllable) || disableRollableCameraDebug) return;
var controller = controllable.getOrientationController();
if (!controller.isActive() && controller.getOrientation() != null) {
if (this.returnTimer < 1) {
//Rotation is taken from entity since we no longer handle mouse ourselves
//Stops a period of time when you can't input anything.
rollable.getOrientation().set(
controller.getOrientation().set(
new Matrix3f()
.rotateY((float) Math.toRadians(180 - this.entity.getYRot()))
.rotateX((float) Math.toRadians(-this.entity.getXRot()))
);
if(rollAngleStart == 0){
if (rollAngleStart == 0) {
this.returnTimer = 1;
rollable.clearRotation();
controller.reset();
return;
}
rollable.getOrientation().rotateZ((float) Math.toRadians(-rollAngleStart*(1-returnTimer)));
applyRotation();
controller.getOrientation().rotateZ((float) Math.toRadians(-rollAngleStart * (1 - returnTimer)));
cobblemon$applyRotation();
this.returnTimer += .05F;
ci.cancel();
} else {
}
else {
this.returnTimer = 1;
rollable.clearRotation();
controller.reset();
}
return;
}
if (rollable.getOrientation() == null) return;
applyRotation();
if (controller.getOrientation() == null) return;
cobblemon$applyRotation();
this.returnTimer = 0;
this.rollAngleStart = rollable.getRoll();
this.rollAngleStart = controller.getRoll();
ci.cancel();
}
@Inject(method = "setup", at = @At("HEAD"))
private void cobblemon$tickAnimationPreRenders(BlockGetter level, Entity entity, boolean detached, boolean thirdPersonReverse, float partialTick, CallbackInfo ci) {
MountedPokemonAnimationRenderController.INSTANCE.reset();
}
@WrapOperation(method = "setup", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/Camera;setPosition(DDD)V"))
public void cobblemon$positionCamera(Camera instance, double x, double y, double z, Operation<Void> original, @Local(ordinal = 1, argsOnly = true) boolean thirdPersonReverse) {
if (cobblemon$isRidingPokemon(entity)) {
Vec3 position = MountedCameraRenderer.INSTANCE.getCameraPosition(instance, entity, entity.getVehicle(), thirdPersonReverse, eyeHeightOld, eyeHeight);
if (position != null) {
setPosition(position);
return;
}
}
original.call(instance, x, y, z);
}
@Unique
private void applyRotation(){
if (!(this.entity instanceof Rollable rollable) || rollable.getOrientation() == null) return;
var newRotation = rollable.getOrientation().normal(new Matrix3f()).getNormalizedRotation(new Quaternionf());
private boolean cobblemon$isRidingPokemon(Entity entity) {
return entity.getVehicle() instanceof PokemonEntity;
}
@Unique
private void cobblemon$applyRotation() {
if (!(this.entity instanceof OrientationControllable controllable) || controllable.getOrientationController().getOrientation() == null)
return;
var controller = controllable.getOrientationController();
var newRotation = controller.getOrientation().normal(new Matrix3f()).getNormalizedRotation(new Quaternionf());
if (this.minecraft.options.getCameraType().isMirrored()) {
newRotation.rotateY((float)Math.toRadians(180));
newRotation.rotateY((float) Math.toRadians(180));
}
this.rotation.set(newRotation);
this.xRot = rollable.getPitch();
this.yRot = rollable.getYaw();
this.forwards.set(rollable.getForwardVector());
this.up.set(rollable.getUpVector());
this.left.set(rollable.getLeftVector());
this.xRot = controller.getPitch();
this.yRot = controller.getYaw();
this.forwards.set(controller.getForwardVector());
this.up.set(controller.getUpVector());
this.left.set(controller.getLeftVector());
}
@WrapOperation(method = "setup", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/Camera;move(FFF)V", ordinal = 0))
public void stopMoveIfRolling(Camera instance, float zoom, float dy, float dx, Operation<Void> original) {
Entity entity = instance.getEntity();
Entity vehicle = entity.getVehicle();
if (!(vehicle instanceof PokemonEntity) || Cobblemon.config.getViewBobTranslation()) {
original.call(instance, zoom, dy, dx);
}
}
}
@@ -0,0 +1,85 @@
/*
* 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.CobblemonRecipeCategories;
import com.cobblemon.mod.common.item.crafting.CookingPotBookCategory;
import com.cobblemon.mod.common.item.crafting.CookingPotRecipe;
import com.cobblemon.mod.common.item.crafting.CookingPotShapelessRecipe;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import net.minecraft.client.ClientRecipeBook;
import net.minecraft.client.RecipeBookCategories;
import net.minecraft.client.gui.screens.recipebook.RecipeCollection;
import net.minecraft.core.RegistryAccess;
import net.minecraft.world.item.crafting.Recipe;
import net.minecraft.world.item.crafting.RecipeHolder;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import java.util.List;
import java.util.Map;
@Mixin(ClientRecipeBook.class)
public abstract class ClientRecipeBookMixin {
@Shadow
protected static Map<RecipeBookCategories, List<List<RecipeHolder<?>>>> categorizeAndGroupRecipes(Iterable<RecipeHolder<?>> recipes) {
return null;
}
@Shadow private Map<RecipeBookCategories, List<RecipeCollection>> collectionsByTab;
@Shadow private List<RecipeCollection> allCollections;
@Inject(method = "getCategory", at = @At(value = "HEAD"), cancellable = true)
private static void addCustomCategory(RecipeHolder<?> recipe, CallbackInfoReturnable<RecipeBookCategories> cir) {
Recipe<?> recipe2 = recipe.value();
if (recipe2 instanceof CookingPotRecipe || recipe2 instanceof CookingPotShapelessRecipe) {
CookingPotBookCategory category = recipe2 instanceof CookingPotRecipe
? ((CookingPotRecipe) recipe2).getCategory()
: ((CookingPotShapelessRecipe) recipe2).category();
RecipeBookCategories var7;
switch (category) {
case MISC -> var7 = CobblemonRecipeCategories.COOKING_POT_MISC.toVanillaCategory();
case FOODS -> var7 = CobblemonRecipeCategories.COOKING_POT_FOODS.toVanillaCategory();
case MEDICINES -> var7 = CobblemonRecipeCategories.COOKING_POT_MEDICINES.toVanillaCategory();
case BAITS -> var7 = CobblemonRecipeCategories.COOKING_POT_BAITS.toVanillaCategory();
default -> throw new MatchException(null, null);
}
cir.setReturnValue(var7);
}
}
@Inject(method = "setupCollections", at = @At("RETURN"))
private void addCustomAggregateCategories(Iterable<RecipeHolder<?>> recipes, RegistryAccess registryAccess, CallbackInfo ci) {
Map<RecipeBookCategories, List<List<RecipeHolder<?>>>> map = categorizeAndGroupRecipes(recipes);
Map<RecipeBookCategories, List<RecipeCollection>> map2 = Maps.newHashMap();
ImmutableList.Builder<RecipeCollection> builder = ImmutableList.builder();
map.forEach((recipeBookCategories, list) -> {
List<RecipeCollection> collections = list.stream()
.map(listx -> new RecipeCollection(registryAccess, listx))
.peek(builder::add)
.collect(ImmutableList.toImmutableList());
map2.put(recipeBookCategories, collections);
});
RecipeBookCategories.AGGREGATE_CATEGORIES.forEach((recipeBookCategories, list) -> map2.put(recipeBookCategories, (List)list.stream().flatMap((recipeBookCategoriesx) -> ((List)map2.getOrDefault(recipeBookCategoriesx, ImmutableList.of())).stream()).collect(ImmutableList.toImmutableList())));
CobblemonRecipeCategories.Companion.getCustomAggregateCategories().forEach((recipeBookCategories, list) -> map2.put(recipeBookCategories, (List)list.stream().flatMap((recipeBookCategoriesx) -> ((List)map2.getOrDefault(recipeBookCategoriesx, ImmutableList.of())).stream()).collect(ImmutableList.toImmutableList())));
this.collectionsByTab = ImmutableMap.copyOf(map2);
this.allCollections = builder.build();
}
}
@@ -59,8 +59,21 @@ public class HumanoidModelMixin {
}
Entity vehicle = entity.getVehicle();
if (vehicle instanceof PokemonEntity && entity instanceof AbstractClientPlayer) {
MountedPlayerRenderer.INSTANCE.animate((PokemonEntity) vehicle, (AbstractClientPlayer) entity, relevantPartsByName, netHeadYaw, headPitch, ageInTicks, limbSwing, limbSwingAmount);
if (vehicle instanceof PokemonEntity pokemonEntity && entity instanceof AbstractClientPlayer) {
var shouldRotatePlayerHead = pokemonEntity.ifRidingAvailableSupply(false, (behaviour, settings, state) -> {
return behaviour.shouldRotatePlayerHead(settings, state, pokemonEntity);
});
if (!shouldRotatePlayerHead) {
netHeadYaw = 0f;
headPitch = 0f;
if (this.head != null) {
this.head.yRot = 0f;
this.head.xRot = 0f;
}
}
MountedPlayerRenderer.INSTANCE.animate(pokemonEntity, (AbstractClientPlayer) entity, relevantPartsByName, netHeadYaw, headPitch, ageInTicks, limbSwing, limbSwingAmount);
}
}
}
@@ -8,7 +8,7 @@
package com.cobblemon.mod.common.mixin.client;
import com.cobblemon.mod.common.Rollable;
import com.cobblemon.mod.common.OrientationControllable;
import com.cobblemon.mod.common.item.PokedexItem;
import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.client.Minecraft;
@@ -31,14 +31,14 @@ public class ItemInHandRendererMixin {
if (abstractClientPlayer.isUsingItem() && abstractClientPlayer.getUseItem().getItem() instanceof PokedexItem) {
ci.cancel();
}
else if (abstractClientPlayer instanceof Rollable rollable && rollable.shouldRoll()) {
else if (abstractClientPlayer instanceof OrientationControllable controllable && controllable.getOrientationController().isActive()) {
}
}
@Redirect(method = "renderHandsWithItems", at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/vertex/PoseStack;mulPose(Lorg/joml/Quaternionf;)V", ordinal = 1))
private void cobblemon$renderHandswithItems(PoseStack instance, Quaternionf quaternion) {
if (!(Minecraft.getInstance().player instanceof Rollable rollable && rollable.shouldRoll())) {
if (!(Minecraft.getInstance().player instanceof OrientationControllable controllable && controllable.getOrientationController().isActive())) {
instance.mulPose(quaternion);
}
}
@@ -12,6 +12,7 @@ import com.cobblemon.mod.common.Cobblemon;
import com.cobblemon.mod.common.ModAPI;
import com.cobblemon.mod.common.item.PokeBallItem;
import com.cobblemon.mod.common.item.PokedexItem;
import com.cobblemon.mod.common.item.WearableItem;
import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.client.renderer.ItemModelShaper;
@@ -54,17 +55,18 @@ 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;
ResourceLocation resourceLocation = null;
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 (renderMode != ItemDisplayContext.HEAD && stack.getItem() instanceof WearableItem wearableItem) resourceLocation = wearableItem.getModel2d();
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);
}
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);
}
}
}
@@ -78,6 +80,7 @@ public abstract class ItemRendererMixin {
boolean canOpenScreen = entity != null && ((entity.getOffhandItem() == stack && !(entity.getMainHandItem().getItem() instanceof PokedexItem)) || entity.getMainHandItem() == stack);
resourceLocation = pokedexItem.getType().getItemModelPath(isScanModel ? "scanning" : (canOpenScreen ? null : "off"));
}
else if (stack.getItem() instanceof WearableItem wearableItem) resourceLocation = wearableItem.getModel3d();
if (resourceLocation != null) {
BakedModel model = this.itemModelShaper.getModelManager().getModel(new ModelResourceLocation(resourceLocation, MODEL_PATH));
@@ -9,9 +9,14 @@
package com.cobblemon.mod.common.mixin.client;
import com.cobblemon.mod.common.CobblemonNetwork;
import com.cobblemon.mod.common.Rollable;
import com.cobblemon.mod.common.net.messages.server.orientation.C2SUpdateOrientationPacket;
import com.cobblemon.mod.common.OrientationControllable;
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity;
import com.cobblemon.mod.common.net.messages.server.orientation.ServerboundUpdateOrientationPacket;
import net.minecraft.client.Minecraft;
import net.minecraft.client.player.LocalPlayer;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.level.Level;
import org.joml.Matrix3f;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
@@ -20,24 +25,55 @@ import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(LocalPlayer.class)
public class LocalPlayerMixin {
public abstract class LocalPlayerMixin extends LivingEntity {
@Unique Matrix3f cobblemon$lastOrientation;
@Inject(method = "sendPosition", at = @At("TAIL"))
private void cobblemon_updateRotationMatrix(CallbackInfo ci) {
if (!(this instanceof Rollable rollable)) return;
if (rollable.getOrientation() == cobblemon$lastOrientation) return;
cobblemon$lastOrientation = rollable.getOrientation() != null ? new Matrix3f(rollable.getOrientation()) : null;
CobblemonNetwork.INSTANCE.sendToServer(new C2SUpdateOrientationPacket(rollable.getOrientation()));
protected LocalPlayerMixin(EntityType<? extends LivingEntity> entityType, Level level) {
super(entityType, level);
}
// @Inject(method = "sendPosition", at = @At("TAIL"))
// private void cobblemon$updateRotationMatrix(CallbackInfo ci) {
// if (!(this instanceof OrientationControllable controllable)) return;
// var controller = controllable.getOrientationController();
// if (!controller.isActive() || controller.getOrientation() == cobblemon$lastOrientation) return;
// cobblemon$lastOrientation = controller.getOrientation() != null ? new Matrix3f(controller.getOrientation()) : null;
// CobblemonNetwork.INSTANCE.sendToServer(new ServerboundUpdateOrientationPacket(controller.getOrientation()));
// }
@Inject(method = "tick", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/multiplayer/ClientPacketListener;send(Lnet/minecraft/network/protocol/Packet;)V"))
private void cobblemon_updateRotationMatrixPassenger(CallbackInfo ci) {
if (!(this instanceof Rollable rollable)) return;
if (rollable.getOrientation() == cobblemon$lastOrientation) return;
cobblemon$lastOrientation = rollable.getOrientation() != null ? new Matrix3f(rollable.getOrientation()) : null;
CobblemonNetwork.INSTANCE.sendToServer(new C2SUpdateOrientationPacket(rollable.getOrientation()));
private void cobblemon$updateRotationMatrixPassenger(CallbackInfo ci) {
if (!(this instanceof OrientationControllable controllable)) return;
var controller = controllable.getOrientationController();
if (!controller.isActive() || controller.getOrientation() == cobblemon$lastOrientation) return;
cobblemon$lastOrientation = controller.getOrientation() != null ? new Matrix3f(controller.getOrientation()) : null;
CobblemonNetwork.INSTANCE.sendToServer(new ServerboundUpdateOrientationPacket(controller.getOrientation()));
}
@Inject(method = "rideTick", at = @At("HEAD"))
private void cobblemon$updateOrientationControllerRideTick(CallbackInfo ci) {
if (Minecraft.getInstance().player != (Object)this) return;
if (!(this instanceof OrientationControllable controllable)) return;
var shouldUseCustomOrientation = cobblemon$shouldUseCustomOrientation((LocalPlayer)(Object)this);
controllable.getOrientationController().setActive(shouldUseCustomOrientation);
}
@Unique
private boolean cobblemon$shouldUseCustomOrientation(LocalPlayer player) {
var playerVehicle = player.getVehicle();
if (playerVehicle == null) return false;
if (!(playerVehicle instanceof PokemonEntity pokemonEntity)) return false;
return pokemonEntity.ifRidingAvailableSupply(false, (behaviour, settings, state) -> {
return behaviour.shouldRoll(settings, state, pokemonEntity);
});
}
@Override
public void stopRiding() {
super.stopRiding();
if (Minecraft.getInstance().player != (Object)this) return;
if (!(this instanceof OrientationControllable controllable)) return;
controllable.getOrientationController().setActive(false);
}
}
@@ -8,9 +8,10 @@
package com.cobblemon.mod.common.mixin.client;
import com.cobblemon.mod.common.Rollable;
import com.cobblemon.mod.common.OrientationControllable;
import com.cobblemon.mod.common.client.CobblemonClient;
import com.cobblemon.mod.common.client.keybind.keybinds.PartySendBinding;
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity;
import com.cobblemon.mod.common.pokedex.scanner.PokedexUsageContext;
import com.llamalad7.mixinextras.injector.v2.WrapWithCondition;
import com.llamalad7.mixinextras.sugar.Local;
@@ -29,9 +30,10 @@ import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
@Mixin(MouseHandler.class)
public class MouseHandlerMixin {
public abstract class MouseHandlerMixin {
@Shadow private double accumulatedScrollY;
@Shadow @Final private Minecraft minecraft;
@@ -49,7 +51,13 @@ public class MouseHandlerMixin {
@Shadow private double accumulatedDY;
@Shadow private double accumulatedScrollX;
@Shadow private double lastHandleMovementTime;
@Shadow public abstract boolean isMouseGrabbed();
@Shadow protected abstract void turnPlayer(double movementTime);
@Unique private double cobblemon$timeDelta;
@Inject(
method = "onScroll",
@@ -121,9 +129,9 @@ public class MouseHandlerMixin {
return false;
}
if (!(player instanceof Rollable rollable)) return true;
if (!(player instanceof OrientationControllable controllable)) return true;
if (!rollable.shouldRoll()) {
if (!controllable.getOrientationController().isActive()) {
xMouseSmoother.reset();
yMouseSmoother.reset();
pitchSmoother.reset();
@@ -132,68 +140,110 @@ public class MouseHandlerMixin {
return true;
}
var defaultSensitivity = this.minecraft.options.sensitivity().get() * 0.6000000238418579 + 0.20000000298023224;
var ridingSensitivity = Math.pow(defaultSensitivity, 3);
//Send mouse input to be interpreted into rotation
//deltas by the ride controller
Vec3 angVecMouse = rollable.rotationOnMouseXY(
cursorDeltaY,
cursorDeltaX ,
yMouseSmoother,
xMouseSmoother,
ridingSensitivity,
movementTime
);
Vec3 angVecMouse = cobblemon$getRideMouseRotation(cursorDeltaX, cursorDeltaY, movementTime);
//Perform Rotation using mouse influenced rotation deltas.
rollable.rotate(
controllable.getOrientationController().rotate(
(float) angVecMouse.x,
(float) angVecMouse.y,
(float) angVecMouse.z
);
//Gather and apply the current rotation deltas
var angRot = rollable.angRollVel(movementTime);
var angRot = cobblemon$getAngularVelocity(movementTime);
//Apply smoothing if requested by the controller.
//This Might be best if done by the controller itself?
if( rollable.useAngVelSmoothing() )
if(cobblemon$shouldUseAngVelSmoothing())
{
if( angRot != null ) {
var yaw = yawSmoother.getNewDeltaValue(angRot.x * 0.5f, d);
var pitch = pitchSmoother.getNewDeltaValue(angRot.y * 0.5f, d);
var roll = rollSmoother.getNewDeltaValue(angRot.z * 0.5f, d);
rollable.rotate((float) yaw, (float) pitch, (float) roll);
}
var yaw = yawSmoother.getNewDeltaValue(angRot.x * 0.5f, d);
var pitch = pitchSmoother.getNewDeltaValue(angRot.y * 0.5f, d);
var roll = rollSmoother.getNewDeltaValue(angRot.z * 0.5f, d);
controllable.getOrientationController().rotate((float) yaw, (float) pitch, (float) roll);
}
//Otherwise simply apply the smoothing
else
{
if( angRot != null ) {
rollable.rotate((float) (
angRot.x * 10 * d),
(float) (angRot.y * 10 * d),
(float) (angRot.z * 10 * d)
);
}
controllable.getOrientationController().rotate((float) (angRot.x * 10 * d), (float) (angRot.y * 10 * d), (float) (angRot.z * 10 * d));
}
return false;
}
@Inject(method = "handleAccumulatedMovement", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/MouseHandler;isMouseGrabbed()Z", ordinal = 0))
private void cobblemon$maintainMovementWhenInScreens(CallbackInfo ci, @Local(ordinal = 1) double e) {
if (minecraft.player == null) return;
if (!(minecraft.player instanceof Rollable rollable)) return;
if (!rollable.shouldRoll()) return;
if (minecraft.isPaused()) return;
@Inject(method = "handleAccumulatedMovement", at = @At("HEAD"))
private void cobblemon$maintainMovementWhenInScreens2(CallbackInfo ci) {
double time = Blaze3D.getTime();
cobblemon$timeDelta = time - this.lastHandleMovementTime;
}
var pitch = pitchSmoother.getNewDeltaValue(0, e);
var roll = rollSmoother.getNewDeltaValue(0, e);
rollable.rotate(0.0F, (float)pitch, (float)roll);
@Inject(method = "handleAccumulatedMovement", at = @At("TAIL"))
private void cobblemon$maintainMovementWhenInScreens(CallbackInfo ci) {
if (minecraft.player == null) return;
if (!(minecraft.player instanceof OrientationControllable controllable)) return;
if (!controllable.getOrientationController().isActive()) return;
if (minecraft.isPaused()) return;
if (isMouseGrabbed()) return;
this.turnPlayer(cobblemon$timeDelta);
}
@Unique
private Vec3 cobblemon$getAngularVelocity(double deltaTime) {
var player = minecraft.player;
if (player == null) return Vec3.ZERO;
if (!(player instanceof OrientationControllable)) return Vec3.ZERO;
var playerVehicle = player.getVehicle();
if (playerVehicle == null) return Vec3.ZERO;
if (!(playerVehicle instanceof PokemonEntity pokemonEntity)) return Vec3.ZERO;
return pokemonEntity.ifRidingAvailableSupply(Vec3.ZERO, (behaviour, settings, state) -> {
return behaviour.angRollVel(settings, state, pokemonEntity, player, deltaTime);
});
}
@Unique
private Vec3 cobblemon$getRideMouseRotation(double mouseX, double mouseY, double deltaTime) {
var player = minecraft.player;
if (player == null) return Vec3.ZERO;
var vehicle = player.getVehicle();
if (vehicle == null) return Vec3.ZERO;
if (!(vehicle instanceof PokemonEntity pokemonEntity)) return Vec3.ZERO;
var sensitivity = cobblemon$getRidingSensitivity();
return pokemonEntity.ifRidingAvailableSupply(Vec3.ZERO, (behaviour, settings, state) -> {
return behaviour.rotationOnMouseXY(
settings,
state,
pokemonEntity,
player,
mouseY,
mouseX,
yMouseSmoother,
xMouseSmoother,
sensitivity,
deltaTime
);
});
}
@Unique
private double cobblemon$getRidingSensitivity() {
var sensitivity = this.minecraft.options.sensitivity().get() * 0.6000000238418579 + 0.20000000298023224;
return Math.pow(sensitivity, 3);
}
@Unique
private boolean cobblemon$shouldUseAngVelSmoothing() {
var player = minecraft.player;
if (player == null) return true;
var playerVehicle = player.getVehicle();
if (playerVehicle == null) return true;
if (!(playerVehicle instanceof PokemonEntity pokemonEntity)) return true;
return pokemonEntity.ifRidingAvailableSupply(true, (behaviour, settings, state) -> {
return behaviour.useAngVelSmoothing(settings, state, pokemonEntity);
});
}
}
@@ -1,36 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.mixin.client;
import com.cobblemon.mod.common.api.riding.Rideable;
import com.cobblemon.mod.common.api.riding.RidingManager;
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity;
import net.minecraft.client.model.PlayerModel;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.player.Player;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(PlayerModel.class)
public class PlayerModelMixin {
@Inject(method = "setupAnim(Lnet/minecraft/world/entity/LivingEntity;FFFFF)V", at = @At(value = "HEAD"))
private void cobblemon$setHeadRotation(LivingEntity entity, float limbSwing, float limbSwingAmount, float ageInTicks, float netHeadYaw, float headPitch, CallbackInfo ci){
if (!(entity instanceof Player)) return;
Entity vehicle = entity.getVehicle();
if (!(vehicle instanceof PokemonEntity)) return;
RidingManager ridingManager = ((Rideable) vehicle).getRiding();
if (ridingManager.shouldRotatePlayerHead((PokemonEntity) vehicle)) return;
netHeadYaw = 0f;
headPitch = 0f;
}
}
@@ -11,9 +11,15 @@ package com.cobblemon.mod.common.mixin.client;
import com.cobblemon.mod.common.client.render.ClientPlayerIcon;
import com.cobblemon.mod.common.client.render.player.MountedPlayerRenderer;
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity;
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.client.model.EntityModel;
import net.minecraft.client.model.PlayerModel;
import net.minecraft.client.player.AbstractClientPlayer;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.entity.EntityRendererProvider;
import net.minecraft.client.renderer.entity.LivingEntityRenderer;
import net.minecraft.client.renderer.entity.player.PlayerRenderer;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.player.Player;
@@ -23,12 +29,33 @@ import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(PlayerRenderer.class)
public class PlayerRendererMixin {
public abstract class PlayerRendererMixin extends LivingEntityRenderer<AbstractClientPlayer, PlayerModel<AbstractClientPlayer>> {
public PlayerRendererMixin(EntityRendererProvider.Context context, PlayerModel<AbstractClientPlayer> model, float shadowRadius) {
super(context, model, shadowRadius);
}
@Inject(method = "render(Lnet/minecraft/world/entity/LivingEntity;FFLcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;I)V", at = @At(value = "TAIL"))
public void cobblemon$clientPlayerIcon(LivingEntity entity, float entityYaw, float partialTicks, PoseStack poseStack, MultiBufferSource buffer, int packedLight, CallbackInfo ci) {
ClientPlayerIcon.Companion.onRenderPlayer((Player) entity);
}
@WrapOperation(method = "getRenderOffset(Lnet/minecraft/client/player/AbstractClientPlayer;F)Lnet/minecraft/world/phys/Vec3;", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/player/AbstractClientPlayer;isCrouching()Z"))
private boolean cobblemon$disableCrouchOffset(AbstractClientPlayer instance, Operation<Boolean> original) {
if (instance.isPassenger() && instance.getVehicle() instanceof PokemonEntity) {
return false;
}
return original.call(instance);
}
@Inject(method = "setModelProperties", at = @At("TAIL"))
private void cobblemon$setModelProperties(AbstractClientPlayer player, CallbackInfo ci) {
if (player.isPassenger() && player.getVehicle() instanceof PokemonEntity) {
PlayerModel<AbstractClientPlayer> playerModel = this.getModel();
playerModel.crouching = false;
}
}
@Inject(
method = "setupRotations(Lnet/minecraft/client/player/AbstractClientPlayer;Lcom/mojang/blaze3d/vertex/PoseStack;FFFF)V",
at = @At("HEAD")
@@ -0,0 +1,73 @@
/*
* 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.CobblemonItems;
import com.cobblemon.mod.common.CobblemonRecipeCategories;
import com.google.common.collect.ImmutableList;
import net.minecraft.client.RecipeBookCategories;
import net.minecraft.world.inventory.RecipeBookType;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Mutable;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.gen.Invoker;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import java.util.ArrayList;
import java.util.List;
@Mixin(RecipeBookCategories.class)
public class RecipeBookCategoriesMixin {
@Final
@Mutable
@Shadow
private static RecipeBookCategories[] $VALUES;
@Invoker("<init>")
private static RecipeBookCategories cobblemon$createCategory(String name, int ordinal, ItemStack... icons) {
throw new AssertionError();
}
@Inject(
method = "<clinit>",
at = @At("TAIL")
)
private static void cobblemon$addRecipeBookType(CallbackInfo ci) {
ArrayList<RecipeBookCategories> types = new ArrayList<>(List.of($VALUES));
types.add(cobblemon$createCategory("COOKING_POT_SEARCH", $VALUES.length, new ItemStack(Items.COMPASS)));
types.add(cobblemon$createCategory("COOKING_POT_FOODS", $VALUES.length + 1, new ItemStack(CobblemonItems.ROASTED_LEEK)));
types.add(cobblemon$createCategory("COOKING_POT_MEDICINES", $VALUES.length + 2, new ItemStack(CobblemonItems.HP_UP)));
types.add(cobblemon$createCategory("COOKING_POT_BAITS", $VALUES.length + 3, new ItemStack(CobblemonItems.PERSIM_BERRY)));
types.add(cobblemon$createCategory("COOKING_POT_MISC", $VALUES.length + 4, new ItemStack(CobblemonItems.MIRROR_HERB)));
$VALUES = types.toArray(RecipeBookCategories[]::new);
}
@Inject(method = "getCategories", at = @At("HEAD"), cancellable = true)
private static void modifyCategories(RecipeBookType recipeBookType, CallbackInfoReturnable<List<RecipeBookCategories>> cir) {
if (recipeBookType == RecipeBookType.valueOf("COOKING_POT")) {
List var10000 = ImmutableList.of(
CobblemonRecipeCategories.COOKING_POT_SEARCH.toVanillaCategory(),
CobblemonRecipeCategories.COOKING_POT_FOODS.toVanillaCategory(),
CobblemonRecipeCategories.COOKING_POT_MEDICINES.toVanillaCategory(),
CobblemonRecipeCategories.COOKING_POT_BAITS.toVanillaCategory(),
CobblemonRecipeCategories.COOKING_POT_MISC.toVanillaCategory());
cir.setReturnValue(var10000);
return;
}
}
}
@@ -0,0 +1,63 @@
/*
* 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.CobblemonRecipeCategories;
import net.minecraft.client.ClientRecipeBook;
import net.minecraft.client.Minecraft;
import net.minecraft.client.RecipeBookCategories;
import net.minecraft.client.gui.screens.recipebook.RecipeBookComponent;
import net.minecraft.client.gui.screens.recipebook.RecipeBookPage;
import net.minecraft.client.gui.screens.recipebook.RecipeBookTabButton;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(RecipeBookComponent.class)
public class RecipeBookComponentMixin {
@Shadow private ClientRecipeBook book;
@Shadow protected Minecraft minecraft;
@Shadow private int width;
@Shadow private int xOffset;
@Shadow private int height;
@Shadow @Final private RecipeBookPage recipeBookPage;
@Inject(method = "updateTabs", at = @At("HEAD"), cancellable = true)
private void customUpdateTabs(CallbackInfo ci) {
RecipeBookComponent instance = (RecipeBookComponent) (Object) this;
int i = (width - 147) / 2 - xOffset - 30;
int j = (height - 166) / 2 + 3;
int k = 27;
int l = 0;
for (RecipeBookTabButton recipeBookTabButton : instance.tabButtons) {
RecipeBookCategories recipeBookCategories = recipeBookTabButton.getCategory();
if (recipeBookCategories != RecipeBookCategories.CRAFTING_SEARCH && recipeBookCategories != RecipeBookCategories.FURNACE_SEARCH && recipeBookCategories != CobblemonRecipeCategories.COOKING_POT_SEARCH.toVanillaCategory()) {
if (recipeBookTabButton.updateVisibility(book)) {
recipeBookTabButton.setPosition(i, j + 27 * l++);
recipeBookTabButton.startAnimation(minecraft);
}
} else {
recipeBookTabButton.visible = true;
recipeBookTabButton.setPosition(i, j + k * l++);
}
}
ci.cancel();
}
}
@@ -0,0 +1,40 @@
/*
* 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 net.minecraft.client.ClientRecipeBook;
import net.minecraft.client.gui.screens.recipebook.RecipeBookTabButton;
import net.minecraft.client.gui.screens.recipebook.RecipeCollection;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import java.util.List;
@Mixin(RecipeBookTabButton.class)
public class RecipeBookTabButtonMixin {
@Inject(method = "updateVisibility", at = @At("HEAD"), cancellable = true)
private void customUpdateVisibility(ClientRecipeBook recipeBook, CallbackInfoReturnable<Boolean> cir) {
RecipeBookTabButton instance = (RecipeBookTabButton) (Object) this;
List<RecipeCollection> list = recipeBook.getCollection(instance.getCategory());
boolean visible = false;
if (list != null) {
for (RecipeCollection recipeCollection : list) {
if (recipeCollection.hasKnownRecipes() && recipeCollection.hasFitting()) {
visible = true;
break;
}
}
}
instance.visible = visible;
cir.setReturnValue(visible);
}
}
@@ -0,0 +1,53 @@
/*
* 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 net.minecraft.client.gui.screens.recipebook.RecipeCollection;
import net.minecraft.stats.RecipeBook;
import net.minecraft.world.entity.player.StackedContents;
import net.minecraft.world.item.crafting.RecipeHolder;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.util.List;
import java.util.Set;
@Mixin(RecipeCollection.class)
public class RecipeCollectionMixin {
@Shadow @Final private Set<RecipeHolder<?>> fitsDimensions;
@Shadow @Final private Set<RecipeHolder<?>> craftable;
@Shadow @Final private List<RecipeHolder<?>> recipes;
@Inject(method = "canCraft", at = @At("HEAD"), cancellable = true)
private void customCanCraft(StackedContents handler, int width, int height, RecipeBook book, CallbackInfo ci) {
for (RecipeHolder<?> recipeHolder : recipes) {
boolean bl = recipeHolder.value().canCraftInDimensions(width, height) && book.contains(recipeHolder);
if (bl) {
fitsDimensions.add(recipeHolder);
} else {
fitsDimensions.remove(recipeHolder);
}
if (bl && handler.canCraft(recipeHolder.value(), null)) {
craftable.add(recipeHolder);
} else {
craftable.remove(recipeHolder);
}
}
ci.cancel();
}
}
@@ -128,6 +128,7 @@ import kotlin.reflect.jvm.isAccessible
import kotlin.reflect.jvm.javaField
import net.minecraft.client.Minecraft
import net.minecraft.commands.synchronization.SingletonArgumentInfo
import net.minecraft.core.registries.Registries
import net.minecraft.resources.ResourceKey
import net.minecraft.resources.ResourceLocation
import net.minecraft.server.level.ServerPlayer
@@ -194,6 +195,8 @@ object Cobblemon {
this.LOGGER.info(" - Branch: ${CobblemonBuildDetails.BRANCH}")
}
implementation.registerRecipeSerializers()
implementation.registerRecipeTypes()
implementation.registerPermissionValidator()
implementation.registerSoundEvents()
implementation.registerDataComponents()
@@ -202,9 +205,11 @@ object Cobblemon {
implementation.registerEntityTypes()
implementation.registerEntityAttributes()
implementation.registerBlockEntityTypes()
implementation.registerPoiTypes()
implementation.registerVillagers()
implementation.registerWorldGenFeatures()
implementation.registerParticles()
implementation.registerMenu()
implementation.registerEntityDataSerializers()
implementation.registerCriteria()
implementation.registerEntitySubPredicates()
@@ -562,6 +567,9 @@ object Cobblemon {
this.implementation.registerCommandArgument(cobblemonResource("dex"), DexArgumentType::class, SingletonArgumentInfo.contextFree (DexArgumentType::dex))
this.implementation.registerCommandArgument(cobblemonResource("npc_class"), NPCClassArgumentType::class, SingletonArgumentInfo.contextFree(NPCClassArgumentType::npcClass))
this.implementation.registerCommandArgument(cobblemonResource("wallpaper"), UnlockablePCBoxWallpaperArgumentType::class, SingletonArgumentInfo.contextFree(UnlockablePCBoxWallpaperArgumentType::wallpaper))
this.implementation.registerCommandArgument(cobblemonResource("mark"), MarkArgumentType::class, SingletonArgumentInfo.contextFree(MarkArgumentType::mark))
this.implementation.registerCommandArgument(cobblemonResource("transform_type"), TransformTypeArgumentType::class, SingletonArgumentInfo.contextFree(TransformTypeArgumentType::transformType))
this.implementation.registerCommandArgument(cobblemonResource("model_part"), ModelPartArgumentType::class, SingletonArgumentInfo.contextFree(ModelPartArgumentType::modelPart))
}
}
@@ -8,6 +8,7 @@
package com.cobblemon.mod.common
import com.cobblemon.mod.common.block.entity.PokeCakeBlockEntity
import com.cobblemon.mod.common.block.entity.BerryBlockEntity
import com.cobblemon.mod.common.block.entity.HealingMachineBlockEntity
import com.cobblemon.mod.common.block.entity.PCBlockEntity
@@ -45,9 +46,9 @@ object CobblemonBlockEntities : PlatformRegistry<Registry<BlockEntityType<*>>, R
@JvmField
val PASTURE: BlockEntityType<PokemonPastureBlockEntity> = this.create("pasture", BlockEntityType.Builder.of(::PokemonPastureBlockEntity, CobblemonBlocks.PASTURE).build(null))
@JvmField
val SIGN: BlockEntityType<CobblemonSignBlockEntity> = this.create("sign", BlockEntityType.Builder.of(::CobblemonSignBlockEntity, CobblemonBlocks.APRICORN_SIGN, CobblemonBlocks.APRICORN_WALL_SIGN).build(null))
val SIGN: BlockEntityType<CobblemonSignBlockEntity> = this.create("sign", BlockEntityType.Builder.of(::CobblemonSignBlockEntity, CobblemonBlocks.APRICORN_SIGN, CobblemonBlocks.APRICORN_WALL_SIGN, CobblemonBlocks.SACCHARINE_SIGN, CobblemonBlocks.SACCHARINE_WALL_SIGN).build(null))
@JvmField
val HANGING_SIGN: BlockEntityType<CobblemonHangingSignBlockEntity> = this.create("hanging_sign", BlockEntityType.Builder.of(::CobblemonHangingSignBlockEntity, CobblemonBlocks.APRICORN_HANGING_SIGN, CobblemonBlocks.APRICORN_WALL_HANGING_SIGN).build(null))
val HANGING_SIGN: BlockEntityType<CobblemonHangingSignBlockEntity> = this.create("hanging_sign", BlockEntityType.Builder.of(::CobblemonHangingSignBlockEntity, CobblemonBlocks.APRICORN_HANGING_SIGN, CobblemonBlocks.APRICORN_WALL_HANGING_SIGN, CobblemonBlocks.SACCHARINE_HANGING_SIGN, CobblemonBlocks.SACCHARINE_WALL_HANGING_SIGN).build(null))
@JvmField
val GILDED_CHEST: BlockEntityType<GildedChestBlockEntity> = this.create("chest", BlockEntityType.Builder.of(::GildedChestBlockEntity,
@@ -86,4 +87,36 @@ object CobblemonBlockEntities : PlatformRegistry<Registry<BlockEntityType<*>>, R
val DISPLAY_CASE: BlockEntityType<DisplayCaseBlockEntity> = this.create("display_case",
BlockEntityType.Builder.of(::DisplayCaseBlockEntity, CobblemonBlocks.DISPLAY_CASE).build(null)
)
@JvmField
val INCENSE_SWEET: BlockEntityType<SweetIncenseBlockEntity> = this.create("incense_sweet",
BlockEntityType.Builder.of(::SweetIncenseBlockEntity, CobblemonBlocks.INCENSE_SWEET).build(null)
)
@JvmField
val CAMPFIRE: BlockEntityType<CampfireBlockEntity> = this.create("campfire_pot",
BlockEntityType.Builder.of(::CampfireBlockEntity, CobblemonBlocks.CAMPFIRE).build(null)
)
/*@JvmField
val LURE_CAKE: BlockEntityType<LureCakeBlockEntity> =
BlockEntityType.Builder.of({ pos, state -> LureCakeBlockEntity(pos, state) },
CobblemonBlocks.LURE_CAKE
).build(null)*/
@JvmField
val LURE_CAKE: BlockEntityType<LureCakeBlockEntity> = this.create(
"lure_cake",
BlockEntityType.Builder.of(::LureCakeBlockEntity, CobblemonBlocks.LURE_CAKE).build(null)
)
@JvmField
val POKE_CAKE: BlockEntityType<PokeCakeBlockEntity> = this.create(
"poke_cake",
BlockEntityType.Builder.of(::PokeCakeBlockEntity, CobblemonBlocks.POKE_CAKE).build(null)
)
@JvmField
val CANDLE_POKE_CAKE: BlockEntityType<CandlePokeCakeBlockEntity> = this.create(
"candle_poke_cake",
BlockEntityType.Builder.of(::CandlePokeCakeBlockEntity, CobblemonBlocks.CANDLE_POKE_CAKE).build(null)
)
}
@@ -10,8 +10,10 @@ package com.cobblemon.mod.common
import com.cobblemon.mod.common.api.apricorn.Apricorn
import com.cobblemon.mod.common.block.*
import com.cobblemon.mod.common.block.campfirepot.CampfireBlock
import com.cobblemon.mod.common.block.LecternBlock
import com.cobblemon.mod.common.block.MintBlock.MintType
import com.cobblemon.mod.common.block.campfirepot.CampfirePotBlock
import com.cobblemon.mod.common.block.chest.GildedChestBlock
import com.cobblemon.mod.common.block.sign.CobblemonHangingSignBlock
import com.cobblemon.mod.common.block.sign.CobblemonSignBlock
@@ -20,6 +22,7 @@ import com.cobblemon.mod.common.block.sign.CobblemonWallSignBlock
import com.cobblemon.mod.common.mixin.invoker.*
import com.cobblemon.mod.common.platform.PlatformRegistry
import com.cobblemon.mod.common.util.cobblemonResource
import net.minecraft.core.BlockPos
import net.minecraft.core.Registry
import net.minecraft.core.registries.BuiltInRegistries
import net.minecraft.core.registries.Registries
@@ -27,9 +30,13 @@ import net.minecraft.resources.ResourceKey
import net.minecraft.resources.ResourceLocation
import net.minecraft.util.valueproviders.UniformInt
import net.minecraft.world.effect.MobEffects
import net.minecraft.world.entity.EntityType
import net.minecraft.world.level.BlockGetter
import net.minecraft.world.level.block.*
import net.minecraft.world.level.block.state.BlockBehaviour
import net.minecraft.world.level.block.state.BlockState
import net.minecraft.world.level.block.state.properties.BlockSetType
import net.minecraft.world.level.block.state.properties.BlockStateProperties.LIT
import net.minecraft.world.level.block.state.properties.NoteBlockInstrument
import net.minecraft.world.level.block.state.properties.WoodType
import net.minecraft.world.level.material.MapColor
@@ -43,6 +50,8 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
val APRICORN_BLOCK_SET_TYPE = BlockSetType("apricorn")
val APRICORN_WOOD_TYPE = WoodType.register(WoodType("apricorn", APRICORN_BLOCK_SET_TYPE))
val SACCHARINE_BLOCK_SET_TYPE = BlockSetType("saccharine")
val SACCHARINE_WOOD_TYPE = WoodType.register(WoodType("saccharine", SACCHARINE_BLOCK_SET_TYPE))
// Evolution Ores
@JvmField
@@ -159,15 +168,80 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
@JvmField
val YELLOW_APRICORN_SAPLING = this.create("yellow_apricorn_sapling", ApricornSaplingBlock(PLANT_PROPERTIES, Apricorn.YELLOW))
// Saccharines
@JvmField
val SACCHARINE_LOG = this.create("saccharine_log", SaccharineLogBlock(BlockBehaviour.Properties.of().mapColor(MapColor.COLOR_BLUE).instrument(NoteBlockInstrument.BASS).strength(2.0F).sound(SoundType.WOOD).ignitedByLava()))
@JvmField
val SACCHARINE_HONEY_LOG = this.create("saccharine_honey_log", SaccharineHoneyLogBlock(BlockBehaviour.Properties.of().mapColor(MapColor.COLOR_BLUE).instrument(NoteBlockInstrument.BASS).strength(2.0F).sound(SoundType.WOOD).ignitedByLava()))
@JvmField
val STRIPPED_SACCHARINE_LOG = this.create("stripped_saccharine_log", SaccharineStrippedLogBlock(BlockBehaviour.Properties.of().mapColor(MapColor.COLOR_LIGHT_BLUE).instrument(NoteBlockInstrument.BASS).strength(2.0F).sound(SoundType.WOOD).ignitedByLava())) //log("stripped_saccharine_log")
@JvmField
val SACCHARINE_WOOD = log("saccharine_wood")
@JvmField
val STRIPPED_SACCHARINE_WOOD = this.create("stripped_saccharine_wood", SaccharineStrippedLogBlock(BlockBehaviour.Properties.of().mapColor(MapColor.COLOR_LIGHT_BLUE).instrument(NoteBlockInstrument.BASS).strength(2.0F).sound(SoundType.WOOD).ignitedByLava())) //log("stripped_saccharine_log")
@JvmField
val SACCHARINE_PLANKS = this.create("saccharine_planks", Block(BlockBehaviour.Properties.of().mapColor(MapColor.COLOR_LIGHT_BLUE).instrument(NoteBlockInstrument.BASS).strength(2.0f, 3.0f).sound(SoundType.WOOD)))
@JvmField
val SACCHARINE_LEAVES = this.create("saccharine_leaves", SaccharineLeafBlock(
BlockBehaviour.Properties.of().mapColor(
MapColor.PLANT
).strength(0.2f).randomTicks().sound(SoundType.GRASS).noOcclusion()
.isValidSpawn { _: BlockState?, _: BlockGetter?, _: BlockPos?, entity: EntityType<*>? ->
entity === EntityType.OCELOT || entity === EntityType.PARROT
}.isSuffocating { _: BlockState?, _: BlockGetter?, _: BlockPos? ->
false
}.isViewBlocking { _: BlockState?, _: BlockGetter?, _: BlockPos? ->
false
}.ignitedByLava().pushReaction(PushReaction.DESTROY)
.isRedstoneConductor { _: BlockState?, _: BlockGetter?, _: BlockPos? ->
false
}))
@JvmField
val SACCHARINE_FENCE = this.create("saccharine_fence", FenceBlock(BlockBehaviour.Properties.of().mapColor(SACCHARINE_PLANKS.defaultMapColor()).instrument(NoteBlockInstrument.BASS).strength(2.0f, 3.0f).sound(SoundType.WOOD)))
@JvmField
val SACCHARINE_FENCE_GATE = this.create("saccharine_fence_gate", FenceGateBlock(SACCHARINE_WOOD_TYPE, BlockBehaviour.Properties.of().mapColor(SACCHARINE_PLANKS.defaultMapColor()).instrument(NoteBlockInstrument.BASS).strength(2.0f, 3.0f).sound(SoundType.WOOD)))
val SACCHARINE_BUTTON = this.create("saccharine_button", BlocksInvoker.createWoodenButtonBlock(BlockSetType.OAK))
@JvmField
val SACCHARINE_PRESSURE_PLATE = this.create("saccharine_pressure_plate", PressurePlateBlockInvoker.`cobblemon$create`(SACCHARINE_BLOCK_SET_TYPE, BlockBehaviour.Properties.of().mapColor(SACCHARINE_PLANKS.defaultMapColor()).instrument(NoteBlockInstrument.BASS).noCollission().strength(0.5f).sound(SoundType.WOOD)))
@JvmField
val SACCHARINE_SIGN = this.create("saccharine_sign", CobblemonSignBlock(BlockBehaviour.Properties.ofFullCopy(Blocks.OAK_SIGN), SACCHARINE_WOOD_TYPE))
@JvmField
val SACCHARINE_WALL_SIGN = this.create("saccharine_wall_sign", CobblemonWallSignBlock(BlockBehaviour.Properties.ofFullCopy(Blocks.OAK_WALL_SIGN), SACCHARINE_WOOD_TYPE))
@JvmField
val SACCHARINE_HANGING_SIGN = this.create("saccharine_hanging_sign", CobblemonHangingSignBlock(BlockBehaviour.Properties.ofFullCopy(Blocks.OAK_WALL_HANGING_SIGN), SACCHARINE_WOOD_TYPE))
@JvmField
val SACCHARINE_WALL_HANGING_SIGN = this.create("saccharine_wall_hanging_sign", CobblemonWallHangingSignBlock(BlockBehaviour.Properties.ofFullCopy(Blocks.OAK_HANGING_SIGN), SACCHARINE_WOOD_TYPE))
@JvmField
val SACCHARINE_SLAB = this.create("saccharine_slab", SlabBlock(BlockBehaviour.Properties.of().mapColor(MapColor.WOOD).instrument(NoteBlockInstrument.BASS).strength(2.0f, 3.0f).sound(SoundType.WOOD)))
@JvmField
val SACCHARINE_STAIRS = this.create("saccharine_stairs", StairsBlockInvoker.`cobblemon$create`(SACCHARINE_PLANKS.defaultBlockState(), BlockBehaviour.Properties.ofFullCopy(SACCHARINE_PLANKS)))
@JvmField
val SACCHARINE_DOOR = this.create("saccharine_door", DoorBlockInvoker.`cobblemon$create`(SACCHARINE_BLOCK_SET_TYPE, BlockBehaviour.Properties.of().mapColor(SACCHARINE_PLANKS.defaultMapColor()).instrument(NoteBlockInstrument.BASS).strength(3.0F).sound(SoundType.WOOD).noOcclusion()))
@JvmField
val SACCHARINE_TRAPDOOR = this.create("saccharine_trapdoor", TrapdoorBlockInvoker.`cobblemon$create`(SACCHARINE_BLOCK_SET_TYPE, BlockBehaviour.Properties.of().mapColor(MapColor.WOOD).instrument(NoteBlockInstrument.BASS).strength(3.0F).sound(SoundType.WOOD).noOcclusion()))
@JvmField
val SACCHARINE_SAPLING = this.create("saccharine_sapling", SaccharineSaplingBlock(PLANT_PROPERTIES))
@JvmField
val MEDICINAL_LEEK = this.create("medicinal_leek", MedicinalLeekBlock(BlockBehaviour.Properties.of().pushReaction(PushReaction.DESTROY).ignitedByLava().mapColor(MapColor.CRIMSON_NYLIUM).noCollission().randomTicks().instabreak().sound(CobblemonSounds.MEDICINAL_LEEK_SOUNDS)))
@JvmField
val BUGWORT = this.create("bugwort", BugwortBlock(BlockBehaviour.Properties.of().pushReaction(PushReaction.DESTROY).ignitedByLava().mapColor(MapColor.COLOR_PURPLE).noCollission().randomTicks().instabreak().sound(CobblemonSounds.MEDICINAL_LEEK_SOUNDS)))
@JvmField
val ENERGY_ROOT = this.create("energy_root", EnergyRootBlock(BlockBehaviour.Properties.of().pushReaction(PushReaction.DESTROY).ignitedByLava().mapColor(MapColor.DIRT).noCollission().randomTicks().instabreak().sound(CobblemonSounds.ENERGY_ROOT_SOUNDS)))
@JvmField
val BIG_ROOT = this.create("big_root", BigRootBlock(BlockBehaviour.Properties.of().pushReaction(PushReaction.DESTROY).ignitedByLava().mapColor(MapColor.PLANT).noCollission().randomTicks().instabreak().sound(CobblemonSounds.BIG_ROOT_SOUNDS)))
@JvmField
val REVIVAL_HERB = this.create("revival_herb", RevivalHerbBlock(BlockBehaviour.Properties.of().pushReaction(PushReaction.DESTROY).mapColor(MapColor.PLANT).ignitedByLava().noCollission().instabreak().sound(CobblemonSounds.REVIVAL_HERB_SOUNDS)))
@JvmField
val LURE_CAKE = this.create("lure_cake", LureCakeBlock(BlockBehaviour.Properties.of().forceSolidOn().strength(0.5F).sound(SoundType.WOOL).pushReaction(PushReaction.DESTROY)))
@JvmField
val POKE_CAKE = this.create("poke_cake", PokeCakeBlock(BlockBehaviour.Properties.ofFullCopy(LURE_CAKE)))
@JvmField
val CANDLE_POKE_CAKE = this.create("candle_poke_cake", CandlePokeCakeBlock(BlockBehaviour.Properties.ofFullCopy(LURE_CAKE).lightLevel { blockState -> if (blockState.getValue(LIT) == true) 3 else 0 }))
@JvmField
val TUMBLESTONE_CLUSTER = tumblestoneBlock("tumblestone_cluster", GrowableStoneBlock.STAGE_3, 7, 3, null)
@JvmField
@@ -319,6 +393,60 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
@JvmField
val YELLOW_APRICORN = apricornBlock("yellow_apricorn", Apricorn.YELLOW)
@JvmField
val BLACK_CAMPFIRE_POT = create("campfire_pot_black",
CampfirePotBlock(
BlockBehaviour.Properties.of().mapColor(MapColor.COLOR_BLACK).sound(CobblemonSounds.CAMPFIRE_POT_SOUNDS)
.strength(0.5F).pushReaction(PushReaction.BLOCK).noOcclusion()
)
)
@JvmField
val BLUE_CAMPFIRE_POT = create("campfire_pot_blue",
CampfirePotBlock(
BlockBehaviour.Properties.of().mapColor(MapColor.COLOR_BLUE).sound(CobblemonSounds.CAMPFIRE_POT_SOUNDS)
.strength(0.5F).pushReaction(PushReaction.BLOCK).noOcclusion()
)
)
@JvmField
val GREEN_CAMPFIRE_POT = create("campfire_pot_green",
CampfirePotBlock(
BlockBehaviour.Properties.of().mapColor(MapColor.COLOR_GREEN).sound(CobblemonSounds.CAMPFIRE_POT_SOUNDS)
.strength(0.5F).pushReaction(PushReaction.BLOCK).noOcclusion()
)
)
@JvmField
val PINK_CAMPFIRE_POT = create("campfire_pot_pink",
CampfirePotBlock(
BlockBehaviour.Properties.of().mapColor(MapColor.COLOR_PINK).sound(CobblemonSounds.CAMPFIRE_POT_SOUNDS)
.strength(0.5F).pushReaction(PushReaction.BLOCK).noOcclusion()
)
)
@JvmField
val RED_CAMPFIRE_POT = create("campfire_pot_red",
CampfirePotBlock(
BlockBehaviour.Properties.of().mapColor(MapColor.COLOR_RED).sound(CobblemonSounds.CAMPFIRE_POT_SOUNDS)
.strength(0.5F).pushReaction(PushReaction.BLOCK).noOcclusion()
)
)
@JvmField
val WHITE_CAMPFIRE_POT = create("campfire_pot_white",
CampfirePotBlock(
BlockBehaviour.Properties.of().mapColor(MapColor.COLOR_LIGHT_GRAY)
.sound(CobblemonSounds.CAMPFIRE_POT_SOUNDS).strength(0.5F).pushReaction(PushReaction.BLOCK)
.noOcclusion()
)
)
@JvmField
val YELLOW_CAMPFIRE_POT = create("campfire_pot_yellow",
CampfirePotBlock(
BlockBehaviour.Properties.of().mapColor(MapColor.COLOR_YELLOW).sound(CobblemonSounds.CAMPFIRE_POT_SOUNDS)
.strength(0.5F).pushReaction(PushReaction.BLOCK).noOcclusion()
)
)
@JvmField
val CAMPFIRE = create("campfire", CampfireBlock(BlockBehaviour.Properties.of().sound(SoundType.WOOD).noOcclusion().pushReaction(PushReaction.BLOCK).mapColor(MapColor.PODZOL).strength(2.0F).lightLevel { if ((it.getValue(CampfireBlock.SOUL) as Boolean)) 9 else 14 }))
@JvmField
val RELIC_COIN_POUCH = create("relic_coin_pouch", CoinPouchBlock(BlockBehaviour.Properties.of().sound(CobblemonSounds.RELIC_COIN_POUCH_SOUNDS).pushReaction(PushReaction.DESTROY).noOcclusion(), true))
@JvmField
@@ -360,6 +488,9 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
@JvmField
val DISPLAY_CASE = create("display_case", DisplayCaseBlock(BlockBehaviour.Properties.of().sound(CobblemonSounds.DISPLAY_CASE_SOUNDS).noOcclusion().pushReaction(PushReaction.BLOCK).mapColor(MapColor.STONE).strength(0.3F)))
@JvmField
val INCENSE_SWEET = create("incense_sweet", SweetIncenseBlock(BlockBehaviour.Properties.of().sound(CobblemonSounds.DISPLAY_CASE_SOUNDS).noOcclusion().pushReaction(PushReaction.BLOCK).mapColor(MapColor.STONE).strength(0.3f)))
@JvmField
val PASTURE = create("pasture", PastureBlock(BlockBehaviour.Properties.of().mapColor(MapColor.COLOR_BROWN).sound(SoundType.WOOD).strength(2F).noOcclusion().pushReaction(PushReaction.BLOCK).lightLevel { if ((it.getValue(PastureBlock.ON) as Boolean) && (it.getValue(PastureBlock.PART) == PastureBlock.PasturePart.TOP)) 10 else 0 }))
@@ -381,6 +512,8 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
val PEP_UP_FLOWER = this.create("pep_up_flower", FlowerBlock(MobEffects.LEVITATION, 10F, BlockBehaviour.Properties.of().mapColor(MapColor.PLANT).noCollission().instabreak().sound(SoundType.GRASS).offsetType(BlockBehaviour.OffsetType.XZ).pushReaction(PushReaction.DESTROY)))
@JvmField
val POTTED_PEP_UP_FLOWER = this.create("potted_pep_up_flower", BlocksInvoker.createFlowerPotBlock(PEP_UP_FLOWER))
@JvmField
val HEARTY_GRAINS = this.create("hearty_grains", HeartyGrainsBlock(BlockBehaviour.Properties.of().pushReaction(PushReaction.DESTROY).ignitedByLava().mapColor(MapColor.PLANT).noCollission().randomTicks().instabreak().sound(CobblemonSounds.VIVICHOKE_SOUNDS)))
/**
* Returns a map of all the blocks that can be stripped with an axe in the format of input - output.
@@ -389,7 +522,10 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
*/
fun strippedBlocks(): Map<Block, Block> = mapOf(
APRICORN_WOOD to STRIPPED_APRICORN_WOOD,
APRICORN_LOG to STRIPPED_APRICORN_LOG
APRICORN_LOG to STRIPPED_APRICORN_LOG,
SACCHARINE_WOOD to STRIPPED_SACCHARINE_WOOD,
SACCHARINE_LOG to STRIPPED_SACCHARINE_LOG,
SACCHARINE_HONEY_LOG to STRIPPED_SACCHARINE_LOG
)
@@ -23,8 +23,9 @@ object CobblemonCommands {
ChangeEyeHeight.register(dispatcher)
ChangeScaleAndSize.register(dispatcher)
ChangeWalkSpeed.register(dispatcher)
ChangeJointScaleCommand.register(dispatcher)
TransformModelPartCommand.register(dispatcher)
TestCommand.register(dispatcher)
ReloadShowdownCommand.register(dispatcher)
ClickTextCommand.register(dispatcher)
PokemonEditCommand.register(dispatcher)
TeachCommand.register(dispatcher)
@@ -59,12 +60,17 @@ object CobblemonCommands {
RenameBoxCommand.register(dispatcher)
ChangeBoxWallpaperCommand.register(dispatcher)
RunMolangScriptCommand.register(dispatcher)
SpectateBattleCommand.register(dispatcher)
CobblemonConfigCommand.register(dispatcher)
UnlockPCBoxWallpaperCommand.register(dispatcher)
ChangePCBoxesCommand.register(dispatcher)
MarkGiveCommand.register(dispatcher)
MarkTakeCommand.register(dispatcher)
MarkGiveAllCommand.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
CobblemonInfoCommand.register(dispatcher)
CalculateSeatPositionCommand.register(dispatcher)
}
}
}
@@ -94,12 +94,17 @@ interface CobblemonImplementation {
*/
fun registerBlockEntityTypes()
fun registerPoiTypes()
/**
* TODO
*
*/
fun registerVillagers()
fun registerRecipeSerializers()
fun registerRecipeTypes()
/**
* TODO
*
@@ -108,6 +113,8 @@ interface CobblemonImplementation {
fun registerParticles()
fun registerMenu()
fun registerEntitySubPredicates()
@@ -8,9 +8,13 @@
package com.cobblemon.mod.common
import com.cobblemon.mod.common.block.PotComponent
import com.cobblemon.mod.common.item.components.BaitEffectsComponent
import com.cobblemon.mod.common.item.components.FlavourComponent
import com.cobblemon.mod.common.item.components.FoodColourComponent
import com.cobblemon.mod.common.item.components.HeldItemCapableComponent
import com.cobblemon.mod.common.item.components.PokemonItemComponent
import com.cobblemon.mod.common.item.RodBaitComponent
import com.cobblemon.mod.common.item.components.RodBaitComponent
import com.cobblemon.mod.common.platform.PlatformRegistry
import net.minecraft.core.Registry
import net.minecraft.core.component.DataComponentType
@@ -36,11 +40,34 @@ object CobblemonItemComponents : PlatformRegistry<Registry<DataComponentType<*>>
.networkSynchronized(RodBaitComponent.PACKET_CODEC)
.build())
val POT_DATA: DataComponentType<PotComponent> = create("cooking_pot_item", DataComponentType.builder<PotComponent>()
.persistent(PotComponent.CODEC)
.networkSynchronized(PotComponent.PACKET_CODEC)
.build())
val BAIT_EFFECTS: DataComponentType<BaitEffectsComponent> = create("bait_effects", DataComponentType.builder<BaitEffectsComponent>()
.persistent(BaitEffectsComponent.CODEC)
.networkSynchronized(BaitEffectsComponent.PACKET_CODEC)
.build())
val FLAVOUR: DataComponentType<FlavourComponent> = create("flavour", DataComponentType.builder<FlavourComponent>()
.persistent(FlavourComponent.CODEC)
.networkSynchronized(FlavourComponent.PACKET_CODEC)
.build())
val FOOD_COLOUR: DataComponentType<FoodColourComponent> = create("food_colour", DataComponentType.builder<FoodColourComponent>()
.persistent(FoodColourComponent.CODEC)
.networkSynchronized(FoodColourComponent.PACKET_CODEC)
.build())
fun register() {
Registry.register(BuiltInRegistries.DATA_COMPONENT_TYPE, ResourceLocation.parse("cobblemon:pokemon_item"), POKEMON_ITEM)
Registry.register(BuiltInRegistries.DATA_COMPONENT_TYPE, ResourceLocation.parse("cobblemon:bait"), BAIT)
Registry.register(BuiltInRegistries.DATA_COMPONENT_TYPE, ResourceLocation.parse("cobblemon:cooking_pot_item"), POT_DATA)
Registry.register(BuiltInRegistries.DATA_COMPONENT_TYPE, ResourceLocation.parse("cobblemon:bait_effects"), BAIT_EFFECTS)
Registry.register(BuiltInRegistries.DATA_COMPONENT_TYPE, ResourceLocation.parse("cobblemon:flavour"), FLAVOUR)
Registry.register(BuiltInRegistries.DATA_COMPONENT_TYPE, ResourceLocation.parse("cobblemon:food_colour"), FOOD_COLOUR)
}
override val registry = BuiltInRegistries.DATA_COMPONENT_TYPE
@@ -8,6 +8,7 @@
package com.cobblemon.mod.common
import com.cobblemon.mod.common.api.apricorn.Apricorn
import com.cobblemon.mod.common.api.item.ability.AbilityChanger
import com.cobblemon.mod.common.api.mulch.MulchVariant
import com.cobblemon.mod.common.api.pokeball.PokeBalls
@@ -26,9 +27,14 @@ import com.cobblemon.mod.common.item.armor.CobblemonArmorTrims
import com.cobblemon.mod.common.item.battle.DireHitItem
import com.cobblemon.mod.common.item.battle.GuardSpecItem
import com.cobblemon.mod.common.item.battle.XStatItem
import com.cobblemon.mod.common.item.berry.*
import com.cobblemon.mod.common.item.berry.BerryItem
import com.cobblemon.mod.common.item.berry.FriendshipRaisingBerryItem
import com.cobblemon.mod.common.item.berry.HealingBerryItem
import com.cobblemon.mod.common.item.berry.PPRestoringBerryItem
import com.cobblemon.mod.common.item.berry.PortionHealingBerryItem
import com.cobblemon.mod.common.item.berry.StatusCuringBerryItem
import com.cobblemon.mod.common.item.berry.VolatileCuringBerryItem
import com.cobblemon.mod.common.item.interactive.*
import com.cobblemon.mod.common.item.interactive.PotionItem
import com.cobblemon.mod.common.item.interactive.ability.AbilityChangeItem
import com.cobblemon.mod.common.platform.PlatformRegistry
import com.cobblemon.mod.common.pokeball.PokeBall
@@ -44,7 +50,14 @@ import net.minecraft.world.effect.MobEffectInstance
import net.minecraft.world.effect.MobEffects
import net.minecraft.world.entity.LivingEntity
import net.minecraft.world.food.FoodProperties
import net.minecraft.world.item.*
import net.minecraft.world.item.BlockItem
import net.minecraft.world.item.HangingSignItem
import net.minecraft.world.item.Item
import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.Items
import net.minecraft.world.item.Rarity
import net.minecraft.world.item.SignItem
import net.minecraft.world.item.SmithingTemplateItem
import net.minecraft.world.level.Level
import net.minecraft.world.level.block.Block
@@ -171,6 +184,25 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
@JvmField
val POKEDEX_WHITE = pokedexItem(PokedexType.WHITE)
val campfire_pots = mutableListOf<CampfirePotItem>()
@JvmField
val CAMPFIRE_POT_BLACK = campfirePotItem(CobblemonBlocks.BLACK_CAMPFIRE_POT, "black")
@JvmField
val CAMPFIRE_POT_BLUE = campfirePotItem(CobblemonBlocks.BLUE_CAMPFIRE_POT, "blue")
@JvmField
val CAMPFIRE_POT_GREEN = campfirePotItem(CobblemonBlocks.GREEN_CAMPFIRE_POT, "green")
@JvmField
val CAMPFIRE_POT_PINK = campfirePotItem(CobblemonBlocks.PINK_CAMPFIRE_POT, "pink")
@JvmField
val CAMPFIRE_POT_RED = campfirePotItem(CobblemonBlocks.RED_CAMPFIRE_POT, "red")
@JvmField
val CAMPFIRE_POT_WHITE = campfirePotItem(CobblemonBlocks.WHITE_CAMPFIRE_POT, "white")
@JvmField
val CAMPFIRE_POT_YELLOW = campfirePotItem(CobblemonBlocks.YELLOW_CAMPFIRE_POT, "yellow")
@JvmField
val Hearty_Grains = compostableItem("hearty_grains", HeartyGrainsItem(CobblemonBlocks.HEARTY_GRAINS))
@JvmField
val VIVICHOKE = compostableItem("vivichoke")
@@ -261,6 +293,321 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
@JvmField
val GIMMIGHOUL_CHEST = this.create("gimmighoul_chest", BlockItem(CobblemonBlocks.GIMMIGHOUL_CHEST, Item.Properties()))
// Saccharines
@JvmField
val SACCHARINE_LOG = blockItem("saccharine_log", CobblemonBlocks.SACCHARINE_LOG)
@JvmField
val SACCHARINE_HONEY_LOG = blockItem("saccharine_honey_log", CobblemonBlocks.SACCHARINE_HONEY_LOG)
@JvmField
val STRIPPED_SACCHARINE_LOG = blockItem("stripped_saccharine_log", CobblemonBlocks.STRIPPED_SACCHARINE_LOG)
@JvmField
val SACCHARINE_WOOD = blockItem("saccharine_wood", CobblemonBlocks.SACCHARINE_WOOD)
@JvmField
val STRIPPED_SACCHARINE_WOOD = blockItem("stripped_saccharine_wood", CobblemonBlocks.STRIPPED_SACCHARINE_WOOD)
@JvmField
val SACCHARINE_PLANKS = blockItem("saccharine_planks", CobblemonBlocks.SACCHARINE_PLANKS)
@JvmField
val SACCHARINE_LEAVES = compostableBlockItem("saccharine_leaves", CobblemonBlocks.SACCHARINE_LEAVES)
@JvmField
val SACCHARINE_BOAT = create("saccharine_boat", CobblemonBoatItem(CobblemonBoatType.SACCHARINE, false, Item.Properties().stacksTo(1)))
@JvmField
val SACCHARINE_CHEST_BOAT = create("saccharine_chest_boat", CobblemonBoatItem(CobblemonBoatType.SACCHARINE, true, Item.Properties().stacksTo(1)))
@JvmField
val SACCHARINE_DOOR = blockItem("saccharine_door", CobblemonBlocks.SACCHARINE_DOOR)
@JvmField
val SACCHARINE_TRAPDOOR = blockItem("saccharine_trapdoor", CobblemonBlocks.SACCHARINE_TRAPDOOR)
@JvmField
val SACCHARINE_FENCE = blockItem("saccharine_fence", CobblemonBlocks.SACCHARINE_FENCE)
@JvmField
val SACCHARINE_FENCE_GATE = blockItem("saccharine_fence_gate", CobblemonBlocks.SACCHARINE_FENCE_GATE)
@JvmField
val SACCHARINE_BUTTON = blockItem("saccharine_button", CobblemonBlocks.SACCHARINE_BUTTON)
@JvmField
val SACCHARINE_PRESSURE_PLATE = blockItem("saccharine_pressure_plate", CobblemonBlocks.SACCHARINE_PRESSURE_PLATE)
@JvmField
val SACCHARINE_SLAB = blockItem("saccharine_slab", CobblemonBlocks.SACCHARINE_SLAB)
@JvmField
val SACCHARINE_STAIRS = blockItem("saccharine_stairs", CobblemonBlocks.SACCHARINE_STAIRS)
@JvmField
val SACCHARINE_SIGN = this.create("saccharine_sign", SignItem(Item.Properties().stacksTo(16), CobblemonBlocks.SACCHARINE_SIGN, CobblemonBlocks.SACCHARINE_WALL_SIGN))
@JvmField
val SACCHARINE_HANGING_SIGN = this.create("saccharine_hanging_sign", HangingSignItem(CobblemonBlocks.SACCHARINE_HANGING_SIGN, CobblemonBlocks.SACCHARINE_WALL_HANGING_SIGN, Item.Properties().stacksTo(16)))
@JvmField
val SACCHARINE_SAPLING = saccharineSaplingItem("saccharine_sapling", SaccharineSaplingItem(CobblemonBlocks.SACCHARINE_SAPLING))
@JvmField
val BUGWORT = bugwortItem("bugwort", BugwortItem(CobblemonBlocks.BUGWORT))
@JvmField
val POKE_BAIT = noSettingsItem("poke_bait")
@JvmField
val LURE_CAKE = blockItem("lure_cake", CobblemonBlocks.LURE_CAKE)
@JvmField
val POKE_CAKE = blockItem("poke_cake", CobblemonBlocks.POKE_CAKE)
val aprijuices = mutableListOf<AprijuiceItem>()
@JvmField
val APRIJUICE_BLACK = aprijuiceItem(Apricorn.BLACK)
@JvmField
val APRIJUICE_RED = aprijuiceItem(Apricorn.RED)
@JvmField
val APRIJUICE_BLUE = aprijuiceItem(Apricorn.BLUE)
@JvmField
val APRIJUICE_GREEN = aprijuiceItem(Apricorn.GREEN)
@JvmField
val APRIJUICE_YELLOW = aprijuiceItem(Apricorn.YELLOW)
@JvmField
val APRIJUICE_WHITE = aprijuiceItem(Apricorn.WHITE)
@JvmField
val APRIJUICE_PINK = aprijuiceItem(Apricorn.PINK)
@JvmField
val POKE_PUFF = noSettingsItem("poke_puff") // todo make a PokePuffItem class for friendship boosting purposes
// FOODS
@JvmField
val SWEET_HEART = noSettingsItem("sweet_heart") // todo make a SweetHeartItem class for breeding purposes
@JvmField
val PEWTER_CRUNCHIES = create("pewter_crunchies", object : Item(Properties().stacksTo(16) // todo add all the effects and/or an item class for it for special interactions?
.food(FoodProperties.Builder()
.nutrition(10)
.saturationModifier(1.2F)
.effect(MobEffectInstance(MobEffects.ABSORPTION, 900, 0), 1F)
.alwaysEdible()
.build())) {
override fun finishUsingItem(stack: ItemStack, world: Level, user: LivingEntity): ItemStack {
user.removeAllEffects()
return super.finishUsingItem(stack, world, user)
}
})
@JvmField
val RAGE_CANDY_BAR = create("rage_candy_bar", object : Item(Properties().stacksTo(16) // todo add all the effects and/or an item class for it for special interactions?
.food(FoodProperties.Builder()
.nutrition(10)
.saturationModifier(1.2F)
.effect(MobEffectInstance(MobEffects.ABSORPTION, 900, 0), 1F)
.alwaysEdible()
.build())) {
override fun finishUsingItem(stack: ItemStack, world: Level, user: LivingEntity): ItemStack {
user.removeAllEffects()
return super.finishUsingItem(stack, world, user)
}
})
@JvmField
val LAVA_COOKIE = create("lava_cookie", object : Item(Properties().stacksTo(16) // todo add all the effects and/or an item class for it for special interactions?
.food(FoodProperties.Builder()
.nutrition(10)
.saturationModifier(1.2F)
.effect(MobEffectInstance(MobEffects.ABSORPTION, 900, 0), 1F)
.alwaysEdible()
.build())) {
override fun finishUsingItem(stack: ItemStack, world: Level, user: LivingEntity): ItemStack {
user.removeAllEffects()
return super.finishUsingItem(stack, world, user)
}
})
@JvmField
val OLD_GATEAU = create("old_gateau", object : Item(Properties().stacksTo(16) // todo add all the effects and/or an item class for it for special interactions?
.food(FoodProperties.Builder()
.nutrition(10)
.saturationModifier(1.2F)
.effect(MobEffectInstance(MobEffects.ABSORPTION, 900, 0), 1F)
.alwaysEdible()
.build())) {
override fun finishUsingItem(stack: ItemStack, world: Level, user: LivingEntity): ItemStack {
user.removeAllEffects()
return super.finishUsingItem(stack, world, user)
}
})
@JvmField
val CASTELIACONE = create("casteliacone", object : Item(Properties().stacksTo(16) // todo add all the effects and/or an item class for it for special interactions?
.food(FoodProperties.Builder()
.nutrition(10)
.saturationModifier(1.2F)
.effect(MobEffectInstance(MobEffects.ABSORPTION, 900, 0), 1F)
.alwaysEdible()
.build())) {
override fun finishUsingItem(stack: ItemStack, world: Level, user: LivingEntity): ItemStack {
user.removeAllEffects()
return super.finishUsingItem(stack, world, user)
}
})
@JvmField
val SHALOR_SABLE = create("shalor_sable", object : Item(Properties().stacksTo(16) // todo add all the effects and/or an item class for it for special interactions?
.food(FoodProperties.Builder()
.nutrition(10)
.saturationModifier(1.2F)
.effect(MobEffectInstance(MobEffects.ABSORPTION, 900, 0), 1F)
.alwaysEdible()
.build())) {
override fun finishUsingItem(stack: ItemStack, world: Level, user: LivingEntity): ItemStack {
user.removeAllEffects()
return super.finishUsingItem(stack, world, user)
}
})
@JvmField
val LUMIOSE_GALETTE = create("lumiose_galette", object : Item(Properties().stacksTo(16) // todo add all the effects and/or an item class for it for special interactions?
.food(FoodProperties.Builder()
.nutrition(10)
.saturationModifier(1.2F)
.effect(MobEffectInstance(MobEffects.ABSORPTION, 900, 0), 1F)
.alwaysEdible()
.build())) {
override fun finishUsingItem(stack: ItemStack, world: Level, user: LivingEntity): ItemStack {
user.removeAllEffects()
return super.finishUsingItem(stack, world, user)
}
})
@JvmField
val BIG_MALASADA = create("big_malasada", object : Item(Properties().stacksTo(16) // todo add all the effects and/or an item class for it for special interactions?
.food(FoodProperties.Builder()
.nutrition(10)
.saturationModifier(1.2F)
.effect(MobEffectInstance(MobEffects.ABSORPTION, 900, 0), 1F)
.alwaysEdible()
.build())) {
override fun finishUsingItem(stack: ItemStack, world: Level, user: LivingEntity): ItemStack {
user.removeAllEffects()
return super.finishUsingItem(stack, world, user)
}
})
/*@JvmField // todo see what we are doing for these (are there different kinds?)
val CURRY = create("curry", object : Item(Properties().stacksTo(16) // todo add all the effects and/or an item class for it for special interactions?
.food(FoodProperties.Builder()
.nutrition(10)
.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()
return super.finishUsingItem(stack, world, user)
}
})*/
@JvmField
val JUBILIFE_MUFFIN = create("jubilife_muffin", object : Item(Properties().stacksTo(16) // todo add all the effects and/or an item class for it for special interactions?
.food(FoodProperties.Builder()
.nutrition(10)
.saturationModifier(1.2F)
.effect(MobEffectInstance(MobEffects.ABSORPTION, 900, 0), 1F)
.alwaysEdible()
.build())) {
override fun finishUsingItem(stack: ItemStack, world: Level, user: LivingEntity): ItemStack {
user.removeAllEffects()
return super.finishUsingItem(stack, world, user)
}
})
/*@JvmField // todo see what we are doing for these (are there different kinds?)
val SANDWICH = create("sandwich", object : Item(Properties().stacksTo(16) // todo add all the effects and/or an item class for it for special interactions?
.food(FoodProperties.Builder()
.nutrition(10)
.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()
return super.finishUsingItem(stack, world, user)
}
})*/
// todo we might need to wait on these for later?
/*@JvmField
val CHOICE_DUMPLING = noSettingsItem("choice_dumpling") // todo make a ChoiceDumpingItem class for breeding purposes
@JvmField
val SWAP_SNACK = noSettingsItem("swap_snack") // todo make a SwapSnackItem class for breeding purposes
@JvmField
val TWICE_SPICED_BEETROOT = noSettingsItem("twice_spiced_beetroot") // todo make a TwiceSpiceBeetrootItem class for breeding purposes
*/
@JvmField
val POTATO_MOCHI = create("potato_mochi", object : Item(Properties().stacksTo(16)
.food(FoodProperties.Builder()
.nutrition(10)
.saturationModifier(1.2F)
.effect(MobEffectInstance(MobEffects.ABSORPTION, 900, 0), 1F)
.alwaysEdible()
.build())) {
override fun finishUsingItem(stack: ItemStack, world: Level, user: LivingEntity): ItemStack {
user.removeAllEffects()
return super.finishUsingItem(stack, world, user)
}
})
@JvmField
val FRIED_RICE = create("fried_rice", object : Item(Properties().stacksTo(16)
.food(FoodProperties.Builder()
.nutrition(10)
.saturationModifier(1.2F)
.effect(MobEffectInstance(MobEffects.ABSORPTION, 900, 0), 1F)
.alwaysEdible()
.build())) {
override fun finishUsingItem(stack: ItemStack, world: Level, user: LivingEntity): ItemStack {
user.removeAllEffects()
return super.finishUsingItem(stack, world, user)
}
})
@JvmField
val CANDIED_APPLE = create("candied_apple", object : Item(Properties().stacksTo(16)
.food(FoodProperties.Builder()
.nutrition(10)
.saturationModifier(1.2F)
.effect(MobEffectInstance(MobEffects.ABSORPTION, 900, 0), 1F)
.alwaysEdible()
.build())) {
override fun finishUsingItem(stack: ItemStack, world: Level, user: LivingEntity): ItemStack {
user.removeAllEffects()
return super.finishUsingItem(stack, world, user)
}
})
@JvmField
val CANDIED_BERRY = create("candied_berry", object : Item(Properties().stacksTo(16)
.food(FoodProperties.Builder()
.nutrition(10)
.saturationModifier(1.2F)
.effect(MobEffectInstance(MobEffects.ABSORPTION, 900, 0), 1F)
.alwaysEdible()
.build())) {
override fun finishUsingItem(stack: ItemStack, world: Level, user: LivingEntity): ItemStack {
user.removeAllEffects()
return super.finishUsingItem(stack, world, user)
}
})
@JvmField
val JELLY_DOUGHNUT = create("jelly_doughnut", object : Item(Properties().stacksTo(16)
.food(FoodProperties.Builder()
.nutrition(10)
.saturationModifier(1.2F)
.effect(MobEffectInstance(MobEffects.ABSORPTION, 900, 0), 1F)
.alwaysEdible()
.build())) {
override fun finishUsingItem(stack: ItemStack, world: Level, user: LivingEntity): ItemStack {
user.removeAllEffects()
return super.finishUsingItem(stack, world, user)
}
})
// todo etc?
//@JvmField
//val SCATTER_BANG = this.create("scatter_bang", ScatterBangItem(Item.Settings()))
//@JvmField
//val STICKY_GLOB = this.create("sticky_glob", StickyGlobItem(Item.Settings()))
@JvmField
val RESTORATION_TANK = blockItem("restoration_tank", CobblemonBlocks.RESTORATION_TANK)
@JvmField
@@ -276,12 +623,12 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
@JvmField
val DISPLAY_CASE = blockItem("display_case", CobblemonBlocks.DISPLAY_CASE)
@JvmField
val LECTERN = blockItem("lectern", CobblemonBlocks.LECTERN)
val INCENSE_SWEET = blockItem("incense_sweet", CobblemonBlocks.INCENSE_SWEET)
// Evolution items
@JvmField val LINK_CABLE = create("link_cable", LinkCableItem())
@JvmField val DRAGON_SCALE = noSettingsItem("dragon_scale")
@JvmField val KINGS_ROCK = noSettingsItem("kings_rock")
@JvmField val METAL_COAT = noSettingsItem("metal_coat")
@JvmField val UPGRADE = noSettingsItem("upgrade")
@JvmField val DUBIOUS_DISC = noSettingsItem("dubious_disc")
@@ -294,20 +641,21 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
@JvmField val REAPER_CLOTH = noSettingsItem("reaper_cloth")
@JvmField val PRISM_SCALE = noSettingsItem("prism_scale")
@JvmField val SACHET = noSettingsItem("sachet")
@JvmField val WHIPPED_DREAM = noSettingsItem("whipped_dream")
@JvmField val STRAWBERRY_SWEET = noSettingsItem("strawberry_sweet")
@JvmField val LOVE_SWEET = noSettingsItem("love_sweet")
@JvmField val BERRY_SWEET = noSettingsItem("berry_sweet")
@JvmField val CLOVER_SWEET = noSettingsItem("clover_sweet")
@JvmField val FLOWER_SWEET = noSettingsItem("flower_sweet")
@JvmField val STAR_SWEET = noSettingsItem("star_sweet")
@JvmField val RIBBON_SWEET = noSettingsItem("ribbon_sweet")
@JvmField val WHIPPED_DREAM = create("whipped_dream", foodItem(8, 0.3f))
@JvmField val STRAWBERRY_SWEET = create("strawberry_sweet", foodItem(6, 0.125f))
@JvmField val LOVE_SWEET = create("love_sweet", foodItem(6, 0.125f))
@JvmField val BERRY_SWEET = create("berry_sweet", foodItem(6, 0.125f))
@JvmField val CLOVER_SWEET = create("clover_sweet", foodItem(6, 0.125f))
@JvmField val FLOWER_SWEET = create("flower_sweet", foodItem(6, 0.125f))
@JvmField val STAR_SWEET = create("star_sweet", foodItem(6, 0.125f))
@JvmField val RIBBON_SWEET = create("ribbon_sweet", foodItem(6, 0.125f))
@JvmField val CHIPPED_POT = noSettingsItem("chipped_pot")
@JvmField val CRACKED_POT = noSettingsItem("cracked_pot")
@JvmField val MASTERPIECE_TEACUP = noSettingsItem("masterpiece_teacup")
@JvmField val UNREMARKABLE_TEACUP = noSettingsItem("unremarkable_teacup")
@JvmField val SWEET_APPLE = noSettingsItem("sweet_apple")
@JvmField val TART_APPLE = noSettingsItem("tart_apple")
@JvmField val SWEET_APPLE = create("sweet_apple", foodItem(4, 0.3f))
@JvmField val TART_APPLE = create("tart_apple", foodItem(4, 0.3f))
@JvmField val SYRUPY_APPLE = create("syrupy_apple", foodItem(4, 0.3f))
@JvmField val GALARICA_CUFF = noSettingsItem("galarica_cuff")
@JvmField val GALARICA_WREATH = noSettingsItem("galarica_wreath")
@JvmField val BLACK_AUGURITE = noSettingsItem("black_augurite")
@@ -421,6 +769,20 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
@JvmField
val ZINC = create("zinc", VitaminItem(Stats.SPECIAL_DEFENCE))
@JvmField
val HEALTH_MOCHI = create("health_mochi", MochiItem(Stats.HP))
@JvmField
val MUSCLE_MOCHI = create("muscle_mochi", MochiItem(Stats.ATTACK))
@JvmField
val RESIST_MOCHI = create("resist_mochi", MochiItem(Stats.DEFENCE))
@JvmField
val GENIUS_MOCHI = create("genius_mochi", MochiItem(Stats.SPECIAL_ATTACK))
@JvmField
val CLEVER_MOCHI = create("clever_mochi", MochiItem(Stats.SPECIAL_DEFENCE))
@JvmField
val SWIFT_MOCHI = create("swift_mochi", MochiItem(Stats.SPEED))
@JvmField
val FRESH_START_MOCHI = create("fresh_start_mochi", FreshStartMochiItem())
@JvmField
val GENIUS_FEATHER = create("genius_feather", FeatherItem(Stats.SPECIAL_ATTACK))
@JvmField
val SWIFT_FEATHER = create("swift_feather", FeatherItem(Stats.SPEED))
@@ -660,6 +1022,19 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
@JvmField
val WATER_STONE = noSettingsItem("water_stone")
val wearables = mutableListOf<WearableItem>()
//Wearable items (these items should have a corresponding 3D model)
@JvmField val BLACK_GLASSES = wearableItem("black_glasses")
@JvmField val CHOICE_BAND = wearableItem("choice_band")
@JvmField val CHOICE_SPECS = wearableItem("choice_specs")
@JvmField val EXP_SHARE = wearableItem("exp_share")
@JvmField val FOCUS_BAND = wearableItem("focus_band")
@JvmField val KINGS_ROCK = wearableItem("kings_rock")
@JvmField val MUSCLE_BAND = wearableItem("muscle_band")
@JvmField val ROCKY_HELMET = wearableItem("rocky_helmet")
@JvmField val SAFETY_GOGGLES = wearableItem("safety_goggles")
@JvmField val WISE_GLASSES = wearableItem("wise_glasses")
// Held Items
@JvmField
val ABILITY_SHIELD = heldItem("ability_shield")
@@ -676,8 +1051,6 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
@JvmField
val BLACK_BELT = heldItem("black_belt")
@JvmField
val BLACK_GLASSES = heldItem("black_glasses")
@JvmField
val BLACK_SLUDGE = heldItem("black_sludge")
@JvmField
val BLUNDER_POLICY = heldItem("blunder_policy")
@@ -686,12 +1059,8 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
@JvmField
val CHARCOAL = heldItem("charcoal_stick", remappedName = "charcoal")
@JvmField
val CHOICE_BAND = heldItem("choice_band")
@JvmField
val CHOICE_SCARF = heldItem("choice_scarf")
@JvmField
val CHOICE_SPECS = heldItem("choice_specs")
@JvmField
val CLEANSE_TAG = heldItem("cleanse_tag")
// @JvmField
// val CLEAR_AMULET = heldItem("clear_amulet")
@@ -712,8 +1081,6 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
@JvmField
val EVIOLITE = heldItem("eviolite")
@JvmField
val EXP_SHARE = heldItem("exp_share")
@JvmField
val EXPERT_BELT = heldItem("expert_belt")
@JvmField
val FAIRY_FEATHER = heldItem("fairy_feather")
@@ -722,8 +1089,6 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
@JvmField
val FLOAT_STONE = heldItem("float_stone")
@JvmField
val FOCUS_BAND = heldItem("focus_band")
@JvmField
val FOCUS_SASH = heldItem("focus_sash")
@JvmField
val GRASSY_SEED = heldItem("grassy_seed")
@@ -758,8 +1123,6 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
@JvmField
val MIRACLE_SEED = heldItem("miracle_seed")
@JvmField
val MUSCLE_BAND = heldItem("muscle_band")
@JvmField
val MYSTIC_WATER = heldItem("mystic_water")
@JvmField
val NEVER_MELT_ICE = heldItem("never_melt_ice")
@@ -790,12 +1153,8 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
@JvmField
val RING_TARGET = heldItem("ring_target")
@JvmField
val ROCKY_HELMET = heldItem("rocky_helmet")
@JvmField
val ROOM_SERVICE = heldItem("room_service")
@JvmField
val SAFETY_GOGGLES = heldItem("safety_goggles")
@JvmField
val SCOPE_LENS = heldItem("scope_lens")
@JvmField
val SHARP_BEAK = heldItem("sharp_beak")
@@ -832,8 +1191,6 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
@JvmField
val WIDE_LENS = heldItem("wide_lens")
@JvmField
val WISE_GLASSES = heldItem("wise_glasses")
@JvmField
val ZOOM_LENS = heldItem("zoom_lens")
@JvmField
val MENTAL_HERB = compostableHeldItem("mental_herb", null, 1F)
@@ -1263,6 +1620,28 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
return item
}
private fun wearableItem(name: String, heldItemRemappedName: String? = null): CobblemonItem = create(
name,
WearableItem(name).also {
wearables.add(it)
if (heldItemRemappedName != null) {
CobblemonHeldItemManager.registerRemap(it, heldItemRemappedName)
}
}
)
private fun campfirePotItem(block: Block, type: String): CampfirePotItem {
val item = create("campfire_pot_${type}", CampfirePotItem(block))
campfire_pots.add(item)
return item
}
private fun aprijuiceItem(type: Apricorn): AprijuiceItem {
val item = create("aprijuice_${type.name.lowercase()}", AprijuiceItem(type))
aprijuices.add(item)
return item
}
private fun heldItem(name: String, remappedName: String? = null): CobblemonItem = create(
name,
CobblemonItem(Item.Properties()).also {
@@ -1322,6 +1701,21 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
return item
}
private fun saccharineSaplingItem(name: String, saccharineSaplingItem: SaccharineSaplingItem): SaccharineSaplingItem {
val finalName = "saccharine_sapling"
val item = this.create(finalName, saccharineSaplingItem)
compostable(item, .65f)
return item
}
private fun bugwortItem(name: String, bugwortItem: BugwortItem): BugwortItem {
val finalName = "bugwort"
val item = this.create(finalName, bugwortItem)
compostable(item, .65f)
return item
}
private fun mintSeed(name: String, mintBlock: MintBlock): Item {
val finalName = "${name}_mint_seeds"
val item = this.blockItem(finalName, mintBlock)
@@ -1354,4 +1748,7 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
return createdItem
}
private fun foodItem(nutrition: Int, saturationModifier: Float): Item {
return Item(Item.Properties().food(FoodProperties.Builder().nutrition(nutrition).saturationModifier(saturationModifier).build()))
}
}
@@ -0,0 +1,30 @@
/*
* 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.cobblemon.mod.common.block.campfirepot.CookingPotMenu
import com.cobblemon.mod.common.client.gui.cookingpot.CookingPotScreen
import com.cobblemon.mod.common.platform.PlatformRegistry
import net.minecraft.client.gui.screens.MenuScreens
import net.minecraft.core.Registry
import net.minecraft.core.registries.BuiltInRegistries
import net.minecraft.core.registries.Registries
import net.minecraft.resources.ResourceKey
import net.minecraft.world.inventory.MenuType
object CobblemonMenuType : PlatformRegistry<Registry<MenuType<*>>, ResourceKey<Registry<MenuType<*>>>, MenuType<*>>() {
val COOKING_POT = MenuType.register("cooking_pot", ::CookingPotMenu)
override val registry: Registry<MenuType<*>>
get() = BuiltInRegistries.MENU
override val resourceKey: ResourceKey<Registry<MenuType<*>>>
get() = Registries.MENU
}
@@ -17,9 +17,9 @@ import com.cobblemon.mod.common.client.net.battle.*
import com.cobblemon.mod.common.client.net.callback.move.OpenMoveCallbackHandler
import com.cobblemon.mod.common.client.net.callback.party.OpenPartyCallbackHandler
import com.cobblemon.mod.common.client.net.callback.partymove.OpenPartyMoveCallbackHandler
import com.cobblemon.mod.common.client.net.cooking.ToggleCookingPotLidHandler
import com.cobblemon.mod.common.client.net.data.DataRegistrySyncPacketHandler
import com.cobblemon.mod.common.client.net.data.UnlockReloadPacketHandler
import com.cobblemon.mod.common.client.net.debug.showdown.ShowdownRefreshInfoHandler
import com.cobblemon.mod.common.client.net.dialogue.DialogueClosedHandler
import com.cobblemon.mod.common.client.net.dialogue.DialogueOpenedHandler
import com.cobblemon.mod.common.client.net.effect.RunPosableMoLangHandler
@@ -30,11 +30,13 @@ import com.cobblemon.mod.common.client.net.gui.PokedexUIPacketHandler
import com.cobblemon.mod.common.client.net.gui.SummaryUIPacketHandler
import com.cobblemon.mod.common.client.net.npc.CloseNPCEditorHandler
import com.cobblemon.mod.common.client.net.npc.OpenNPCEditorHandler
import com.cobblemon.mod.common.client.net.orientation.S2CUpdateOrientationHandler
import com.cobblemon.mod.common.client.net.pasture.ClosePastureHandler
import com.cobblemon.mod.common.client.net.pasture.OpenPastureHandler
import com.cobblemon.mod.common.client.net.pasture.PokemonPasturedHandler
import com.cobblemon.mod.common.client.net.pasture.PokemonUnpasturedHandler
import com.cobblemon.mod.common.client.net.pokedex.ServerConfirmedRegisterHandler
import com.cobblemon.mod.common.client.net.pokemon.update.ClientboundUpdateRidingStateHandler
import com.cobblemon.mod.common.client.net.pokemon.update.PokemonUpdatePacketHandler
import com.cobblemon.mod.common.client.net.settings.OpenCobblemonConfigEditorHandler
import com.cobblemon.mod.common.client.net.settings.ServerSettingsPacketHandler
@@ -49,7 +51,14 @@ import com.cobblemon.mod.common.client.net.storage.party.SetPartyPokemonHandler
import com.cobblemon.mod.common.client.net.storage.party.SetPartyReferenceHandler
import com.cobblemon.mod.common.client.net.storage.pc.*
import com.cobblemon.mod.common.client.net.toast.ToastPacketHandler
import com.cobblemon.mod.common.client.net.trade.*
import com.cobblemon.mod.common.client.net.trade.TradeAcceptanceChangedHandler
import com.cobblemon.mod.common.client.net.trade.TradeCancelledHandler
import com.cobblemon.mod.common.client.net.trade.TradeCompletedHandler
import com.cobblemon.mod.common.client.net.trade.TradeOfferExpiredHandler
import com.cobblemon.mod.common.client.net.trade.TradeOfferNotificationHandler
import com.cobblemon.mod.common.client.net.trade.TradeProcessStartedHandler
import com.cobblemon.mod.common.client.net.trade.TradeStartedHandler
import com.cobblemon.mod.common.client.net.trade.TradeUpdatedHandler
import com.cobblemon.mod.common.net.PacketRegisterInfo
import com.cobblemon.mod.common.net.messages.client.CalculateSeatPositionsPacket
import com.cobblemon.mod.common.net.messages.client.PlayerInteractOptionsPacket
@@ -59,8 +68,9 @@ import com.cobblemon.mod.common.net.messages.client.battle.*
import com.cobblemon.mod.common.net.messages.client.callback.OpenMoveCallbackPacket
import com.cobblemon.mod.common.net.messages.client.callback.OpenPartyCallbackPacket
import com.cobblemon.mod.common.net.messages.client.callback.OpenPartyMoveCallbackPacket
import com.cobblemon.mod.common.net.messages.client.cooking.SeasoningRegistrySyncPacket
import com.cobblemon.mod.common.net.messages.client.cooking.ToggleCookingPotLidPacket
import com.cobblemon.mod.common.net.messages.client.data.*
import com.cobblemon.mod.common.net.messages.client.debug.showdown.ShowdownRefreshInfoPacket
import com.cobblemon.mod.common.net.messages.client.dialogue.DialogueClosedPacket
import com.cobblemon.mod.common.net.messages.client.dialogue.DialogueOpenedPacket
import com.cobblemon.mod.common.net.messages.client.effect.RunPosableMoLangPacket
@@ -68,6 +78,7 @@ import com.cobblemon.mod.common.net.messages.client.effect.SpawnSnowstormEntityP
import com.cobblemon.mod.common.net.messages.client.effect.SpawnSnowstormParticlePacket
import com.cobblemon.mod.common.net.messages.client.npc.CloseNPCEditorPacket
import com.cobblemon.mod.common.net.messages.client.npc.OpenNPCEditorPacket
import com.cobblemon.mod.common.net.messages.client.orientation.ClientboundUpdateOrientationPacket
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
@@ -91,18 +102,42 @@ import com.cobblemon.mod.common.net.messages.client.storage.party.InitializePart
import com.cobblemon.mod.common.net.messages.client.storage.party.MoveClientPartyPokemonPacket
import com.cobblemon.mod.common.net.messages.client.storage.party.SetPartyPokemonPacket
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.storage.pc.ClosePCPacket
import com.cobblemon.mod.common.net.messages.client.storage.pc.InitializePCPacket
import com.cobblemon.mod.common.net.messages.client.storage.pc.MoveClientPCPokemonPacket
import com.cobblemon.mod.common.net.messages.client.storage.pc.OpenPCPacket
import com.cobblemon.mod.common.net.messages.client.storage.pc.RenamePCBoxPacket
import com.cobblemon.mod.common.net.messages.client.storage.pc.SetPCBoxPacket
import com.cobblemon.mod.common.net.messages.client.storage.pc.SetPCPokemonPacket
import com.cobblemon.mod.common.net.messages.client.storage.pc.wallpaper.ChangePCBoxWallpaperPacket
import com.cobblemon.mod.common.net.messages.client.storage.pc.wallpaper.RequestPCBoxWallpapersPacket
import com.cobblemon.mod.common.net.messages.client.storage.pc.wallpaper.SetPCBoxWallpapersPacket
import com.cobblemon.mod.common.net.messages.client.storage.pc.wallpaper.UnlockPCBoxWallpaperPacket
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.trade.TradeAcceptanceChangedPacket
import com.cobblemon.mod.common.net.messages.client.trade.TradeCancelledPacket
import com.cobblemon.mod.common.net.messages.client.trade.TradeCompletedPacket
import com.cobblemon.mod.common.net.messages.client.trade.TradeOfferExpiredPacket
import com.cobblemon.mod.common.net.messages.client.trade.TradeOfferNotificationPacket
import com.cobblemon.mod.common.net.messages.client.trade.TradeProcessStartedPacket
import com.cobblemon.mod.common.net.messages.client.trade.TradeStartedPacket
import com.cobblemon.mod.common.net.messages.client.trade.TradeUpdatedPacket
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.BattleChallengePacket
import com.cobblemon.mod.common.net.messages.server.BattleChallengeResponsePacket
import com.cobblemon.mod.common.net.messages.server.BenchMovePacket
import com.cobblemon.mod.common.net.messages.server.RequestMoveSwapPacket
import com.cobblemon.mod.common.net.messages.server.RequestPlayerInteractionsPacket
import com.cobblemon.mod.common.net.messages.server.SelectStarterPacket
import com.cobblemon.mod.common.net.messages.server.SendOutPokemonPacket
import com.cobblemon.mod.common.net.messages.server.battle.BattleSelectActionsPacket
import com.cobblemon.mod.common.net.messages.server.battle.BattleTeamLeavePacket
import com.cobblemon.mod.common.net.messages.server.battle.BattleTeamRequestPacket
import com.cobblemon.mod.common.net.messages.server.battle.BattleTeamResponsePacket
import com.cobblemon.mod.common.net.messages.server.battle.RemoveSpectatorPacket
import com.cobblemon.mod.common.net.messages.server.battle.SpectateBattlePacket
import com.cobblemon.mod.common.net.messages.server.block.AdjustBlockEntityViewerCountPacket
import com.cobblemon.mod.common.net.messages.server.callback.move.MoveSelectCancelledPacket
import com.cobblemon.mod.common.net.messages.server.callback.move.MoveSelectedPacket
@@ -110,13 +145,12 @@ import com.cobblemon.mod.common.net.messages.server.callback.party.PartyPokemonS
import com.cobblemon.mod.common.net.messages.server.callback.party.PartySelectCancelledPacket
import com.cobblemon.mod.common.net.messages.server.callback.partymove.PartyMoveSelectCancelledPacket
import com.cobblemon.mod.common.net.messages.server.callback.partymove.PartyPokemonMoveSelectedPacket
import com.cobblemon.mod.common.net.messages.server.debug.showdown.RequestShowdownInfoPacket
import com.cobblemon.mod.common.net.messages.server.debug.showdown.ShowdownActionPacket
import com.cobblemon.mod.common.net.messages.server.debug.showdown.ShowdownInputPacket
import com.cobblemon.mod.common.net.messages.server.debug.ServerboundUpdateRidingStatRangePacket
import com.cobblemon.mod.common.net.messages.server.debug.ServerboundUpdateRidingStatsPacket
import com.cobblemon.mod.common.net.messages.server.dialogue.EscapeDialoguePacket
import com.cobblemon.mod.common.net.messages.server.dialogue.InputToDialoguePacket
import com.cobblemon.mod.common.net.messages.server.npc.SaveNPCPacket
import com.cobblemon.mod.common.net.messages.server.orientation.C2SUpdateOrientationPacket
import com.cobblemon.mod.common.net.messages.server.orientation.ServerboundUpdateOrientationPacket
import com.cobblemon.mod.common.net.messages.server.pasture.PasturePokemonPacket
import com.cobblemon.mod.common.net.messages.server.pasture.UnpastureAllPokemonPacket
import com.cobblemon.mod.common.net.messages.server.pasture.UnpasturePokemonPacket
@@ -125,6 +159,9 @@ import com.cobblemon.mod.common.net.messages.server.pokedex.scanner.StartScannin
import com.cobblemon.mod.common.net.messages.server.pokemon.interact.InteractPokemonPacket
import com.cobblemon.mod.common.net.messages.server.pokemon.update.SetItemHiddenPacket
import com.cobblemon.mod.common.net.messages.server.pokemon.update.SetNicknamePacket
import com.cobblemon.mod.common.net.messages.server.pokemon.update.SetActiveMarkPacket
import com.cobblemon.mod.common.net.messages.server.pokemon.update.SetMarkingsPacket
import com.cobblemon.mod.common.net.messages.server.pokemon.update.ServerboundUpdateRidingStatePacket
import com.cobblemon.mod.common.net.messages.server.pokemon.update.evolution.AcceptEvolutionPacket
import com.cobblemon.mod.common.net.messages.server.starter.RequestStarterScreenPacket
import com.cobblemon.mod.common.net.messages.server.storage.SwapPCPartyPokemonPacket
@@ -132,11 +169,21 @@ import com.cobblemon.mod.common.net.messages.server.storage.party.MovePartyPokem
import com.cobblemon.mod.common.net.messages.server.storage.party.ReleasePartyPokemonPacket
import com.cobblemon.mod.common.net.messages.server.storage.party.SwapPartyPokemonPacket
import com.cobblemon.mod.common.net.messages.server.storage.pc.*
import com.cobblemon.mod.common.net.messages.server.trade.*
import com.cobblemon.mod.common.net.messages.server.trade.AcceptTradeRequestPacket
import com.cobblemon.mod.common.net.messages.server.trade.CancelTradePacket
import com.cobblemon.mod.common.net.messages.server.trade.ChangeTradeAcceptancePacket
import com.cobblemon.mod.common.net.messages.server.trade.OfferTradePacket
import com.cobblemon.mod.common.net.messages.server.trade.PerformTradePacket
import com.cobblemon.mod.common.net.messages.server.trade.UpdateTradeOfferPacket
import com.cobblemon.mod.common.net.serverhandling.ChallengeHandler
import com.cobblemon.mod.common.net.serverhandling.ChallengeResponseHandler
import com.cobblemon.mod.common.net.serverhandling.RequestInteractionsHandler
import com.cobblemon.mod.common.net.serverhandling.battle.*
import com.cobblemon.mod.common.net.serverhandling.battle.BattleSelectActionsHandler
import com.cobblemon.mod.common.net.serverhandling.battle.RemoveSpectatorHandler
import com.cobblemon.mod.common.net.serverhandling.battle.SpectateBattleHandler
import com.cobblemon.mod.common.net.serverhandling.battle.TeamLeaveHandler
import com.cobblemon.mod.common.net.serverhandling.battle.TeamRequestHandler
import com.cobblemon.mod.common.net.serverhandling.battle.TeamRequestResponseHandler
import com.cobblemon.mod.common.net.serverhandling.block.AdjustBlockEntityViewerCountHandler
import com.cobblemon.mod.common.net.serverhandling.callback.move.MoveSelectCancelledHandler
import com.cobblemon.mod.common.net.serverhandling.callback.move.MoveSelectedHandler
@@ -144,9 +191,8 @@ import com.cobblemon.mod.common.net.serverhandling.callback.party.PartyPokemonSe
import com.cobblemon.mod.common.net.serverhandling.callback.party.PartySelectCancelledHandler
import com.cobblemon.mod.common.net.serverhandling.callback.partymove.PartyMoveSelectCancelledHandler
import com.cobblemon.mod.common.net.serverhandling.callback.partymove.PartyPokemonMoveSelectedHandler
import com.cobblemon.mod.common.net.serverhandling.debug.showdown.RequestShowdownInfoHandler
import com.cobblemon.mod.common.net.serverhandling.debug.showdown.ShowdownActionHandler
import com.cobblemon.mod.common.net.serverhandling.debug.showdown.ShowdownInputHandler
import com.cobblemon.mod.common.net.serverhandling.debug.ServerboundUpdateRidingStatRangeHandler
import com.cobblemon.mod.common.net.serverhandling.debug.ServerboundUpdateRidingStatsHandler
import com.cobblemon.mod.common.net.serverhandling.dialogue.EscapeDialogueHandler
import com.cobblemon.mod.common.net.serverhandling.dialogue.InputToDialogueHandler
import com.cobblemon.mod.common.net.serverhandling.evolution.AcceptEvolutionHandler
@@ -160,6 +206,9 @@ import com.cobblemon.mod.common.net.serverhandling.pokedex.scanner.StartScanning
import com.cobblemon.mod.common.net.serverhandling.pokemon.interact.InteractPokemonHandler
import com.cobblemon.mod.common.net.serverhandling.pokemon.update.SetItemHiddenHandler
import com.cobblemon.mod.common.net.serverhandling.pokemon.update.SetNicknameHandler
import com.cobblemon.mod.common.net.serverhandling.pokemon.update.SetActiveMarkHandler
import com.cobblemon.mod.common.net.serverhandling.pokemon.update.SetMarkingsHandler
import com.cobblemon.mod.common.net.serverhandling.pokemon.update.ServerboundUpdateRidingStateHandler
import com.cobblemon.mod.common.net.serverhandling.starter.RequestStarterScreenHandler
import com.cobblemon.mod.common.net.serverhandling.starter.SelectStarterPacketHandler
import com.cobblemon.mod.common.net.serverhandling.storage.BenchMoveHandler
@@ -170,7 +219,12 @@ import com.cobblemon.mod.common.net.serverhandling.storage.party.MovePartyPokemo
import com.cobblemon.mod.common.net.serverhandling.storage.party.ReleasePCPokemonHandler
import com.cobblemon.mod.common.net.serverhandling.storage.party.SwapPartyPokemonHandler
import com.cobblemon.mod.common.net.serverhandling.storage.pc.*
import com.cobblemon.mod.common.net.serverhandling.trade.*
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.PerformTradeHandler
import com.cobblemon.mod.common.net.serverhandling.trade.UpdateTradeOfferHandler
import com.cobblemon.mod.common.util.server
import net.minecraft.server.level.ServerPlayer
@@ -227,6 +281,14 @@ object CobblemonNetwork {
list.add(PacketRegisterInfo(DmaxLevelUpdatePacket.ID, DmaxLevelUpdatePacket::decode, PokemonUpdatePacketHandler()))
list.add(PacketRegisterInfo(GmaxFactorUpdatePacket.ID, GmaxFactorUpdatePacket::decode, PokemonUpdatePacketHandler()))
list.add(PacketRegisterInfo(CosmeticItemUpdatePacket.ID, CosmeticItemUpdatePacket::decode, PokemonUpdatePacketHandler()))
list.add(PacketRegisterInfo(ActiveMarkUpdatePacket.ID, ActiveMarkUpdatePacket::decode, PokemonUpdatePacketHandler()))
list.add(PacketRegisterInfo(MarkAddUpdatePacket.ID, MarkAddUpdatePacket::decode, PokemonUpdatePacketHandler()))
list.add(PacketRegisterInfo(MarkRemoveUpdatePacket.ID, MarkRemoveUpdatePacket::decode, PokemonUpdatePacketHandler()))
list.add(PacketRegisterInfo(MarkPotentialAddUpdatePacket.ID, MarkPotentialAddUpdatePacket::decode, PokemonUpdatePacketHandler()))
list.add(PacketRegisterInfo(MarksUpdatePacket.ID, MarksUpdatePacket::decode, PokemonUpdatePacketHandler()))
list.add(PacketRegisterInfo(MarksPotentialUpdatePacket.ID, MarksPotentialUpdatePacket::decode, PokemonUpdatePacketHandler()))
list.add(PacketRegisterInfo(MarkingsUpdatePacket.ID, MarkingsUpdatePacket::decode, PokemonUpdatePacketHandler()))
list.add(PacketRegisterInfo(RideBoostsUpdatePacket.ID, RideBoostsUpdatePacket::decode, PokemonUpdatePacketHandler()))
// Evolution start
list.add(PacketRegisterInfo(AddEvolutionPacket.ID, AddEvolutionPacket::decode, PokemonUpdatePacketHandler()))
@@ -316,9 +378,11 @@ object CobblemonNetwork {
list.add(PacketRegisterInfo(ScriptRegistrySyncPacket.ID, ScriptRegistrySyncPacket::decode, DataRegistrySyncPacketHandler()))
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(SpawnBaitRegistrySyncPacket.ID, SpawnBaitRegistrySyncPacket::decode, DataRegistrySyncPacketHandler()))
list.add(PacketRegisterInfo(SeasoningRegistrySyncPacket.ID, SeasoningRegistrySyncPacket::decode, DataRegistrySyncPacketHandler()))
list.add(PacketRegisterInfo(FlowRegistrySyncPacket.ID, FlowRegistrySyncPacket::decode, DataRegistrySyncPacketHandler()))
list.add(PacketRegisterInfo(CosmeticItemAssignmentSyncPacket.ID, CosmeticItemAssignmentSyncPacket::decode, DataRegistrySyncPacketHandler()))
list.add(PacketRegisterInfo(MarkRegistrySyncPacket.ID, MarkRegistrySyncPacket::decode, DataRegistrySyncPacketHandler()))
// Effects
list.add(PacketRegisterInfo(SpawnSnowstormParticlePacket.ID, SpawnSnowstormParticlePacket::decode, SpawnSnowstormParticleHandler))
@@ -349,6 +413,9 @@ object CobblemonNetwork {
list.add(PacketRegisterInfo(PokemonPasturedPacket.ID, PokemonPasturedPacket::decode, PokemonPasturedHandler))
list.add(PacketRegisterInfo(PokemonUnpasturedPacket.ID, PokemonUnpasturedPacket::decode, PokemonUnpasturedHandler))
// Orientation
list.add(PacketRegisterInfo(ClientboundUpdateOrientationPacket.ID, ClientboundUpdateOrientationPacket::decode, S2CUpdateOrientationHandler))
// Behaviours
list.add(PacketRegisterInfo(PlayPosableAnimationPacket.ID, PlayPosableAnimationPacket::decode, PlayPosableAnimationHandler))
@@ -374,7 +441,9 @@ object CobblemonNetwork {
// Debug / cheats
list.add(PacketRegisterInfo(CalculateSeatPositionsPacket.ID, CalculateSeatPositionsPacket::decode, CalculateSeatPositionsHandler))
list.add(PacketRegisterInfo(ShowdownRefreshInfoPacket.ID, ShowdownRefreshInfoPacket::decode, ShowdownRefreshInfoHandler))
// Riding
list.add(PacketRegisterInfo(ClientboundUpdateRidingStatePacket.ID, ClientboundUpdateRidingStatePacket::decode, ClientboundUpdateRidingStateHandler))
return list
}
@@ -384,6 +453,8 @@ object CobblemonNetwork {
// Pokemon Update Packets
list.add(PacketRegisterInfo(SetNicknamePacket.ID, SetNicknamePacket::decode, SetNicknameHandler))
list.add(PacketRegisterInfo(SetItemHiddenPacket.ID, SetItemHiddenPacket::decode, SetItemHiddenHandler))
list.add(PacketRegisterInfo(SetActiveMarkPacket.ID, SetActiveMarkPacket::decode, SetActiveMarkHandler))
list.add(PacketRegisterInfo(SetMarkingsPacket.ID, SetMarkingsPacket::decode, SetMarkingsHandler))
// Evolution Packets
list.add(PacketRegisterInfo(AcceptEvolutionPacket.ID, AcceptEvolutionPacket::decode, AcceptEvolutionHandler))
@@ -471,13 +542,14 @@ object CobblemonNetwork {
// NPC packets
list.add(PacketRegisterInfo(SaveNPCPacket.ID, SaveNPCPacket::decode, SaveNPCHandler))
// Orientation packet(s)
list.add(PacketRegisterInfo(C2SUpdateOrientationPacket.ID, C2SUpdateOrientationPacket::decode, OrientationPacketHandler))
// Riding packet(s)
list.add(PacketRegisterInfo(ServerboundUpdateOrientationPacket.ID, ServerboundUpdateOrientationPacket::decode, OrientationPacketHandler))
list.add(PacketRegisterInfo(ServerboundUpdateRidingStatePacket.ID, ServerboundUpdateRidingStatePacket::decode, ServerboundUpdateRidingStateHandler))
list.add(PacketRegisterInfo(ServerboundUpdateRidingStatsPacket.ID, ServerboundUpdateRidingStatsPacket::decode, ServerboundUpdateRidingStatsHandler))
list.add(PacketRegisterInfo(ServerboundUpdateRidingStatRangePacket.ID, ServerboundUpdateRidingStatRangePacket::decode, ServerboundUpdateRidingStatRangeHandler))
// Debug / cheats
list.add(PacketRegisterInfo(RequestShowdownInfoPacket.ID, RequestShowdownInfoPacket::decode, RequestShowdownInfoHandler))
list.add(PacketRegisterInfo(ShowdownInputPacket.ID, ShowdownInputPacket::decode, ShowdownInputHandler))
list.add(PacketRegisterInfo(ShowdownActionPacket.ID, ShowdownActionPacket::decode, ShowdownActionHandler))
// Cooking
list.add(PacketRegisterInfo(ToggleCookingPotLidPacket.ID, ToggleCookingPotLidPacket::decode, ToggleCookingPotLidHandler))
return list
}
@@ -19,7 +19,7 @@ import net.minecraft.world.entity.ai.village.poi.PoiType
import net.minecraft.world.level.block.Block
import net.minecraft.world.level.block.state.BlockState
object CobblemonVillagerPoiTypes: PlatformRegistry<Registry<PoiType>, ResourceKey<Registry<PoiType>>, PoiType>() {
object CobblemonPoiTypes: PlatformRegistry<Registry<PoiType>, ResourceKey<Registry<PoiType>>, PoiType>() {
override val registry: Registry<PoiType> = BuiltInRegistries.POINT_OF_INTEREST_TYPE
override val resourceKey: ResourceKey<Registry<PoiType>> = Registries.POINT_OF_INTEREST_TYPE
@@ -27,8 +27,20 @@ object CobblemonVillagerPoiTypes: PlatformRegistry<Registry<PoiType>, ResourceKe
val NURSE_KEY: ResourceKey<PoiType> = createKey("nurse")
@JvmField
val NURSE = create(NURSE_KEY.location().path, PoiType(getBlockStates(CobblemonBlocks.HEALING_MACHINE), 1, 1))
@JvmField
val LURE_CAKE_KEY: ResourceKey<PoiType> = createKey("lure_cake")
@JvmField
val LURE_CAKE = create(LURE_CAKE_KEY.location().path, PoiType(getBlockStates(CobblemonBlocks.LURE_CAKE), 0, 1))
@JvmField
val SACCHARINE_HONEY_LOG_KEY: ResourceKey<PoiType> = createKey("saccharine_honey_log")
@JvmField
val SACCHARINE_HONEY_LOG = create(SACCHARINE_HONEY_LOG_KEY.location().path, PoiType(getBlockStates(CobblemonBlocks.SACCHARINE_HONEY_LOG), 0, 1))
@JvmField
val INCENSE_SWEET_KEY: ResourceKey<PoiType> = createKey("saccharine_honey_log")
@JvmField
val INCENSE_SWEET = create(INCENSE_SWEET_KEY.location().path, PoiType(getBlockStates(CobblemonBlocks.INCENSE_SWEET), 0, 1))
private fun createKey(string: String): ResourceKey<PoiType> = ResourceKey.create(Registries.POINT_OF_INTEREST_TYPE, cobblemonResource(string))
private fun getBlockStates(block: Block): Set<BlockState> = ImmutableSet.copyOf(block.stateDefinition.possibleStates)
}
}
@@ -0,0 +1,40 @@
/*
* 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 net.minecraft.client.RecipeBookCategories
enum class CobblemonRecipeCategories {
COOKING_POT_SEARCH("COOKING_POT_SEARCH"),
COOKING_POT_FOODS("COOKING_POT_FOODS"),
COOKING_POT_MEDICINES("COOKING_POT_MEDICINES"),
COOKING_POT_BAITS("COOKING_POT_BAITS"),
COOKING_POT_MISC("COOKING_POT_MISC");
companion object {
val customAggregateCategories: Map<RecipeBookCategories, List<RecipeBookCategories>> = mapOf(
COOKING_POT_SEARCH.toVanillaCategory() to listOf(
COOKING_POT_FOODS.toVanillaCategory(), COOKING_POT_MISC.toVanillaCategory(), COOKING_POT_MEDICINES.toVanillaCategory(), COOKING_POT_BAITS.toVanillaCategory()
)
)
}
var id: String
constructor(id: String) {
this.id = id
}
fun toVanillaCategory(): RecipeBookCategories {
return RecipeBookCategories.valueOf(this.id)
}
}
@@ -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
import com.cobblemon.mod.common.item.crafting.CookingPotRecipe
import com.cobblemon.mod.common.item.crafting.CookingPotShapelessRecipe
import com.cobblemon.mod.common.platform.PlatformRegistry
import net.minecraft.core.Registry
import net.minecraft.core.registries.BuiltInRegistries
import net.minecraft.core.registries.Registries
import net.minecraft.resources.ResourceKey
import net.minecraft.world.item.crafting.Recipe
import net.minecraft.world.item.crafting.RecipeSerializer
object CobblemonRecipeSerializers : PlatformRegistry<Registry<RecipeSerializer<*>>, ResourceKey<Registry<RecipeSerializer<*>>>, RecipeSerializer<*>>() {
val COOKING_POT_COOKING: RecipeSerializer<*> = register("cobblemon:cooking_pot", CookingPotRecipe.Serializer())
val COOKING_POT_SHAPELESS: RecipeSerializer<*> = register("cobblemon:cooking_pot_shapeless", CookingPotShapelessRecipe.Serializer())
override val registry: Registry<RecipeSerializer<*>>
get() = BuiltInRegistries.RECIPE_SERIALIZER
override val resourceKey: ResourceKey<Registry<RecipeSerializer<*>>>
get() = Registries.RECIPE_SERIALIZER
fun <S : RecipeSerializer<T>, T : Recipe<*>> register(key: String, recipeSerializer: S): S {
return Registry.register(BuiltInRegistries.RECIPE_SERIALIZER, key, recipeSerializer) as S
}
}
@@ -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
import com.cobblemon.mod.common.item.crafting.CookingPotRecipe
import com.cobblemon.mod.common.item.crafting.CookingPotShapelessRecipe
import com.cobblemon.mod.common.platform.PlatformRegistry
import net.minecraft.core.Registry
import net.minecraft.core.registries.BuiltInRegistries
import net.minecraft.core.registries.Registries
import net.minecraft.resources.ResourceKey
import net.minecraft.world.item.crafting.Recipe
import net.minecraft.world.item.crafting.RecipeType
object CobblemonRecipeTypes : PlatformRegistry<Registry<RecipeType<*>>, ResourceKey<Registry<RecipeType<*>>>, RecipeType<*>>() {
val COOKING_POT_COOKING: RecipeType<CookingPotRecipe> = register("cobblemon:cooking_pot")
val COOKING_POT_SHAPELESS: RecipeType<CookingPotShapelessRecipe> = register("cobblemon:cooking_pot_shapeless")
override val registry: Registry<RecipeType<*>>
get() = BuiltInRegistries.RECIPE_TYPE
override val resourceKey: ResourceKey<Registry<RecipeType<*>>>
get() = Registries.RECIPE_TYPE
fun <T : Recipe<*>> register(identifier: String): RecipeType<T> {
return Registry.register(
BuiltInRegistries.RECIPE_TYPE,
identifier,
object : RecipeType<T> {
override fun toString(): String {
return identifier
}
}
)
}
}
@@ -112,6 +112,8 @@ object CobblemonSounds : PlatformRegistry<Registry<SoundEvent>, ResourceKey<Regi
val MEDICINE_SPRAY_USE = this.create("item.medicine.spray.use")
@JvmField
val MEDICINE_FEATHER_USE = this.create("item.medicine.feather.use")
@JvmField
val MOCHI_USE = this.create("item.medicine.feather.use")
@JvmField
val MULCH_PLACE = this.create("block.mulch.place")
@@ -425,5 +427,37 @@ object CobblemonSounds : PlatformRegistry<Registry<SoundEvent>, ResourceKey<Regi
DISPLAY_CASE_STEP
)
@JvmField
val CAMPFIRE_POT_PLACE_CAMPFIRE = this.create("block.campfire_pot.place_campfire")
@JvmField
val CAMPFIRE_POT_RETRIEVE = this.create("block.campfire_pot.retrieve")
@JvmField
val CAMPFIRE_POT_OPEN = this.create("block.campfire_pot.open")
@JvmField
val CAMPFIRE_POT_CLOSE = this.create("block.campfire_pot.close")
@JvmField
val CAMPFIRE_POT_USE = this.create("block.campfire_pot.use")
@JvmField
val CAMPFIRE_POT_COOK = this.create("block.campfire_pot.cook")
@JvmField
val CAMPFIRE_POT_CRAFT = this.create("block.campfire_pot.craft")
@JvmField
val CAMPFIRE_POT_PLACE = this.create("block.campfire_pot.place")
@JvmField
val CAMPFIRE_POT_BREAK = this.create("block.campfire_pot.break")
@JvmField
val CAMPFIRE_POT_HIT = this.create("block.campfire_pot.hit")
@JvmField
val CAMPFIRE_POT_STEP = this.create("block.campfire_pot.step")
@JvmField
val CAMPFIRE_POT_SOUNDS = SoundType(1f, 1.1f,
CAMPFIRE_POT_BREAK,
CAMPFIRE_POT_STEP,
CAMPFIRE_POT_PLACE,
CAMPFIRE_POT_HIT,
CAMPFIRE_POT_STEP
)
private fun create(name: String): SoundEvent = this.create(name, SoundEvent.createVariableRangeEvent(cobblemonResource(name)))
}
@@ -24,7 +24,7 @@ object CobblemonVillagerProfessions: PlatformRegistry<Registry<VillagerProfessio
override val resourceKey: ResourceKey<Registry<VillagerProfession>> = Registries.VILLAGER_PROFESSION
@JvmField
val NURSE = profession(CobblemonVillagerPoiTypes.NURSE_KEY, CobblemonSounds.VILLAGER_WORK_NURSE)
val NURSE = profession(CobblemonPoiTypes.NURSE_KEY, CobblemonSounds.VILLAGER_WORK_NURSE)
/**
* Register a villager profession texture override for Cobblemon villagers of the given [VillagerProfession] for specified names.
@@ -20,8 +20,8 @@ import net.minecraft.resources.ResourceLocation
class CastPokeRodContext(val baitId: ResourceLocation)
class CastPokeRodCriterionCondition(
playerCtx: Optional<ContextAwarePredicate>,
val baitId: String
playerCtx: Optional<ContextAwarePredicate>,
val baitId: String
): SimpleCriterionCondition<CastPokeRodContext>(playerCtx) {
companion object {
@@ -37,7 +37,7 @@ object Abilities : DataRegistry {
PotentialAbility.types.add(CommonAbilityType)
PotentialAbility.types.add(HiddenAbilityType)
this.abilityMap.clear()
val abilitiesJson = ShowdownService.get().getAbilityIds()
val abilitiesJson = ShowdownService.service.getAbilityIds()
for (i in 0 until abilitiesJson.size()) {
val id = abilitiesJson[i].asString
val ability = AbilityTemplate(id)
@@ -67,4 +67,4 @@ object Abilities : DataRegistry {
abilities.forEach { ability -> this.register(ability) }
}
}
}
@@ -10,6 +10,7 @@ package com.cobblemon.mod.common.api.apricorn
import com.cobblemon.mod.common.CobblemonBlocks
import com.cobblemon.mod.common.CobblemonItems
import com.cobblemon.mod.common.api.cooking.Flavour
import com.cobblemon.mod.common.block.ApricornBlock
import com.cobblemon.mod.common.block.ApricornSaplingBlock
import com.cobblemon.mod.common.item.ApricornItem
@@ -27,15 +28,43 @@ import net.minecraft.world.level.material.MapColor
* @author Licious
* @since October 29th, 2022
*/
enum class Apricorn : StringRepresentable {
enum class Apricorn(
/** A value of true means it buffs that flavour, a value of false means it weakens that flavour. */
val flavourStrength: Map<Flavour, Boolean> = emptyMap()
) : StringRepresentable {
BLACK,
BLUE,
GREEN,
PINK,
RED,
BLUE(
mapOf(
Flavour.DRY to true,
Flavour.BITTER to false
)
),
GREEN(
mapOf(
Flavour.BITTER to true,
Flavour.SWEET to false
)
),
PINK(
mapOf(
Flavour.SWEET to true,
Flavour.SPICY to false
)
),
RED(
mapOf(
Flavour.SPICY to true,
Flavour.SOUR to false
)
),
WHITE,
YELLOW;
YELLOW(
mapOf(
Flavour.SOUR to true,
Flavour.DRY to false
)
);
fun item(): ApricornItem = when(this) {
BLACK -> CobblemonItems.BLACK_APRICORN
@@ -15,7 +15,10 @@ import com.cobblemon.mod.common.Cobblemon
import com.cobblemon.mod.common.Cobblemon.LOGGER
import com.cobblemon.mod.common.CobblemonNetwork
import com.cobblemon.mod.common.api.battles.interpreter.BattleMessage
import com.cobblemon.mod.common.api.battles.model.actor.*
import com.cobblemon.mod.common.api.battles.model.actor.ActorType
import com.cobblemon.mod.common.api.battles.model.actor.BattleActor
import com.cobblemon.mod.common.api.battles.model.actor.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.molang.MoLangFunctions.asMoLangValue
@@ -71,9 +74,7 @@ import net.minecraft.world.item.ItemStack
open class PokemonBattle(
val format: BattleFormat,
val side1: BattleSide,
val side2: BattleSide,
val service: ShowdownService = ShowdownService.get(),
val battleId: UUID = UUID.randomUUID()
val side2: BattleSide
) {
/** Whether logging will be silenced for this battle. */
var mute = true
@@ -108,6 +109,8 @@ open class PokemonBattle(
val players = playerUUIDs.mapNotNull { it.getPlayer() }
val spectators = mutableSetOf<UUID>()
val battleId = UUID.randomUUID()
val showdownMessages = mutableListOf<String>()
val battleLog = mutableListOf<String>()
val chatLog = mutableListOf<Component>()
@@ -222,7 +225,7 @@ open class PokemonBattle(
fun writeShowdownAction(vararg messages: String) {
log(messages.joinToString("\n"))
service.send(battleId, messages.toList().toTypedArray())
ShowdownService.service.send(battleId, messages.toList().toTypedArray())
}
fun turn(newTurnNumber: Int) {
@@ -375,6 +378,7 @@ open class PokemonBattle(
fun dispatch(dispatcher: () -> DispatchResult) {
dispatches.add(BattleDispatch { dispatcher() })
}
fun dispatchToFront(dispatcher: () -> DispatchResult) {
@@ -498,7 +502,6 @@ open class PokemonBattle(
}
fun checkForInputDispatch() {
actors.filter { it is UnionBattleActor }.forEach { it.mustChoose = false }
if (checkForfeit()) return // ignore actors that are still choosing, their choices don't matter anymore
val readyToInput = (actors.any { !it.mustChoose && it.responses.isNotEmpty() } && actors.none { it.mustChoose })
if (readyToInput && captureActions.isEmpty()) {
@@ -555,4 +558,4 @@ open class PokemonBattle(
queryStruct.addFunction("has_rule") { params -> DoubleValue(params.getString(0) in format.ruleSet) }
return queryStruct
}
}
}
@@ -42,4 +42,4 @@ abstract class AIBattleActor(
setActionResponses(request!!.iterate(this.activePokemon) { _, _, _ -> PassActionResponse })
}
}
}
}
@@ -73,7 +73,7 @@ abstract class BattleActor(
open fun isForPlayer(serverPlayerEntity: ServerPlayer) = serverPlayerEntity.uuid in getPlayerUUIDs()
open fun isForPokemon(pokemonEntity: PokemonEntity) = activePokemon.any { it.battlePokemon?.effectedPokemon?.entity == pokemonEntity }
open fun turn() {
fun turn() {
val request = request ?: return
responses.clear()
if(activePokemon.any { it.isAlive() }) {
@@ -90,7 +90,7 @@ abstract class BattleActor(
}
}
open fun upkeep() {
fun upkeep() {
val request = request ?: return
val forceSwitchPokemon = request.forceSwitch.mapIndexedNotNull { index, b -> if (b) activePokemon[index] else null }
if (forceSwitchPokemon.isEmpty()) {
@@ -125,7 +125,7 @@ abstract class BattleActor(
battle.checkForInputDispatch()
}
open fun writeShowdownResponse() {
fun writeShowdownResponse() {
val showdownMessages = mutableListOf<String>()
var index = 0
request!!.iterate(activePokemon) { activeBattlePokemon, showdownMoveSet, forceSwitch ->
@@ -159,4 +159,4 @@ abstract class BattleActor(
open fun win(otherWinners: List<BattleActor>, losers: List<BattleActor>) {}
open fun lose(winners: List<BattleActor>, otherLosers: List<BattleActor>) {}
}
}
@@ -1,25 +0,0 @@
package com.cobblemon.mod.common.api.battles.model.actor
import com.cobblemon.mod.common.battles.pokemon.BattlePokemon
import com.cobblemon.mod.common.entity.npc.NPCBattleActor
import com.cobblemon.mod.common.entity.npc.NPCEntity
class UnionBattleActor(npc: NPCEntity, pokemonList: List<BattlePokemon>) : NPCBattleActor(npc, pokemonList.toMutableList(), 1) {
override fun writeShowdownResponse() {}
override fun onChoiceRequested() {
this.mustChoose = false
}
override fun turn() {
super.turn()
this.mustChoose = false
}
override fun upkeep() {
super.upkeep()
this.mustChoose = false
}
}
@@ -11,6 +11,7 @@ package com.cobblemon.mod.common.api.berry
import com.cobblemon.mod.common.CobblemonBlocks
import com.cobblemon.mod.common.CobblemonItems
import com.cobblemon.mod.common.api.berry.spawncondition.BerrySpawnCondition
import com.cobblemon.mod.common.api.cooking.Flavour
import com.cobblemon.mod.common.api.events.CobblemonEvents
import com.cobblemon.mod.common.api.events.berry.BerryYieldCalculationEvent
import com.cobblemon.mod.common.api.mulch.MulchVariant
@@ -20,16 +21,10 @@ import com.cobblemon.mod.common.item.berry.BerryItem
import com.cobblemon.mod.common.pokemon.Nature
import com.cobblemon.mod.common.util.readBox
import com.cobblemon.mod.common.util.readEnumConstant
import com.cobblemon.mod.common.util.readEnumSet
import com.cobblemon.mod.common.util.readIdentifier
import com.cobblemon.mod.common.util.readList
import com.cobblemon.mod.common.util.readMap
import com.cobblemon.mod.common.util.writeBox
import com.cobblemon.mod.common.util.writeCollection
import com.cobblemon.mod.common.util.writeEnumConstant
import com.cobblemon.mod.common.util.writeEnumSet
import com.cobblemon.mod.common.util.writeIdentifier
import com.cobblemon.mod.common.util.writeMap
import com.google.gson.annotations.SerializedName
import net.minecraft.core.BlockPos
import net.minecraft.network.RegistryFriendlyByteBuf
@@ -38,6 +33,7 @@ import java.util.EnumSet
import net.minecraft.resources.ResourceLocation
import net.minecraft.tags.TagKey
import net.minecraft.world.entity.LivingEntity
import net.minecraft.world.item.DyeColor
import net.minecraft.world.level.Level
import net.minecraft.world.level.biome.Biome
import net.minecraft.world.level.block.Block
@@ -61,7 +57,7 @@ import net.minecraft.world.phys.shapes.VoxelShape
* @property growthPoints A collection of [GrowthPoint]s for the berry flowers and fruit.
* @property sproutShapeBoxes A collection of [Box]es that make up the tree [VoxelShape] during the sprouting stages.
* @property matureShapeBoxes A collection of [Box]es that make up the tree [VoxelShape] during the mature stages.
* @property flavors The [Flavor] values.
* @property flavours The [com.cobblemon.mod.common.api.cooking.Flavour] values.
* @property tintIndexes Determines tints at specific indexes if any.
* @property flowerModelIdentifier The [ResourceLocation] for the model of the berry in flower form.
* @property flowerTexture The [ResourceLocation] for the texture of the berry in flower form. This is resolved into a [ModelPart] on the client.
@@ -87,7 +83,10 @@ class Berry(
private val sproutShapeBoxes: Collection<AABB>,
@SerializedName("matureShape")
private val matureShapeBoxes: Collection<AABB>,
private val flavors: Map<Flavor, Int>,
@SerializedName("flavours", alternate = ["flavor"])
val flavours: Map<Flavour, Int>,
@SerializedName("colour", alternate = ["color"])
val colour: DyeColor,
val tintIndexes: Map<Int, Color>,
@SerializedName("flowerModel")
val flowerModelIdentifier: ResourceLocation,
@@ -144,13 +143,13 @@ class Berry(
/**
* Query the value of a certain flavor.
*
* @param flavor The [Flavor] being queried.
* @param flavour The [Flavour] being queried.
* @return The value if any or 0.
*/
fun flavor(flavor: Flavor): Int = this.flavors[flavor] ?: 0
fun flavor(flavour: Flavour): Int = this.flavours[flavour] ?: 0
fun dislikedBy(nature: Nature): Boolean {
val dislikedFlavor = nature.dislikedFlavor ?: return false
val dislikedFlavor = nature.dislikedFlavour ?: return false
return flavor(dislikedFlavor) > 0
}
@@ -281,7 +280,8 @@ class Berry(
buffer.writeCollection(this.matureShapeBoxes) { writer, value ->
writer.writeBox(value)
}
buffer.writeMap(this.flavors, { writer, key -> writer.writeEnumConstant(key) }, { writer, value -> writer.writeInt(value) })
buffer.writeMap(this.flavours, { writer, key -> writer.writeEnumConstant(key) }, { writer, value -> writer.writeInt(value) })
buffer.writeEnumConstant(colour)
buffer.writeMap(this.tintIndexes, { writer, key -> writer.writeInt(key) }, { writer, value -> writer.writeInt(value.rgb) })
buffer.writeIdentifier(this.flowerModelIdentifier)
buffer.writeIdentifier(this.flowerTexture)
@@ -353,7 +353,8 @@ class Berry(
val mutations = buffer.readMap({ reader -> reader.readIdentifier() }, { reader -> reader.readIdentifier() })
val sproutShapeBoxes = buffer.readList { it.readBox() }
val matureShapeBoxes = buffer.readList { it.readBox() }
val flavors = buffer.readMap({ reader -> reader.readEnumConstant(Flavor::class.java) }, { reader -> reader.readInt() })
val flavors = buffer.readMap({ reader -> reader.readEnumConstant(Flavour::class.java) }, { reader -> reader.readInt() })
val colour = buffer.readEnumConstant(DyeColor::class.java)
val tintIndexes = buffer.readMap({ reader -> reader.readInt() }, { reader -> Color(reader.readInt()) })
val flowerModelIdentifier = buffer.readIdentifier()
val flowerTexture = buffer.readIdentifier()
@@ -361,7 +362,7 @@ class Berry(
val fruitTexture = buffer.readIdentifier()
val stageOneYPos = GrowthPoint(Vec3(buffer.readDouble(), buffer.readDouble(), buffer.readDouble()), Vec3(buffer.readDouble(), buffer.readDouble(), buffer.readDouble()))
val boneMealChance = buffer.readFloat()
return Berry(identifier, baseYield, emptyList(), growthTime, refreshRate, favMulchs, emptySet(), emptyList(), growthPoints, randomizedGrowthPoints, mutations, sproutShapeBoxes, matureShapeBoxes, flavors, tintIndexes, flowerModelIdentifier, flowerTexture, fruitModelIdentifier, fruitTexture, stageOneYPos, 0F, boneMealChance)
return Berry(identifier, baseYield, emptyList(), growthTime, refreshRate, favMulchs, emptySet(), emptyList(), growthPoints, randomizedGrowthPoints, mutations, sproutShapeBoxes, matureShapeBoxes, flavors, colour, tintIndexes, flowerModelIdentifier, flowerTexture, fruitModelIdentifier, fruitTexture, stageOneYPos, 0F, boneMealChance)
}
}
@@ -1,24 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.berry
/**
* Represents the different flavors associated with berries and other Pokémon consumables.
* See the [Bulbapedia](https://bulbapedia.bulbagarden.net/wiki/Flavor) article for more information.
*
* @author Licious
* @since November 28th, 2022
*/
enum class Flavor(val colour: Int) {
SPICY(0x00FF00),
DRY(0xFF0000),
SWEET(0x0000FF),
BITTER(0xFFFF00),
SOUR(0xFF00FF);
}
@@ -0,0 +1,32 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.cooking
import net.minecraft.ChatFormatting
import net.minecraft.util.StringRepresentable
/**
* Represents the different flavors associated with berries and other Pokémon consumables.
* See the [Bulbapedia](https://bulbapedia.bulbagarden.net/wiki/Flavor) article for more information.
*
* @author Licious
* @since November 28th, 2022
*/
enum class Flavour(val colour: Int, val chatFormatting: ChatFormatting): StringRepresentable {
SPICY(0x00FF00, ChatFormatting.RED),
DRY(0xFF0000, ChatFormatting.DARK_AQUA),
SWEET(0x0000FF, ChatFormatting.LIGHT_PURPLE),
BITTER(0xFFFF00, ChatFormatting.GREEN),
SOUR(0xFF00FF, ChatFormatting.YELLOW);
override fun getSerializedName() = name
companion object {
val CODEC = StringRepresentable.fromEnum<Flavour> { Flavour.entries.toTypedArray() }
}
}
@@ -0,0 +1,63 @@
/*
* 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.cooking
import net.minecraft.util.FastColor
import net.minecraft.world.item.ItemStack
private val colourMap = mapOf(
Flavour.SPICY to 0xFEB37D,
Flavour.DRY to 0x8AE9FC,
Flavour.SWEET to 0xFFBEED,
Flavour.BITTER to 0x9EED8F,
Flavour.SOUR to 0xFCF38A
)
private val bubbleColourMap = mapOf(
Flavour.SPICY to 0xFFD9AD,
Flavour.DRY to 0xBCF8FE,
Flavour.SWEET to 0xFEE3F9,
Flavour.BITTER to 0xC8F7BC,
Flavour.SOUR to 0xFDFAB8
)
fun getColourMixFromSeasonings(seasonings: List<ItemStack>, forBubbles: Boolean = false): Int? {
val flavors = seasonings
.flatMap { Seasonings.getFlavoursFromItemStack(it).entries }
.groupingBy { it.key }
.fold(0) { acc, entry -> acc + entry.value }
val maxFlavorValue = flavors.values.maxOrNull()
val dominantFlavors = flavors.filter { it.value == maxFlavorValue }.map { it.key }
return getColourMixFromFlavours(dominantFlavors, forBubbles)
}
fun getColourMixFromFlavours(dominantFlavours: List<Flavour>, forBubbles: Boolean = false): Int? {
val colors =
dominantFlavours.mapNotNull { if (forBubbles) bubbleColourMap[it] else colourMap[it] }
.map { FastColor.ARGB32.opaque(it) }
if (colors.isEmpty()) return null
val (alphaSum, redSum, greenSum, blueSum) = colors.fold(IntArray(4)) { acc, color ->
acc[0] += FastColor.ARGB32.alpha(color)
acc[1] += FastColor.ARGB32.red(color)
acc[2] += FastColor.ARGB32.green(color)
acc[3] += FastColor.ARGB32.blue(color)
acc
}
return FastColor.ARGB32.color(
alphaSum / colors.size,
redSum / colors.size,
greenSum / colors.size,
blueSum / colors.size
)
}
@@ -0,0 +1,53 @@
/*
* 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.cooking
import com.cobblemon.mod.common.api.conditional.ITEM_REGISTRY_LIKE_CODEC
import com.cobblemon.mod.common.api.conditional.RegistryLikeCondition
import com.cobblemon.mod.common.api.conditional.RegistryLikeIdentifierCondition
import com.cobblemon.mod.common.api.fishing.SpawnBait
import com.cobblemon.mod.common.util.cobblemonResource
import com.google.gson.annotations.SerializedName
import com.mojang.serialization.Codec
import com.mojang.serialization.codecs.RecordCodecBuilder
import io.netty.buffer.ByteBuf
import net.minecraft.network.codec.ByteBufCodecs
import net.minecraft.network.codec.StreamCodec
import net.minecraft.world.item.DyeColor
import net.minecraft.world.item.Item
data class Seasoning(
val ingredient: RegistryLikeCondition<Item>,
@SerializedName("flavours", alternate = ["flavors"])
val flavours: Map<Flavour, Int>,
@SerializedName("colour", alternate = ["color"])
val colour: DyeColor,
@SerializedName("baitEffects")
val baitEffects: List<SpawnBait.Effect> = emptyList()
) {
companion object {
val CODEC: Codec<Seasoning> = RecordCodecBuilder.create { builder ->
builder.group(
ITEM_REGISTRY_LIKE_CODEC.fieldOf("ingredient").forGetter { it.ingredient },
Codec.unboundedMap(Flavour.CODEC, Codec.INT).fieldOf("flavours").forGetter { it.flavours }, // Use map codec
DyeColor.CODEC.fieldOf("colour").forGetter { it.colour },
SpawnBait.Effect.CODEC.listOf().optionalFieldOf("baitEffects", emptyList()).forGetter { it.baitEffects }
).apply(builder, ::Seasoning)
}
val STREAM_CODEC: StreamCodec<ByteBuf, Seasoning> = ByteBufCodecs.fromCodec(CODEC)
val BLANK_SEASONING = Seasoning(
ingredient = RegistryLikeIdentifierCondition<Item>(cobblemonResource("blank")),
flavours = Flavour.entries.associate { it to 0 },
colour = DyeColor.WHITE,
baitEffects = emptyList()
)
}
}
@@ -0,0 +1,92 @@
/*
* 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.cooking
import com.cobblemon.mod.common.CobblemonItemComponents
import com.cobblemon.mod.common.api.berry.Berries
import com.cobblemon.mod.common.api.conditional.RegistryLikeCondition
import com.cobblemon.mod.common.api.conditional.RegistryLikeIdentifierCondition
import com.cobblemon.mod.common.api.data.JsonDataRegistry
import com.cobblemon.mod.common.api.fishing.SpawnBait
import com.cobblemon.mod.common.api.reactive.SimpleObservable
import com.cobblemon.mod.common.net.messages.client.cooking.SeasoningRegistrySyncPacket
import com.cobblemon.mod.common.util.adapters.IdentifierAdapter
import com.cobblemon.mod.common.util.adapters.ItemLikeConditionAdapter
import com.cobblemon.mod.common.util.cobblemonResource
import com.google.gson.Gson
import com.google.gson.GsonBuilder
import com.google.gson.reflect.TypeToken
import net.minecraft.resources.ResourceLocation
import net.minecraft.server.level.ServerPlayer
import net.minecraft.server.packs.PackType
import net.minecraft.world.item.DyeColor
import net.minecraft.world.item.Item
import net.minecraft.world.item.ItemStack
object Seasonings : JsonDataRegistry<Seasoning> {
override val id = cobblemonResource("seasonings")
override val type = PackType.SERVER_DATA
override val observable = SimpleObservable<Seasonings>()
override val typeToken: TypeToken<Seasoning> = TypeToken.get(Seasoning::class.java)
override val resourcePath = "seasonings"
override val gson: Gson = GsonBuilder()
.registerTypeAdapter(ResourceLocation::class.java, IdentifierAdapter)
.registerTypeAdapter(TypeToken.getParameterized(RegistryLikeCondition::class.java, Item::class.java).type, ItemLikeConditionAdapter)
.setPrettyPrinting()
.create()
val seasonings = mutableListOf<Seasoning>()
val BLANK_SEASONING = Seasoning(
ingredient = RegistryLikeIdentifierCondition<Item>(cobblemonResource("blank")),
flavours = emptyMap(),
colour = DyeColor.WHITE
)
override fun sync(player: ServerPlayer) {
SeasoningRegistrySyncPacket(seasonings.toList()).sendToPlayer(player)
}
override fun reload(data: Map<ResourceLocation, Seasoning>) {
// this needs to sideload the berry data so we don't get duplicate JSONs.
val finalData = Berries.all().associate {
it.identifier to Seasoning(
ingredient = RegistryLikeIdentifierCondition(it.identifier),
flavours = it.flavours.toMap(),
colour = it.colour
)
}.toMutableMap()
finalData.putAll(data)
seasonings.addAll(finalData.values)
}
fun reloadEntries(seasonings: Collection<Seasoning>) {
this.seasonings.clear()
this.seasonings.addAll(seasonings)
}
fun getFlavoursFromItemStack(stack: ItemStack): Map<Flavour, Int> {
val holder = stack.itemHolder
val seasoning = seasonings.find { it.ingredient.fits(holder) } ?: BLANK_SEASONING
val inherentFlavours = stack.get(CobblemonItemComponents.FLAVOUR)?.flavours ?: emptyMap()
return seasoning.flavours.mapValues { (flavour, value) -> inherentFlavours.getOrDefault(flavour, 0) + value }
}
fun getBaitEffectsFromItemStack(stack: ItemStack): List<SpawnBait.Effect> {
return getFromItemStack(stack)?.baitEffects ?: emptyList()
}
fun getFromItemStack(stack: ItemStack): Seasoning? {
val holder = stack.itemHolder
return seasonings.find { it.ingredient.fits(holder) }
}
fun isSeasoning(stack: ItemStack) = getFromItemStack(stack) != null
}
@@ -20,4 +20,4 @@ interface EntitySideDelegate<T : Entity> {
fun tick(entity: T) {}
fun onSyncedDataUpdated(data: EntityDataAccessor<*>) {}
fun addToStruct(struct: QueryStruct) {}
}
}
@@ -21,4 +21,6 @@ interface PokemonSideDelegate : EntitySideDelegate<PokemonEntity> {
fun updatePostDeath() {}
fun handleStatus(status: Byte) {}
fun spawnShinyParticle(player: Player) {}
}
fun positionRider(passenger: Entity, positionUpdater: MoveFunction)
fun updateAge(age: Int) {}
}
@@ -255,6 +255,11 @@ object CobblemonEvents {
@JvmField
val BAIT_EFFECT_REGISTRATION = EventObservable<BaitEffectFunctionRegistryEvent>()
// Baits and Lures
@JvmField
val BAIT_SPAWN_POKEMON_MODIFY = EventObservable<BaitSpawnPokemonEvent.Modify>()
@JvmField
val COLLECT_EGG = CancelableObservable<CollectEggEvent>()
@JvmField
@@ -8,19 +8,19 @@
package com.cobblemon.mod.common.api.events.fishing
import com.cobblemon.mod.common.api.fishing.FishingBait
import com.cobblemon.mod.common.api.fishing.SpawnBait
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import net.minecraft.resources.ResourceLocation
/**
* Event to register code-based functions for bait effects.
* @see FishingBait.Effect
* @see FishingBait.Effects
* @see SpawnBait.Effect
* @see SpawnBait.Effects
*/
class BaitEffectFunctionRegistryEvent {
val functions = mutableMapOf<ResourceLocation, (PokemonEntity, FishingBait.Effect) -> Unit>()
val functions = mutableMapOf<ResourceLocation, (PokemonEntity, SpawnBait.Effect) -> Unit>()
fun registerFunction(id: ResourceLocation, function: (PokemonEntity, FishingBait.Effect) -> Unit) {
fun registerFunction(id: ResourceLocation, function: (PokemonEntity, SpawnBait.Effect) -> Unit) {
functions[id] = function
}
}
@@ -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.events.fishing
import com.cobblemon.mod.common.api.events.Cancelable
import com.cobblemon.mod.common.api.spawning.SpawnBucket
import com.cobblemon.mod.common.entity.fishing.PokeRodFishingBobberEntity
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import net.minecraft.world.item.ItemStack
/**
* Event that is fired when a Pokemon is spawned by a bobber.
*/
interface BaitSpawnPokemonEvent {
/**
* Event that is fired before a Pokemon is spawned by a bobber.
* @param bobber The PokeRodFishingBobberEntity that is spawning the Pokemon.
* @param chosenBucket The bucket that is chosen.
* @param rod The ItemStack of the rod that the bobber is attached to.
*/
data class Pre(
val bobber: PokeRodFishingBobberEntity, // todo replace this with the bait entity
val chosenBucket: SpawnBucket,
val rod: ItemStack
) : Cancelable(), BobberSpawnPokemonEvent
/**
* Event that is fired when a Pokemon is modified before it is spawned by a bobber.
* @param chosenBucket The bucket that is chosen.
* @param rod The ItemStack of the rod that the bobber is attached to.
* @param pokemon The Pokemon that is modified.
*/
data class Modify(
val chosenBucket: SpawnBucket,
val rod: ItemStack,
val pokemon: PokemonEntity
) : BobberSpawnPokemonEvent
/**
* Event that is fired after a Pokemon is spawned by a bobber.
* @param bobber The PokeRodFishingBobberEntity that is spawning the Pokemon.
* @param chosenBucket The bucket that is chosen.
* @param bait The ItemStack of the bait that is set on the rod.
* @param pokemon The Pokemon that is spawned.
*/
data class Post(
val bobber: PokeRodFishingBobberEntity,
val chosenBucket: SpawnBucket,
val bait: ItemStack,
val pokemon: PokemonEntity
) : BobberSpawnPokemonEvent
}
@@ -8,10 +8,16 @@
package com.cobblemon.mod.common.api.events.fishing
import com.bedrockk.molang.runtime.value.DoubleValue
import com.bedrockk.molang.runtime.value.MoValue
import com.cobblemon.mod.common.api.events.Cancelable
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMoLangValue
import com.cobblemon.mod.common.api.molang.ObjectValue
import com.cobblemon.mod.common.api.spawning.SpawnBucket
import com.cobblemon.mod.common.entity.fishing.PokeRodFishingBobberEntity
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import com.cobblemon.mod.common.util.itemRegistry
import net.minecraft.core.registries.Registries
import net.minecraft.world.item.ItemStack
/**
@@ -55,5 +61,11 @@ interface BobberSpawnPokemonEvent {
val chosenBucket: SpawnBucket,
val bait: ItemStack,
val pokemon: PokemonEntity
) : BobberSpawnPokemonEvent
) : BobberSpawnPokemonEvent {
val context = mutableMapOf<String, MoValue>(
"chosen_bucket" to ObjectValue(chosenBucket, { it.name }),
"bait" to pokemon.level().itemRegistry.wrapAsHolder(bait.item).asMoLangValue(Registries.ITEM),
"pokemon_entity" to pokemon.asMoLangValue()
)
}
}
@@ -8,10 +8,18 @@
package com.cobblemon.mod.common.api.events.pokemon
import com.bedrockk.molang.runtime.value.DoubleValue
import com.bedrockk.molang.runtime.value.MoValue
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMoLangValue
import com.cobblemon.mod.common.pokemon.Pokemon
import net.minecraft.server.level.ServerPlayer
data class FossilRevivedEvent (
val pokemon: Pokemon,
val player: ServerPlayer?
)
) {
val context = mutableMapOf<String, MoValue>(
"pokemon" to pokemon.struct,
"player" to (player?.asMoLangValue() ?: DoubleValue.ZERO)
)
}
@@ -1,114 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.fishing
import com.cobblemon.mod.common.CobblemonItemComponents
import com.cobblemon.mod.common.api.data.JsonDataRegistry
import com.cobblemon.mod.common.api.reactive.SimpleObservable
import com.cobblemon.mod.common.net.messages.client.data.FishingBaitRegistrySyncPacket
import com.cobblemon.mod.common.util.adapters.IdentifierAdapter
import com.cobblemon.mod.common.util.cobblemonResource
import com.google.gson.Gson
import com.google.gson.GsonBuilder
import com.google.gson.reflect.TypeToken
import net.minecraft.core.registries.BuiltInRegistries
import net.minecraft.resources.ResourceLocation
import net.minecraft.server.level.ServerPlayer
import net.minecraft.server.packs.PackType
import net.minecraft.world.item.ItemStack
object FishingBaits : JsonDataRegistry<FishingBait>{
override val id = cobblemonResource("fishing_baits")
override val type = PackType.SERVER_DATA
override val observable = SimpleObservable<FishingBaits>()
override val typeToken: TypeToken<FishingBait> = TypeToken.get(FishingBait::class.java)
override val resourcePath = "fishing_baits"
override val gson: Gson = GsonBuilder()
.registerTypeAdapter(ResourceLocation::class.java, IdentifierAdapter)
.setPrettyPrinting()
.create()
private val itemMap = mutableMapOf<ResourceLocation, FishingBait>()
override fun sync(player: ServerPlayer) {
FishingBaitRegistrySyncPacket(this.itemMap.values.toList()).sendToPlayer(player)
}
override fun reload(data: Map<ResourceLocation, FishingBait>) {
itemMap.clear()
data.forEach { id, bait ->
itemMap[bait.item] = bait
}
}
fun getFromRodItemStack(stack: ItemStack): FishingBait? {
return stack.components.get(CobblemonItemComponents.BAIT)?.bait
}
fun getFromBaitItemStack(stack: ItemStack): FishingBait? {
return getFromIdentifier(BuiltInRegistries.ITEM.getKey(stack.item))
}
fun getFromIdentifier(identifier: ResourceLocation): FishingBait? {
return itemMap[identifier]
}
fun isFishingBait(stack: ItemStack) = itemMap.containsKey(BuiltInRegistries.ITEM.getKey(stack.item))
//
//
// fun getBaitSubcategory(item: ItemStack): String? {
// val itemId = Registries.ITEM.getId(item.item)
// if (itemId in itemMap.keys) {
// return itemMap[itemId]?.subcategory
// }
// val tag = tagMap.keys.firstOrNull { it.fits(item.item, Registries.ITEM) }
// if (tag != null) {
// return tagMap[tag]?.subcategory
// }
// return null
// }
//
// fun getBaitSuccessChance(item: ItemStack): Double? {
// val itemId = Registries.ITEM.getId(item.item)
// if (itemId in itemMap.keys) {
// return itemMap[itemId]?.chance
// }
// val tag = tagMap.keys.firstOrNull { it.fits(item.item, Registries.ITEM) }
// if (tag != null) {
// return tagMap[tag]?.chance
// }
// return null
// }
//
// fun getBaitEffectValue(item: ItemStack): Double? {
// val itemId = Registries.ITEM.getId(item.item)
// if (itemId in itemMap.keys) {
// return itemMap[itemId]?.value
// }
// val tag = tagMap.keys.firstOrNull { it.fits(item.item, Registries.ITEM) }
// if (tag != null) {
// return tagMap[tag]?.value
// }
// return null
// }
//
//
// fun getBaitNote(item: ItemStack): String? {
// val itemId = Registries.ITEM.getId(item.item)
// if (itemId in itemMap.keys) {
// return itemMap[itemId]?.note
// }
// val tag = tagMap.keys.firstOrNull { it.fits(item.item, Registries.ITEM) }
// if (tag != null) {
// return tagMap[tag]?.note
// }
// return null
// }
}
@@ -8,6 +8,8 @@
package com.cobblemon.mod.common.api.fishing
import com.cobblemon.mod.common.api.conditional.ITEM_REGISTRY_LIKE_CODEC
import com.cobblemon.mod.common.api.conditional.RegistryLikeCondition
import com.cobblemon.mod.common.api.events.CobblemonEvents
import com.cobblemon.mod.common.api.events.fishing.BaitEffectFunctionRegistryEvent
import com.cobblemon.mod.common.api.spawning.fishing.FishingSpawnCause
@@ -16,18 +18,14 @@ 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.network.codec.ByteBufCodecs
import net.minecraft.resources.ResourceLocation
import net.minecraft.world.item.Item
import net.minecraft.world.item.ItemStack
data class FishingBait(
val item: ResourceLocation,
class SpawnBait(
val item: RegistryLikeCondition<Item>,
val effects: List<Effect>,
) {
fun toItemStack(itemRegistry: Registry<Item>) = item.let(itemRegistry::get)?.let { ItemStack(it) } ?: ItemStack.EMPTY
data class Effect(
val type: ResourceLocation,
val subcategory: ResourceLocation?,
@@ -49,19 +47,14 @@ data class FishingBait(
}
companion object {
val CODEC = RecordCodecBuilder.create<FishingBait> { instance ->
val CODEC = RecordCodecBuilder.create<SpawnBait> { instance ->
instance.group(
ResourceLocation.CODEC.fieldOf("item").forGetter { it.item },
ITEM_REGISTRY_LIKE_CODEC.fieldOf("item").forGetter { it.item },
Effect.CODEC.listOf().fieldOf("effects").forGetter {it.effects}
).apply(instance, ::FishingBait)
).apply(instance, ::SpawnBait)
}
val STREAM_CODEC = ByteBufCodecs.fromCodec(CODEC)
val BLANK_BAIT = FishingBait(
cobblemonResource("blank"),
emptyList()
)
}
object Effects {
@@ -78,7 +71,7 @@ data class FishingBait(
val HIDDEN_ABILITY_CHANCE = cobblemonResource("ha_chance")
val POKEMON_CHANCE = cobblemonResource("pokemon_chance")
val FRIENDSHIP = cobblemonResource("friendship")
val INERT = cobblemonResource("inert")
val RARITY_BUCKET = cobblemonResource("rarity_bucket")
fun registerEffect(type: ResourceLocation, effect: (PokemonEntity, Effect) -> Unit) {
EFFECT_FUNCTIONS[type] = effect
@@ -89,15 +82,15 @@ data class FishingBait(
}
fun setupEffects() {
EFFECT_FUNCTIONS[NATURE] = { entity, effect -> FishingSpawnCause.alterNatureAttempt(entity, effect) }
EFFECT_FUNCTIONS[IV] = { entity, effect -> FishingSpawnCause.alterIVAttempt(entity, effect) }
EFFECT_FUNCTIONS[SHINY_REROLL] = { entity, effect -> FishingSpawnCause.shinyReroll(entity, effect) }
EFFECT_FUNCTIONS[GENDER_CHANCE] = { entity, effect -> FishingSpawnCause.alterGenderAttempt(entity, effect) }
EFFECT_FUNCTIONS[LEVEL_RAISE] = { entity, effect -> FishingSpawnCause.alterLevelAttempt(entity, effect) }
EFFECT_FUNCTIONS[HIDDEN_ABILITY_CHANCE] = { entity, _ -> FishingSpawnCause.alterHAAttempt(entity) }
EFFECT_FUNCTIONS[FRIENDSHIP] = { entity, effect -> FishingSpawnCause.alterFriendshipAttempt(entity, effect) }
registerEffect(NATURE) { entity, effect -> FishingSpawnCause.alterNatureAttempt(entity, effect) }
registerEffect(IV) { entity, effect -> FishingSpawnCause.alterIVAttempt(entity, effect) }
registerEffect(SHINY_REROLL) { entity, effect -> FishingSpawnCause.shinyReroll(entity, effect) }
registerEffect(GENDER_CHANCE) { entity, effect -> FishingSpawnCause.alterGenderAttempt(entity, effect) }
registerEffect(LEVEL_RAISE) { entity, effect -> FishingSpawnCause.alterLevelAttempt(entity, effect) }
registerEffect(HIDDEN_ABILITY_CHANCE) { entity, _ -> FishingSpawnCause.alterHAAttempt(entity) }
registerEffect(FRIENDSHIP) { entity, effect -> FishingSpawnCause.alterFriendshipAttempt(entity, effect) }
CobblemonEvents.BAIT_EFFECT_REGISTRATION.post(BaitEffectFunctionRegistryEvent()) { event ->
EFFECT_FUNCTIONS.putAll(event.functions)
event.functions.forEach { (type, function) -> registerEffect(type, function) }
}
}
}
@@ -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.api.fishing
import com.cobblemon.mod.common.CobblemonItemComponents
import com.cobblemon.mod.common.api.conditional.RegistryLikeCondition
import com.cobblemon.mod.common.api.conditional.RegistryLikeIdentifierCondition
import com.cobblemon.mod.common.api.data.JsonDataRegistry
import com.cobblemon.mod.common.api.reactive.SimpleObservable
import com.cobblemon.mod.common.net.messages.client.data.SpawnBaitRegistrySyncPacket
import com.cobblemon.mod.common.util.adapters.IdentifierAdapter
import com.cobblemon.mod.common.util.adapters.ItemLikeConditionAdapter
import com.cobblemon.mod.common.util.cobblemonResource
import com.google.gson.Gson
import com.google.gson.GsonBuilder
import com.google.gson.reflect.TypeToken
import net.minecraft.core.Holder
import net.minecraft.resources.ResourceLocation
import net.minecraft.server.level.ServerPlayer
import net.minecraft.server.packs.PackType
import net.minecraft.world.item.Item
import net.minecraft.world.item.ItemStack
object SpawnBaitEffects : JsonDataRegistry<SpawnBait> {
override val id = cobblemonResource("spawn_bait_effects")
override val type = PackType.SERVER_DATA
override val observable = SimpleObservable<SpawnBaitEffects>()
override val typeToken: TypeToken<SpawnBait> = TypeToken.get(SpawnBait::class.java)
override val resourcePath = "spawn_bait_effects"
override val gson: Gson = GsonBuilder()
.registerTypeAdapter(ResourceLocation::class.java, IdentifierAdapter)
.registerTypeAdapter(TypeToken.getParameterized(RegistryLikeCondition::class.java, Item::class.java).type, ItemLikeConditionAdapter)
.setPrettyPrinting()
.create()
private val effectsMap = mutableMapOf<ResourceLocation, SpawnBait>()
override fun sync(player: ServerPlayer) {
SpawnBaitRegistrySyncPacket(this.effectsMap.toMap()).sendToPlayer(player)
}
override fun reload(data: Map<ResourceLocation, SpawnBait>) {
effectsMap.clear()
data.forEach { id, bait ->
effectsMap[id] = bait
}
}
fun getEffectsFromRodItemStack(stack: ItemStack): List<SpawnBait.Effect> {
return getEffectsFromItemStack(stack.components.get(CobblemonItemComponents.BAIT)?.stack ?: ItemStack.EMPTY)
}
fun getEffectsFromItemStack(stack: ItemStack): List<SpawnBait.Effect> {
val componentEffects = stack.get(CobblemonItemComponents.BAIT_EFFECTS)?.effects ?: emptyList()
return componentEffects.mapNotNull(::getFromIdentifier).flatMap { it.effects } +
getEffectsFromItem(stack.itemHolder)
}
fun getBaitIdentifiersFromItem(holder: Holder<Item>): List<ResourceLocation> {
return effectsMap.entries.filter { it.value.item.fits(holder) }.map { it.key }
}
fun getBaitFromItemStack(holder: Holder<Item>): List<SpawnBait> {
return effectsMap.values.filter { it.item.fits(holder) }
}
private fun getEffectsFromItem(holder: Holder<Item>): List<SpawnBait.Effect> {
return getBaitFromItemStack(holder).flatMap { it.effects }
}
fun getFromIdentifier(identifier: ResourceLocation): SpawnBait? {
// Check normal spawn bait registry
effectsMap[identifier]?.let { return it }
// check seasoning spawn bait registry
if (identifier.namespace == "seasonings") {
val seasoning = com.cobblemon.mod.common.api.cooking.Seasonings.seasonings.find {
it.ingredient is RegistryLikeIdentifierCondition &&
(it.ingredient as RegistryLikeIdentifierCondition<Item>).identifier.path == identifier.path
}
if (seasoning != null && seasoning.baitEffects.isNotEmpty()) {
return SpawnBait(
item = seasoning.ingredient,
effects = seasoning.baitEffects
)
}
}
return null
}
fun isFishingBait(stack: ItemStack): Boolean {
val holder = stack.itemHolder
return stack.has(CobblemonItemComponents.BAIT_EFFECTS) || effectsMap.values.any { it.item.fits(holder) }
}
}
@@ -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.api.fishing
object SpawnBaitUtils {
fun mergeEffects(effects: List<SpawnBait.Effect>): List<SpawnBait.Effect> {
val grouped = effects.groupBy { Pair(it.type, it.subcategory) }
return grouped.map { (key, groupEffects) ->
val (type, subcategory) = key
if (type == SpawnBait.Effects.RARITY_BUCKET) {
// we want to keep the highest rarity bucket effect instead of merging them
groupEffects.maxByOrNull { it.value }!!
} else {
val count = groupEffects.size
val totalChance = groupEffects.sumOf { it.chance }
val totalValue = groupEffects.sumOf { it.value }
val multiplier = when (count) {
2 -> 0.8
3 -> 0.9
else -> 1.0
}
val adjustedChance = (totalChance * multiplier).coerceAtMost(1.0)
val adjustedValue = totalValue * multiplier
SpawnBait.Effect(type, subcategory, adjustedChance, adjustedValue)
}
}
}
}
@@ -215,6 +215,7 @@ fun drawPosablePortrait(
ageInTicks: Float = 0F,
headYaw: Float = 0F,
headPitch: Float = 0F,
doQuirks: Boolean = true,
r: Float = 1F,
g: Float = 1F,
b: Float = 1F,
@@ -240,6 +241,7 @@ fun drawPosablePortrait(
context.put(RenderContext.SPECIES, identifier)
context.put(RenderContext.ASPECTS, state.currentAspects)
context.put(RenderContext.POSABLE_STATE, state)
context.put(RenderContext.DO_QUIRKS, doQuirks)
val renderType = RenderType.entityCutout(texture)
@@ -82,7 +82,7 @@ interface PokemonAndMoveSelectingItem {
val bagItem = bagItem
if (!battlePokemon.actor.canFitForcedAction()) {
player.sendSystemMessage(battleLang("bagitem.cannot").red())
} else if (!bagItem!!.canUse(battle, battlePokemon)) {
} else if (!bagItem!!.canUse(stack, battle, battlePokemon)) {
player.sendSystemMessage(battleLang("bagitem.invalid").red())
} else {
battlePokemon.actor.forceChoose(BagItemActionResponse(bagItem, battlePokemon, move.template.name))
@@ -92,10 +92,10 @@ interface PokemonAndMoveSelectingItem {
}
}
fun canUseOnPokemon(pokemon: Pokemon): Boolean
fun canUseOnBattlePokemon(battlePokemon: BattlePokemon): Boolean = bagItem!!.canUse(battlePokemon.actor.battle, battlePokemon)
fun canUseOnMove(pokemon: Pokemon, move: Move): Boolean = canUseOnMove(move)
fun canUseOnMove(move: Move): Boolean
fun canUseOnPokemon(stack: ItemStack, pokemon: Pokemon): Boolean
fun canUseOnBattlePokemon(stack: ItemStack, battlePokemon: BattlePokemon): Boolean = bagItem!!.canUse(stack, battlePokemon.actor.battle, battlePokemon)
fun canUseOnMove(stack: ItemStack, pokemon: Pokemon, move: Move): Boolean = canUseOnMove(stack, move)
fun canUseOnMove(stack: ItemStack, move: Move): Boolean
fun interactWithSpecific(player: ServerPlayer, stack: ItemStack, pokemon: Pokemon): InteractionResultHolder<ItemStack>? {
@@ -106,18 +106,18 @@ interface PokemonAndMoveSelectingItem {
MoveSelectCallbacks.create(
player = player,
moves = pokemon.moveSet.toList(),
canSelect = ::canUseOnMove,
canSelect = { canUseOnMove(stack, it)},
handler = { move -> if (stack.isHeld(player)) applyToPokemon(player, stack, pokemon, move) }
)
return InteractionResultHolder.success(stack)
}
fun interactWithSpecificBattle(player: ServerPlayer, stack: ItemStack, battlePokemon: BattlePokemon): InteractionResultHolder<ItemStack>? {
return if (canUseOnBattlePokemon(battlePokemon)) {
return if (canUseOnBattlePokemon(stack, battlePokemon)) {
MoveSelectCallbacks.create(
player = player,
moves = battlePokemon.moveSet.getMoves(),
canSelect = ::canUseOnMove,
canSelect = { canUseOnMove(stack, it) },
handler = { applyToBattlePokemon(player, stack, battlePokemon, it) }
)
InteractionResultHolder.success(stack)
@@ -131,8 +131,8 @@ interface PokemonAndMoveSelectingItem {
PartyMoveSelectCallbacks.createFromPokemon(
player = player,
pokemon = player.party().toList(),
canSelectPokemon = ::canUseOnPokemon,
canSelectMove = ::canUseOnMove,
canSelectPokemon = { canUseOnPokemon(stack, it) },
canSelectMove = { pokemon, move -> canUseOnMove(stack, pokemon, move) },
handler = { pk, mv -> if (stack.isHeld(player)) applyToPokemon(player, stack, pk, mv) }
)
@@ -144,8 +144,8 @@ interface PokemonAndMoveSelectingItem {
player = player,
pokemon = actor.pokemonList.map { it.effectedPokemon },
moves = { pk -> actor.pokemonList.find { it.effectedPokemon == pk }!!.moveSet.getMoves() },
canSelectPokemon = { pk -> canUseOnBattlePokemon(actor.pokemonList.find { it.effectedPokemon == pk }!!) },
canSelectMove = ::canUseOnMove,
canSelectPokemon = { pk -> canUseOnBattlePokemon(stack, actor.pokemonList.find { it.effectedPokemon == pk }!!) },
canSelectMove = { pokemon, move -> canUseOnMove(stack, pokemon, move) },
handler = { pk, mv -> applyToBattlePokemon(player, stack, actor.pokemonList.find { it.effectedPokemon == pk }!!, mv) }
)
@@ -92,7 +92,7 @@ interface PokemonSelectingItem {
val bagItem = bagItem
if (!battlePokemon.actor.canFitForcedAction()) {
player.sendSystemMessage(battleLang("bagitem.cannot").red())
} else if (!bagItem!!.canUse(battle, battlePokemon)) {
} else if (!bagItem!!.canUse(stack, battle, battlePokemon)) {
player.sendSystemMessage(battleLang("bagitem.invalid").red())
} else {
battlePokemon.actor.forceChoose(BagItemActionResponse(bagItem, battlePokemon))
@@ -105,11 +105,11 @@ interface PokemonSelectingItem {
}
}
fun canUseOnPokemon(pokemon: Pokemon): Boolean
fun canUseOnBattlePokemon(battlePokemon: BattlePokemon): Boolean = bagItem!!.canUse(battlePokemon.actor.battle, battlePokemon)
fun canUseOnPokemon(stack: ItemStack, pokemon: Pokemon): Boolean
fun canUseOnBattlePokemon(stack: ItemStack, battlePokemon: BattlePokemon): Boolean = bagItem!!.canUse(stack, battlePokemon.actor.battle, battlePokemon)
fun interactWithSpecificBattle(player: ServerPlayer, stack: ItemStack, battlePokemon: BattlePokemon): InteractionResultHolder<ItemStack> {
return if (canUseOnBattlePokemon(battlePokemon)) {
return if (canUseOnBattlePokemon(stack, battlePokemon)) {
applyToBattlePokemon(player, stack, battlePokemon)
InteractionResultHolder.success(stack)
} else {
@@ -127,7 +127,7 @@ interface PokemonSelectingItem {
PartySelectCallbacks.createFromPokemon(
player = player,
pokemon = party,
canSelect = ::canUseOnPokemon,
canSelect = { pk -> canUseOnPokemon(stack, pk) },
handler = { pk ->
if (stack.isHeld(player)) {
applyToPokemon(player, stack, pk)
@@ -143,7 +143,7 @@ interface PokemonSelectingItem {
PartySelectCallbacks.createBattleSelect(
player = player,
pokemon = actor.pokemonList,
canSelect = { pk -> canUseOnBattlePokemon(actor.pokemonList.find { it.effectedPokemon == pk.effectedPokemon }!!) },
canSelect = { pk -> canUseOnBattlePokemon(stack, actor.pokemonList.find { it.effectedPokemon == pk.effectedPokemon }!!) },
handler = { pk -> applyToBattlePokemon(player, stack, actor.pokemonList.find { it.effectedPokemon == pk.effectedPokemon }!!) }
)
@@ -0,0 +1,87 @@
/*
* 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.mark
import com.cobblemon.mod.common.Cobblemon
import com.cobblemon.mod.common.util.*
import com.google.gson.annotations.SerializedName
import net.minecraft.network.RegistryFriendlyByteBuf
import net.minecraft.network.chat.MutableComponent
import net.minecraft.resources.ResourceLocation
import net.minecraft.util.StringRepresentable
class Mark(
identifier: ResourceLocation,
val name: String,
val description: String,
val title: String?,
@SerializedName(value = "titleColor", alternate = ["titleColour"])
val titleColour: String?,
val texture: ResourceLocation,
val replace: List<ResourceLocation>?,
val group: String?,
val chance: Float = 0F,
val indexNumber: Int?
): StringRepresentable {
companion object {
internal fun decode(buffer: RegistryFriendlyByteBuf): Mark {
return Mark(
buffer.readIdentifier(),
buffer.readString(),
buffer.readString(),
buffer.readNullable { buffer.readString() },
buffer.readNullable { buffer.readString() },
buffer.readResourceLocation(),
buffer.readNullable { buffer.readList { buffer.readResourceLocation() } },
buffer.readNullable { buffer.readString() },
buffer.readFloat(),
buffer.readNullable { buffer.readInt() }
)
}
}
@Transient
var identifier: ResourceLocation = identifier
internal set
override fun getSerializedName(): String = identifier.toString()
fun getName(): MutableComponent = name.asTranslated()
fun getDescription(): MutableComponent = description.asTranslated()
fun getTitle(name: MutableComponent): MutableComponent {
title?.let {
try {
return if (titleColour != null) it.asTranslated(name.withColor(-1)).withColor(titleColour.toInt(16))
else it.asTranslated(name)
} catch (e: Exception) {
Cobblemon.LOGGER.error("Error parsing titleColor hexadecimal color code for {}", identifier, e)
return it.asTranslated(name)
}
}
return name
}
fun getChanceGroup(): Pair<String, Float> = Pair(group ?: chance.toString(), chance)
internal fun encode(buffer: RegistryFriendlyByteBuf) {
buffer.writeIdentifier(identifier)
buffer.writeString(name)
buffer.writeString(description)
buffer.writeNullable(title) { _, v -> buffer.writeString(v) }
buffer.writeNullable(titleColour) { _, v -> buffer.writeString(v) }
buffer.writeResourceLocation(texture)
buffer.writeNullable(replace) { _, v -> buffer.writeCollection(v) { _, resource -> buffer.writeResourceLocation(resource) } }
buffer.writeNullable(group) { _, v -> buffer.writeString(v) }
buffer.writeFloat(chance)
buffer.writeNullable(indexNumber) { _, v -> buffer.writeInt(v) }
}
}
@@ -0,0 +1,68 @@
/*
* 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.mark
import com.cobblemon.mod.common.Cobblemon
import com.cobblemon.mod.common.api.data.JsonDataRegistry
import com.cobblemon.mod.common.api.reactive.SimpleObservable
import com.cobblemon.mod.common.net.messages.client.data.MarkRegistrySyncPacket
import com.cobblemon.mod.common.util.adapters.IdentifierAdapter
import com.cobblemon.mod.common.util.cobblemonResource
import com.google.gson.GsonBuilder
import com.google.gson.reflect.TypeToken
import net.minecraft.resources.ResourceLocation
import net.minecraft.server.level.ServerPlayer
import net.minecraft.server.packs.PackType
object Marks: JsonDataRegistry<Mark> {
override val id: ResourceLocation = cobblemonResource("marks")
override val type: PackType = PackType.SERVER_DATA
override val observable = SimpleObservable<Marks>()
override val typeToken: TypeToken<Mark> = TypeToken.get(Mark::class.java)
override val resourcePath: String = "marks"
override val gson = GsonBuilder()
.setPrettyPrinting()
.registerTypeAdapter(ResourceLocation::class.java, IdentifierAdapter)
.create()
private val marks = hashMapOf<ResourceLocation, Mark>()
override fun reload(data: Map<ResourceLocation, Mark>) {
this.marks.clear()
data.forEach { (identifier, mark) ->
try {
mark.identifier = identifier
this.marks[identifier] = mark
} catch (e: Exception) {
Cobblemon.LOGGER.error("Skipped loading the {} mark", identifier, e)
}
}
Cobblemon.LOGGER.info("Loaded {} marks", this.marks.size)
this.observable.emit(this)
}
override fun sync(player: ServerPlayer) {
MarkRegistrySyncPacket(this.all()).sendToPlayer(player)
}
/**
* Gets all loaded [Mark]s.
*/
fun all() = this.marks.values.toList()
fun identifiers(): Collection<String> = marks.keys.toSet().map { it.toString() }
/**
* Gets a [Mark] by its [ResourceLocation].
* @param identifier The identifier of the mark.
* @return The [Mark] if loaded, otherwise null.
*/
fun getByIdentifier(identifier: ResourceLocation): Mark? = this.marks[identifier]
}
@@ -17,31 +17,20 @@ import com.bedrockk.molang.runtime.struct.VariableStruct
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.Cobblemon
import com.cobblemon.mod.common.CobblemonActivities
import com.cobblemon.mod.common.CobblemonBlockEntities
import com.cobblemon.mod.common.CobblemonMemories
import com.cobblemon.mod.common.CobblemonUnlockableWallpapers
import com.cobblemon.mod.common.*
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.mark.Marks
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.pokedex.*
import com.cobblemon.mod.common.api.pokemon.PokemonProperties
import com.cobblemon.mod.common.api.pokemon.evolution.Evolution
import com.cobblemon.mod.common.api.pokemon.stats.Stats
import com.cobblemon.mod.common.api.riding.RidingStyle
import com.cobblemon.mod.common.api.riding.stats.RidingStat
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
@@ -49,11 +38,11 @@ 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.tags.CobblemonItemTags
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.battles.actor.PokemonBattleActor
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
@@ -71,13 +60,8 @@ import com.cobblemon.mod.common.pokemon.Species
import com.cobblemon.mod.common.pokemon.evolution.variants.ItemInteractionEvolution
import com.cobblemon.mod.common.pokemon.evolution.variants.LevelUpEvolution
import com.cobblemon.mod.common.pokemon.evolution.variants.TradeEvolution
import com.cobblemon.mod.common.pokemon.riding.controllers.BirdAirController
import com.cobblemon.mod.common.pokemon.riding.states.BirdAirState
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
@@ -85,11 +69,7 @@ import net.minecraft.core.Registry
import net.minecraft.core.RegistryAccess
import net.minecraft.core.registries.BuiltInRegistries
import net.minecraft.core.registries.Registries
import net.minecraft.nbt.CompoundTag
import net.minecraft.nbt.DoubleTag
import net.minecraft.nbt.ListTag
import net.minecraft.nbt.StringTag
import net.minecraft.nbt.Tag
import net.minecraft.nbt.*
import net.minecraft.resources.ResourceKey
import net.minecraft.resources.ResourceLocation
import net.minecraft.server.MinecraftServer
@@ -98,11 +78,7 @@ 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.*
import net.minecraft.world.entity.ai.behavior.BlockPosTracker
import net.minecraft.world.entity.ai.memory.MemoryModuleType
import net.minecraft.world.entity.ai.memory.MemoryStatus
@@ -114,8 +90,12 @@ 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
import net.minecraft.world.level.levelgen.Heightmap
import net.minecraft.world.phys.AABB
import net.minecraft.world.phys.Vec3
import java.util.*
import kotlin.math.sqrt
import kotlin.random.Random
/**
* Holds a bunch of useful MoLang trickery that can be used or extended in API
@@ -236,6 +216,22 @@ object MoLangFunctions {
val z = params.getInt(2)
return@put DoubleValue(world.isRainingAt(BlockPos(x, y, z)))
}
map.put("is_snowing_at") { params ->
val x = params.getInt(0)
val y = params.getInt(1)
val z = params.getInt(2)
val blockPos = BlockPos(x, y, z)
if (!world.isRaining()) {
return@put DoubleValue.ZERO
} else if (!world.canSeeSky(blockPos)) {
return@put DoubleValue.ZERO
} else if (world.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING, blockPos).getY() > blockPos.getY()) {
return@put DoubleValue.ZERO
} else {
val biome = world.getBiome(blockPos).value() as Biome
return@put DoubleValue(biome.getPrecipitationAt(blockPos) == Biome.Precipitation.SNOW)
}
}
map.put("is_chunk_loaded_at") { params ->
val x = params.getInt(0)
val y = params.getInt(1)
@@ -291,16 +287,32 @@ object MoLangFunctions {
} 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())
}
val packet = SpawnSnowstormParticlePacket(particle, pos)
if (player != null) {
packet.sendToPlayer(player)
} else {
val effect = BedrockParticleOptionsRepository.getEffect(particle) ?: return@put DoubleValue.ZERO
ParticleStorm.createAtPosition(world, effect, pos).spawn()
packet.sendToPlayersAround(x, y, z, 64.0, world.dimension())
}
}
map.put("spawn_pokemon") { params ->
val x = params.getInt(0)
val y = params.getInt(1)
val z = params.getInt(2)
val props = params.getString(3).toProperties()
val pos = BlockPos(x, y, z)
if (!Level.isInSpawnableBounds(pos)) {
return@put DoubleValue.ZERO
}
val pokemon = props.createEntity(world)
pokemon.moveTo(pos, pokemon.yRot, pokemon.xRot)
if (world.addFreshEntity(pokemon)) {
return@put pokemon.struct
} else {
return@put DoubleValue.ZERO
}
}
map.put("get_entities_around") { params ->
@@ -469,6 +481,7 @@ object MoLangFunctions {
map.put("is_sneaking") { _ -> DoubleValue(entity.isShiftKeyDown) }
map.put("is_sprinting") { _ -> DoubleValue(entity.isSprinting) }
map.put("is_in_water") { _ -> DoubleValue(entity.isUnderWater) }
map.put("is_in_rain") { _ -> DoubleValue(entity.isInWaterOrRain && !entity.isInWater) }
map.put("is_touching_water_or_rain") { _ -> DoubleValue(entity.isInWaterRainOrBubble) }
map.put("is_touching_water") { _ -> DoubleValue(entity.isInWater) }
map.put("is_underwater") { DoubleValue(entity.getIsSubmerged()) }
@@ -740,6 +753,8 @@ object MoLangFunctions {
map.put("npc") { battleActor.entity.struct }
} else if (battleActor is PlayerBattleActor) {
map.put("player") { battleActor.entity?.asMoLangValue() ?: DoubleValue.ZERO }
} else if (battleActor is PokemonBattleActor) {
map.put("pokemon") { battleActor.entity?.asMoLangValue() ?: DoubleValue.ZERO }
}
return@mutableListOf map
}
@@ -778,6 +793,34 @@ object MoLangFunctions {
DoubleValue.ONE
}
map.put("owner") { pokemon.getOwnerPlayer()?.asMoLangValue() ?: DoubleValue.ZERO }
map.put("add_marks") { params ->
for (param in params.params) {
val identifier = param.asString().asIdentifierDefaultingNamespace()
val mark = Marks.getByIdentifier(identifier)
if (mark != null) pokemon.exchangeMark(mark, true)
}
}
map.put("add_marks_with_chance") { params ->
for (param in params.params) {
val identifier = param.asString().asIdentifierDefaultingNamespace()
val mark = Marks.getByIdentifier(identifier)
mark?.let {
val probability = it.chance.coerceIn(0F, 1F) * 100
val randomValue = Random.nextDouble(0.0, 100.0)
if (randomValue < probability) pokemon.exchangeMark(it, true)
}
}
}
map.put("add_potential_marks") { params ->
for (param in params.params) {
val identifier = param.asString().asIdentifierDefaultingNamespace()
val mark = Marks.getByIdentifier(identifier)
if (mark != null) pokemon.addPotentialMark(mark)
}
}
map.put("apply_potential_marks") {
return@put DoubleValue(pokemon.applyPotentialMarks())
}
map
}
)
@@ -788,10 +831,19 @@ object MoLangFunctions {
map.put("in_battle") { DoubleValue(pokemonEntity.isBattling) }
map.put("is_moving") { DoubleValue((pokemonEntity.moveControl as? PokemonMoveControl)?.hasWanted() == true) }
map.put("is_flying") { DoubleValue(pokemonEntity.getBehaviourFlag(PokemonBehaviourFlag.FLYING)) }
map.put("is_gliding") { DoubleValue(pokemonEntity.useRidingAltPose()) }
map.put("is_flying") { DoubleValue(pokemonEntity.getBehaviourFlag(PokemonBehaviourFlag.FLYING)) }
map.put("get_alt_pose") { StringValue(pokemonEntity.getAltPose()) }
map.put("is_gliding") { DoubleValue(pokemonEntity.isUsingAltPose(cobblemonResource("gliding"))) }
map.put("is_sprinting") { DoubleValue(pokemonEntity.isUsingAltPose(cobblemonResource("sprinting"))) }
map.put("in_air") { DoubleValue(pokemonEntity.isUsingAltPose(cobblemonResource("in_air"))) }
map.put("is_ridden") { DoubleValue(pokemonEntity.hasControllingPassenger()) }
map.put("has_aspect") { DoubleValue(it.getString(0) in pokemonEntity.aspects) }
map.put("is_pokemon") { DoubleValue.ONE }
map.put("is_holding_item") { DoubleValue(!pokemonEntity.entityData.get(PokemonEntity.SHOWN_HELD_ITEM).isEmpty) }
map.put("is_holding_item") { DoubleValue(!pokemonEntity.entityData.get(PokemonEntity.SHOWN_HELD_ITEM).let {
it.isEmpty || it.`is`(CobblemonItemTags.WEARABLE_HAT_ITEMS) || it.`is`(CobblemonItemTags.WEARABLE_FACE_ITEMS)
}) }
map.put("is_wearing_hat") { DoubleValue(pokemonEntity.entityData.get(PokemonEntity.SHOWN_HELD_ITEM).`is`(CobblemonItemTags.WEARABLE_HAT_ITEMS)) }
map.put("is_wearing_face") { DoubleValue(pokemonEntity.entityData.get(PokemonEntity.SHOWN_HELD_ITEM).`is`(CobblemonItemTags.WEARABLE_FACE_ITEMS)) }
map
}
)
@@ -1438,4 +1490,4 @@ object MoLangFunctions {
}
}
fun Either<ResourceLocation, ExpressionLike>.runScript(runtime: MoLangRuntime) = map({ CobblemonScripts.run(it, runtime) }, { it.resolve(runtime) })
fun Either<ResourceLocation, ExpressionLike>.runScript(runtime: MoLangRuntime) = map({ CobblemonScripts.run(it, runtime) }, { it.resolve(runtime) })
@@ -40,7 +40,7 @@ object Moves : DataRegistry {
override fun reload(manager: ResourceManager) {
this.allMoves.clear()
this.idMapping.clear()
val movesJson = ShowdownService.get().getMoves()
val movesJson = ShowdownService.service.getMoves()
for (i in 0 until movesJson.size()) {
val jsMove = movesJson[i].asJsonObject
val id = jsMove.get("id").asString
@@ -116,4 +116,4 @@ object Moves : DataRegistry {
this.idMapping[move.num] = move
}
}
}
@@ -19,4 +19,4 @@ interface Decodable {
*/
fun decode(buffer: RegistryFriendlyByteBuf)
}
}
@@ -25,4 +25,4 @@ interface Encodable {
*/
fun encode(buffer: RegistryFriendlyByteBuf)
}
}
@@ -0,0 +1,37 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.net.serializers
import com.cobblemon.mod.common.api.riding.stats.RidingStat
import com.cobblemon.mod.common.util.cobblemonResource
import com.cobblemon.mod.common.util.readString
import com.cobblemon.mod.common.util.writeString
import net.minecraft.network.RegistryFriendlyByteBuf
import net.minecraft.network.codec.StreamCodec
import net.minecraft.network.syncher.EntityDataSerializer
object RideBoostsDataSerializer : EntityDataSerializer<Map<RidingStat, Float>> {
val ID = cobblemonResource("ride_boosts")
fun read(buf: RegistryFriendlyByteBuf): Map<RidingStat, Float> {
return buf.readMap(
{ RidingStat.valueOf(it.readString()) },
{ it.readFloat() }
)
}
override fun copy(value: Map<RidingStat, Float>) = value.toMap()
fun write(buf: RegistryFriendlyByteBuf, value: Map<RidingStat, Float>) {
buf.writeMap(
value,
{ _, it -> buf.writeString(it.name) },
{ _, it -> buf.writeFloat(it) }
)
}
override fun codec() = StreamCodec.of(::write, ::read)
}
@@ -6,10 +6,10 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.pokemon.riding.states
package com.cobblemon.mod.common.api.net.serializers
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
object RidingStateSerializer {
class RunUpToFlightCompositeState(pokemonEntity: PokemonEntity) : CompositeState(pokemonEntity) {
var currSpeed: Double = 0.0
}
}
@@ -0,0 +1,123 @@
/*
* 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.orientation
import com.cobblemon.mod.common.util.math.geometry.toDegrees
import com.cobblemon.mod.common.util.math.geometry.toRadians
import net.minecraft.resources.ResourceLocation
import net.minecraft.util.Mth
import net.minecraft.world.entity.LivingEntity
import org.joml.Matrix3f
import org.joml.Quaternionf
import org.joml.Vector3f
import kotlin.math.asin
import kotlin.math.sign
open class OrientationController(val entity: LivingEntity) {
companion object {
val FORWARDS: Vector3f = Vector3f(0.0f, 0.0f, -1.0f)
val UP: Vector3f = Vector3f(0.0f, 1.0f, 0.0f)
val LEFT: Vector3f = Vector3f(-1.0f, 0.0f, 0.0f)
}
open var active: Boolean = false
var orientation: Matrix3f? = null
private set
private var renderOrientationO: Matrix3f? = null
private var renderOrientation: Matrix3f? = null
/** Adding this simply because it irritates me seeing `getActive` when most of this is Java. */
fun isActive() = active
fun updateOrientation(fn: (Matrix3f) -> Matrix3f?) {
if (!active) return
if (orientation == null) {
orientation = Matrix3f()
rotate(entity.yRot - 180, entity.xRot, 0f)
}
orientation = fn(orientation!!)
entity.yRot = yaw
entity.xRot = pitch
}
fun reset() {
orientation = null
renderOrientationO = null
renderOrientation = null
active = false
}
fun rotate(yaw: Float, pitch: Float, roll: Float) {
rotateYaw(yaw)
rotatePitch(pitch)
rotateRoll(roll)
}
fun getRenderOrientation(delta: Float): Quaternionf {
val old = renderOrientationO ?: renderOrientation ?: orientation
val new = renderOrientation ?: old
val oldQuat = Quaternionf().setFromUnnormalized(old)
val newQuat = Quaternionf().setFromUnnormalized(new)
oldQuat.slerp(newQuat, delta)
return oldQuat
}
fun tick() {
if (!active || orientation == null) return
renderOrientationO = renderOrientation
val current = orientation
val renderMatrix = this.renderOrientation ?: current
val renderQuat = Quaternionf().setFromUnnormalized(renderMatrix)
val targetQuat = Quaternionf().setFromUnnormalized(current)
val dampingFactor = 0.66f // We can change this factor for faster transitions
renderQuat.slerp(targetQuat, dampingFactor)
val newRenderOrientation = Matrix3f()
renderQuat.get(newRenderOrientation)
renderOrientation = newRenderOrientation
}
val forwardVector: Vector3f
get() = orientation?.transform(FORWARDS, Vector3f()) ?: Vector3f(FORWARDS)
val leftVector: Vector3f
get() = orientation?.transform(LEFT, Vector3f()) ?: Vector3f(LEFT)
val upVector : Vector3f
get() = orientation?.transform(UP, Vector3f()) ?: Vector3f(UP)
fun rotateYaw(yaw: Float) = updateOrientation { it.rotateY(-yaw.toRadians()) }
fun rotatePitch(pitch: Float) = updateOrientation { it.rotateX(-pitch.toRadians()) }
fun rotateRoll(roll: Float) = updateOrientation { it.rotateZ(-roll.toRadians()) }
val yaw: Float
get() = Mth.wrapDegrees(-FORWARDS.angleSigned(forwardVector, UP).toDegrees() + 180)
val pitch: Float
get() = Mth.wrapDegrees(-asin(forwardVector.y).toDegrees())
val roll: Float
get() = Mth.wrapDegrees(-upVector.angleSigned(UP, forwardVector).toDegrees())
fun applyGlobalYaw(deltaYawDegrees: Float) = updateOrientation { original ->
return@updateOrientation original.rotateLocalY(-deltaYawDegrees.toRadians())
}
fun applyGlobalPitch(deltaPitchDegrees: Float) = updateOrientation { original ->
val currQuat = Quaternionf().setFromUnnormalized(original)
val horzLeftVector = Vector3f(this.leftVector.x, 0.0f, this.leftVector.z)
val globalPitch = Quaternionf().fromAxisAngleRad(horzLeftVector.normalize(), -deltaPitchDegrees.toRadians())
val resultQuat = globalPitch.mul(currQuat)
return@updateOrientation Matrix3f().set(resultQuat)
}
}
@@ -20,7 +20,7 @@ object CobblemonPermissions {
@JvmStatic
val CHANGE_WALK_SPEED = this.create("${COMMAND_PREFIX}changewalkspeed", PermissionLevel.ALL_COMMANDS)
@JvmStatic
val CHANGE_JOINT_SCALE = this.create("${COMMAND_PREFIX}changejointscale", PermissionLevel.ALL_COMMANDS)
val TRANSFORM_MODEL_PART = this.create("${COMMAND_PREFIX}transformmodelpart", PermissionLevel.ALL_COMMANDS)
@JvmStatic
val CHECKSPAWNS = this.create("${COMMAND_PREFIX}checkspawns", PermissionLevel.CHEAT_COMMANDS_AND_COMMAND_BLOCKS)
@JvmStatic
@@ -90,6 +90,9 @@ object CobblemonPermissions {
@JvmStatic
val HELD_ITEM = this.create("${COMMAND_PREFIX}helditem", PermissionLevel.CHEAT_COMMANDS_AND_COMMAND_BLOCKS)
@JvmStatic
val CHANGE_MARK = this.create("${COMMAND_PREFIX}changemark", PermissionLevel.CHEAT_COMMANDS_AND_COMMAND_BLOCKS)
@JvmStatic
val PC = this.create("${COMMAND_PREFIX}pc", PermissionLevel.CHEAT_COMMANDS_AND_COMMAND_BLOCKS)
@JvmStatic
@@ -128,8 +131,12 @@ object CobblemonPermissions {
val RUN_MOLANG_SCRIPT = this.create("${COMMAND_PREFIX}runmolangscript", PermissionLevel.CHEAT_COMMANDS_AND_COMMAND_BLOCKS)
@JvmStatic
val COBBLEMON_CONFIG_RELOAD = this.create("${COMMAND_PREFIX}cobblemonconfig.reload", PermissionLevel.CHEAT_COMMANDS_AND_COMMAND_BLOCKS)
@JvmStatic
val CALCULATE_SEAT_POSITIONS = this.create("${COMMAND_PREFIX}calculateseatpositions", PermissionLevel.CHEAT_COMMANDS_AND_COMMAND_BLOCKS)
@JvmStatic
val CHANGE_BOX_COUNT = this.create("${COMMAND_PREFIX}boxcount", PermissionLevel.CHEAT_COMMANDS_AND_COMMAND_BLOCKS)
@JvmStatic
val SPECTATE_BATTLE = this.create("${COMMAND_PREFIX}spectatebattle", PermissionLevel.ALL_COMMANDS)
fun all(): Iterable<Permission> = this.permissions
@@ -77,18 +77,18 @@ object CatchRateModifiers {
/**
* Used by [PokeBalls.MOON_BALL].
* Boosts the catch rate 1.5× during Moon Phases 3 and 7 between the times of 12000 – 24000.
* 2.5× during Moon Phases 2 and 8 between the times of 12000 – 24000.
* 4× during Moon Phase 1 between the times of 12000 – 24000.
* Boosts the catch rate 1.5× during Moon Phases 2 and 6 between the times of 12000 – 24000.
* 2.5× during Moon Phases 1 and 7 between the times of 12000 – 24000.
* 4× during Moon Phase 0 between the times of 12000 – 24000.
* 1× otherwise.
*/
val MOON_PHASES: CatchRateModifier = WorldStateModifier { _, entity ->
if (entity.level().gameTime in 12000..24000)
return@WorldStateModifier 1F
when (entity.level().moonPhase) {
3, 7 -> 1.5F
2, 8 -> 2.5F
1 -> 4F
2, 6 -> 1.5F
1, 7 -> 2.5F
0 -> 4F
else -> 1F
}
}
@@ -8,7 +8,7 @@
package com.cobblemon.mod.common.api.pokemon
import com.cobblemon.mod.common.api.berry.Flavor
import com.cobblemon.mod.common.api.cooking.Flavour
import com.cobblemon.mod.common.api.pokemon.stats.Stats
import com.cobblemon.mod.common.pokemon.Nature
import com.cobblemon.mod.common.util.cobblemonResource
@@ -31,27 +31,27 @@ object Natures {
val LONELY = registerNature(
Nature(cobblemonResource("lonely"), "cobblemon.nature.lonely",
Stats.ATTACK, Stats.DEFENCE, Flavor.SPICY, Flavor.SOUR)
Stats.ATTACK, Stats.DEFENCE, Flavour.SPICY, Flavour.SOUR)
)
val BRAVE = registerNature(
Nature(cobblemonResource("brave"), "cobblemon.nature.brave",
Stats.ATTACK, Stats.SPEED, Flavor.SPICY, Flavor.SWEET)
Stats.ATTACK, Stats.SPEED, Flavour.SPICY, Flavour.SWEET)
)
val ADAMANT = registerNature(
Nature(cobblemonResource("adamant"), "cobblemon.nature.adamant",
Stats.ATTACK, Stats.SPECIAL_ATTACK, Flavor.SPICY, Flavor.DRY)
Stats.ATTACK, Stats.SPECIAL_ATTACK, Flavour.SPICY, Flavour.DRY)
)
val NAUGHTY = registerNature(
Nature(cobblemonResource("naughty"), "cobblemon.nature.naughty",
Stats.ATTACK, Stats.SPECIAL_DEFENCE, Flavor.SPICY, Flavor.BITTER)
Stats.ATTACK, Stats.SPECIAL_DEFENCE, Flavour.SPICY, Flavour.BITTER)
)
val BOLD = registerNature(
Nature(cobblemonResource("bold"), "cobblemon.nature.bold",
Stats.DEFENCE, Stats.ATTACK, Flavor.SOUR, Flavor.SPICY)
Stats.DEFENCE, Stats.ATTACK, Flavour.SOUR, Flavour.SPICY)
)
val DOCILE = registerNature(
@@ -61,27 +61,27 @@ object Natures {
val RELAXED = registerNature(
Nature(cobblemonResource("relaxed"), "cobblemon.nature.relaxed",
Stats.DEFENCE, Stats.SPEED, Flavor.SOUR, Flavor.SWEET)
Stats.DEFENCE, Stats.SPEED, Flavour.SOUR, Flavour.SWEET)
)
val IMPISH = registerNature(
Nature(cobblemonResource("impish"), "cobblemon.nature.impish",
Stats.DEFENCE, Stats.SPECIAL_ATTACK, Flavor.SOUR, Flavor.DRY)
Stats.DEFENCE, Stats.SPECIAL_ATTACK, Flavour.SOUR, Flavour.DRY)
)
val LAX = registerNature(
Nature(cobblemonResource("lax"), "cobblemon.nature.lax",
Stats.DEFENCE, Stats.SPECIAL_DEFENCE, Flavor.SOUR, Flavor.BITTER)
Stats.DEFENCE, Stats.SPECIAL_DEFENCE, Flavour.SOUR, Flavour.BITTER)
)
val TIMID = registerNature(
Nature(cobblemonResource("timid"), "cobblemon.nature.timid",
Stats.SPEED, Stats.ATTACK, Flavor.SWEET, Flavor.SPICY)
Stats.SPEED, Stats.ATTACK, Flavour.SWEET, Flavour.SPICY)
)
val HASTY = registerNature(
Nature(cobblemonResource("hasty"), "cobblemon.nature.hasty",
Stats.SPEED, Stats.DEFENCE, Flavor.SWEET, Flavor.SOUR)
Stats.SPEED, Stats.DEFENCE, Flavour.SWEET, Flavour.SOUR)
)
val SERIOUS = registerNature(
@@ -91,12 +91,12 @@ object Natures {
val JOLLY = registerNature(
Nature(cobblemonResource("jolly"), "cobblemon.nature.jolly",
Stats.SPEED, Stats.SPECIAL_ATTACK, Flavor.SWEET, Flavor.DRY)
Stats.SPEED, Stats.SPECIAL_ATTACK, Flavour.SWEET, Flavour.DRY)
)
val NAIVE = registerNature(
Nature(cobblemonResource("naive"), "cobblemon.nature.naive",
Stats.SPEED, Stats.SPECIAL_DEFENCE, Flavor.SWEET, Flavor.BITTER)
Stats.SPEED, Stats.SPECIAL_DEFENCE, Flavour.SWEET, Flavour.BITTER)
)
val MODEST = registerNature(
@@ -106,12 +106,12 @@ object Natures {
val MILD = registerNature(
Nature(cobblemonResource("mild"), "cobblemon.nature.mild",
Stats.SPECIAL_ATTACK, Stats.DEFENCE, Flavor.DRY, Flavor.SOUR)
Stats.SPECIAL_ATTACK, Stats.DEFENCE, Flavour.DRY, Flavour.SOUR)
)
val QUIET = registerNature(
Nature(cobblemonResource("quiet"), "cobblemon.nature.quiet",
Stats.SPECIAL_ATTACK, Stats.SPEED, Flavor.DRY, Flavor.SWEET)
Stats.SPECIAL_ATTACK, Stats.SPEED, Flavour.DRY, Flavour.SWEET)
)
val BASHFUL = registerNature(
@@ -121,27 +121,27 @@ object Natures {
val RASH = registerNature(
Nature(cobblemonResource("rash"), "cobblemon.nature.rash",
Stats.SPECIAL_ATTACK, Stats.SPECIAL_DEFENCE, Flavor.DRY, Flavor.BITTER)
Stats.SPECIAL_ATTACK, Stats.SPECIAL_DEFENCE, Flavour.DRY, Flavour.BITTER)
)
val CALM = registerNature(
Nature(cobblemonResource("calm"), "cobblemon.nature.calm",
Stats.SPECIAL_DEFENCE, Stats.ATTACK, Flavor.BITTER, Flavor.SPICY)
Stats.SPECIAL_DEFENCE, Stats.ATTACK, Flavour.BITTER, Flavour.SPICY)
)
val GENTLE = registerNature(
Nature(cobblemonResource("gentle"), "cobblemon.nature.gentle",
Stats.SPECIAL_DEFENCE, Stats.DEFENCE, Flavor.BITTER, Flavor.SOUR)
Stats.SPECIAL_DEFENCE, Stats.DEFENCE, Flavour.BITTER, Flavour.SOUR)
)
val SASSY = registerNature(
Nature(cobblemonResource("sassy"), "cobblemon.nature.sassy",
Stats.SPECIAL_DEFENCE, Stats.SPEED, Flavor.BITTER, Flavor.SWEET)
Stats.SPECIAL_DEFENCE, Stats.SPEED, Flavour.BITTER, Flavour.SWEET)
)
val CAREFUL = registerNature(
Nature(cobblemonResource("careful"), "cobblemon.nature.careful",
Stats.SPECIAL_DEFENCE, Stats.SPECIAL_ATTACK, Flavor.BITTER, Flavor.DRY)
Stats.SPECIAL_DEFENCE, Stats.SPECIAL_ATTACK, Flavour.BITTER, Flavour.DRY)
)
val QUIRKY = registerNature(
@@ -33,7 +33,7 @@ import com.cobblemon.mod.common.api.pokemon.moves.Learnset
import com.cobblemon.mod.common.api.pokemon.stats.Stat
import com.cobblemon.mod.common.api.pokemon.stats.Stats
import com.cobblemon.mod.common.api.reactive.SimpleObservable
import com.cobblemon.mod.common.api.riding.controller.RideController
import com.cobblemon.mod.common.api.riding.behaviour.RidingBehaviourSettings
import com.cobblemon.mod.common.api.riding.stats.RidingStatDefinition
import com.cobblemon.mod.common.api.spawning.TimeRange
import com.cobblemon.mod.common.api.types.ElementalType
@@ -48,8 +48,9 @@ import com.cobblemon.mod.common.pokemon.evolution.adapters.CobblemonRequirementA
import com.cobblemon.mod.common.pokemon.evolution.adapters.LegacyItemConditionWrapperAdapter
import com.cobblemon.mod.common.pokemon.helditem.CobblemonHeldItemManager
import com.cobblemon.mod.common.util.adapters.*
import com.cobblemon.mod.common.util.adapters.RideControllerAdapter
import com.cobblemon.mod.common.util.adapters.RidingBehaviourSettingsAdapter
import com.cobblemon.mod.common.util.cobblemonResource
import com.cobblemon.mod.common.util.ifClient
import com.google.common.collect.HashBasedTable
import com.google.gson.Gson
import com.google.gson.GsonBuilder
@@ -106,7 +107,7 @@ object PokemonSpecies : JsonDataRegistry<Species> {
.registerTypeAdapter(EggGroup::class.java, EggGroupAdapter)
.registerTypeAdapter(MobEffect::class.java, RegistryElementAdapter<MobEffect>(BuiltInRegistries::MOB_EFFECT))
.registerTypeAdapter(ItemPredicate::class.java, LegacyItemConditionWrapperAdapter)
.registerTypeAdapter(RideController::class.java, RideControllerAdapter)
.registerTypeAdapter(RidingBehaviourSettings::class.java, RidingBehaviourSettingsAdapter)
.registerTypeAdapter(RidingStatDefinition::class.java, RidingStatDefinitionAdapter)
.registerTypeAdapter(Expression::class.java, ExpressionAdapter)
.disableHtmlEscaping()
@@ -211,6 +212,11 @@ object PokemonSpecies : JsonDataRegistry<Species> {
this.speciesByDex.remove(old.resourceIdentifier.namespace, old.nationalPokedexNumber)
}
this.speciesByDex.put(species.resourceIdentifier.namespace, species.nationalPokedexNumber, species)
ifClient {
if (species.implemented) {
this.implemented.add(species)
}
}
}
}
@@ -285,4 +291,4 @@ object PokemonSpecies : JsonDataRegistry<Species> {
return "${species.resourceIdentifier.namespace}:${species.name}"
}
}
}
@@ -8,6 +8,9 @@
package com.cobblemon.mod.common.api.riding
import com.cobblemon.mod.common.api.riding.behaviour.RidingBehaviour
import com.cobblemon.mod.common.api.riding.behaviour.RidingBehaviourSettings
import com.cobblemon.mod.common.api.riding.behaviour.RidingBehaviourState
import net.minecraft.world.entity.PlayerRideableJumping
/**
@@ -20,6 +23,6 @@ interface Rideable : PlayerRideableJumping {
/**
* Denotes the manager responsible for handling any instance of riding taking place on an entity
*/
val riding: RidingManager
val riding: RidingBehaviour<RidingBehaviourSettings, RidingBehaviourState>?
}
}
@@ -6,7 +6,7 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.riding.controller
package com.cobblemon.mod.common.api.riding
import com.cobblemon.mod.common.util.readString
import com.cobblemon.mod.common.util.writeString
@@ -29,4 +29,4 @@ class RidingAnimation(
)
}
}
}
}
@@ -1,220 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.riding
import com.bedrockk.molang.runtime.MoLangRuntime
import com.bedrockk.molang.runtime.value.DoubleValue
import com.cobblemon.mod.common.Rollable
import com.cobblemon.mod.common.api.molang.MoLangFunctions.setup
import com.cobblemon.mod.common.api.riding.controller.RideController
import com.cobblemon.mod.common.api.riding.stats.RidingStat
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import com.cobblemon.mod.common.util.toProperties
import com.cobblemon.mod.common.util.withQueryValue
import net.minecraft.ChatFormatting
import net.minecraft.network.chat.Component
import net.minecraft.resources.ResourceLocation
import net.minecraft.util.SmoothDouble
import net.minecraft.world.entity.LivingEntity
import net.minecraft.world.entity.player.Player
import net.minecraft.world.phys.Vec2
import net.minecraft.world.phys.Vec3
import kotlin.math.sin
import kotlin.math.sin
data class RidingManager(val entity: PokemonEntity) {
var lastSpeed = 0F
var states: MutableMap<ResourceLocation, RidingState> = mutableMapOf()
var deltaRotation = Vec2.ZERO
val runtime: MoLangRuntime by lazy {
MoLangRuntime()
.setup()
.withQueryValue("entity", entity.struct)
.also {
it.environment.query.addFunction("passenger_count") { DoubleValue(entity.passengers.size.toDouble()) }
it.environment.query.addFunction("get_ride_stats") { params ->
val rideStat = RidingStat.valueOf(params.getString(0).uppercase())
val rideStyle = RidingStyle.valueOf(params.getString(1).uppercase())
val maxVal = params.getDouble(2)
val minVal = params.getDouble(3)
//TODO: Use the mons actual boost once implemented
val normalizedStat = entity.rideProp.calculate(rideStat, rideStyle, 0) / 100.0f
val trueStatVal = (normalizedStat * (maxVal - minVal)) + minVal
DoubleValue(trueStatVal)
}
}
}
fun <T : RidingState> getState(id: ResourceLocation, constructor: (PokemonEntity) -> T): T {
val storedState = states[id]
if (storedState == null) {
val newState = constructor(entity)
states[id] = newState
return newState
}
return storedState as T
}
fun getController(entity: PokemonEntity): RideController? {
return entity.pokemon.riding.controller?.takeIf { it.condition.invoke(entity) }
}
/**
* Responsible for handling riding conditions and transitions amongst controllers. This will tick
* whenever the entity receives a tickControlled interaction.
*/
fun tick(entity: PokemonEntity, driver: Player, input: Vec3) {
val controller = getController(entity) ?: return
val pose = controller.pose(entity)
entity.entityData.set(PokemonEntity.POSE_TYPE, pose)
//val speedPlayer = driver.deltaMovement.horizontalDistance()
//driver.displayClientMessage(Component.literal("Speed player: ").withStyle { it.withColor(ChatFormatting.GREEN) }.append(Component.literal("$speedPlayer b/t")), true)
//val speedEntity = entity.deltaMovement.length() //* 20 * 60 * 60) / ( 1000 )
//println(speedEntity)
//driver.displayClientMessage(Component.literal("Speed: ").withStyle { it.withColor(ChatFormatting.GREEN) }.append(Component.literal("${String.format("%.2f", speedEntity)} km/h")), true)
}
fun speed(entity: PokemonEntity, driver: Player): Float {
val controller = getController(entity) ?: return 0.05F
this.lastSpeed = controller.speed(entity, driver)
return this.lastSpeed
}
fun controlledRotation(entity: PokemonEntity, driver: Player): Vec2 {
val controller = getController(entity) ?: return entity.rotationVector
val previousRotation = entity.rotationVector
val rotation = controller.rotation(entity, driver)
this.deltaRotation = Vec2(rotation.x - previousRotation.x, rotation.y - previousRotation.y)
return rotation
}
fun clampPassengerRotation(entity: PokemonEntity, driver: LivingEntity) {
val controller = getController(entity) ?: return
return controller.clampPassengerRotation(entity, driver)
}
fun updatePassengerRotation(entity: PokemonEntity, driver: LivingEntity) {
val controller = getController(entity) ?: return
return controller.updatePassengerRotation(entity, driver)
}
fun velocity(entity: PokemonEntity, driver: Player, input: Vec3): Vec3 {
val controller = getController(entity) ?: return Vec3.ZERO
return controller.velocity(entity, driver, input)
}
fun setRideBar(entity: PokemonEntity, driver: Player): Float {
val controller = getController(entity) ?: return 0.0f
return controller.setRideBar(entity, driver)
}
fun rideFovMult(entity: PokemonEntity, driver: Player): Float {
val controller = getController(entity) ?: return 1.0f
return controller.rideFovMult(entity, driver)
}
fun canJump(entity: PokemonEntity, driver: Player): Boolean {
val controller = getController(entity) ?: return false
return controller.canJump(entity, driver)
}
fun jumpVelocity(entity: PokemonEntity, driver: Player, jumpStrength: Int): Vec3 {
val controller = getController(entity) ?: return Vec3.ZERO
return controller.jumpForce(entity, driver, jumpStrength)
}
fun useRidingAltPose(entity: PokemonEntity, driver: Player): Boolean {
val controller = getController(entity) ?: return false
return controller.useRidingAltPose(entity, driver)
}
/**
* Used to supply the delta for the lerp() between velocity
* vectors. Called inertia for now as the way it feels when
* affecting the ride is somewhat akin to inertia.
*/
fun inertia(entity: PokemonEntity): Double {
val controller = getController(entity) ?: return 0.5
return controller.inertia(entity)
}
fun gravity(entity: PokemonEntity, regularGravity: Double): Double? {
val controller = getController(entity) ?: return null
return controller.gravity(entity, regularGravity)
}
//Maybe should be changed to be a function that conveys:
// "turn on use our camera system function"
fun shouldRoll(entity: PokemonEntity): Boolean {
val controller = getController(entity) ?: return false
return controller.shouldRoll(entity)
}
fun shouldRotatePlayerHead(entity: PokemonEntity): Boolean {
val controller = getController(entity) ?: return false
return controller.shouldRotatePlayerHead()
}
fun shouldRotatePokemonHead(entity: PokemonEntity): Boolean {
val controller = getController(entity) ?: return false
return controller.shouldRotatePokemonHead()
}
fun rotationOnMouseXY(
entity: PokemonEntity,
driver: Player,
yMouse: Double,
xMouse: Double,
yMouseSmoother: SmoothDouble,
xMouseSmoother: SmoothDouble,
sensitivity: Double,
deltaTime: Double
): Vec3 {
val controller = getController(entity) ?: return Vec3.ZERO
return controller.rotationOnMouseXY(
entity,
driver,
yMouse,
xMouse,
yMouseSmoother,
xMouseSmoother,
sensitivity,
deltaTime
) }
/**
* Determines whether mouse input will affect the rotation of
* the rollable object. Need to remove this as it's not used anymore
*/
//I think this might better serve as a "use smoothing on angular velocity"
fun useAngVelSmoothing(entity: PokemonEntity): Boolean {
val controller = getController(entity) ?: return true
return controller.useAngVelSmoothing(entity)
}
fun turnOffOnGround(entity: PokemonEntity): Boolean {
val controller = getController(entity) ?: return false
return controller.turnOffOnGround(entity)
}
fun angRollVel(entity: PokemonEntity, driver: Player, deltaTime: Double): Vec3 {
val controller = getController(entity) ?: return Vec3(0.0, 0.0, 0.0)
return controller.angRollVel(entity, driver, deltaTime)
}
fun dismountOnShift(): Boolean {
val controller = getController(entity) ?: return false
return controller.dismountOnShift(entity)
}
}
@@ -9,54 +9,59 @@
package com.cobblemon.mod.common.api.riding
import com.bedrockk.molang.Expression
import com.cobblemon.mod.common.api.riding.controller.RideController
import com.cobblemon.mod.common.Cobblemon
import com.cobblemon.mod.common.api.riding.behaviour.RidingBehaviourSettings
import com.cobblemon.mod.common.api.riding.stats.RidingStat
import com.cobblemon.mod.common.api.riding.stats.RidingStatDefinition
import com.cobblemon.mod.common.util.adapters.RideControllerAdapter
import com.cobblemon.mod.common.util.asExpression
import com.cobblemon.mod.common.util.getString
import com.cobblemon.mod.common.util.readIdentifier
import com.cobblemon.mod.common.util.readString
import com.cobblemon.mod.common.util.writeString
import com.cobblemon.mod.common.util.*
import com.cobblemon.mod.common.util.adapters.RidingBehaviourSettingsAdapter
import net.minecraft.network.RegistryFriendlyByteBuf
class RidingProperties(
val stats: Map<RidingStat, RidingStatDefinition> = mapOf(),
val seats: List<Seat> = listOf(),
val conditions: List<Expression> = listOf(),
val controller: RideController? = null
val stats: MutableMap<RidingStat, RidingStatDefinition> = mutableMapOf(),
val seats: List<Seat> = listOf(),
val conditions: List<Expression> = listOf(),
val behaviour: RidingBehaviourSettings? = null
) {
companion object {
fun decode(buffer: RegistryFriendlyByteBuf): RidingProperties {
val stats: Map<RidingStat, RidingStatDefinition> = buffer.readMap(
{ buffer.readEnum<RidingStat>(RidingStat::class.java) },
{ RidingStatDefinition.decode(buffer) }
)
val stats: MutableMap<RidingStat, RidingStatDefinition> = buffer.readMap(
{ buffer.readEnum(RidingStat::class.java) },
{ RidingStatDefinition.decode(buffer) }
).toMutableMap()
val seats: List<Seat> = buffer.readList { _ -> Seat.decode(buffer) }
val conditions = buffer.readList { buffer.readString().asExpression() }
val controller = buffer.readNullable { _ ->
val key = buffer.readIdentifier()
val controller = RideControllerAdapter.types[key]?.getConstructor()?.newInstance() ?: error("Unknown controller key: $key")
controller.decode(buffer)
return@readNullable controller
val behaviour = buffer.readNullable { _ ->
val key = buffer.readResourceLocation()
val settings = RidingBehaviourSettingsAdapter.types[key]?.getConstructor()?.newInstance() ?: error("Unknown controller key: $key")
settings.decode(buffer)
return@readNullable settings
}
return RidingProperties(stats = stats, seats = seats, conditions = conditions, controller = controller)
return RidingProperties(stats = stats, seats = seats, conditions = conditions, behaviour = behaviour)
}
}
val canRide: Boolean
get() = seats.isNotEmpty() && controller != null
internal fun updateStatRange(stat: RidingStat, style: RidingStyle, min: Int, max: Int) {
if (!Cobblemon.config.enableDebugKeys) return
if (stats[stat] == null) {
stats[stat] = RidingStatDefinition()
}
stats[stat]!!.ranges[style] = min..max
}
fun encode(buffer: RegistryFriendlyByteBuf) {
buffer.writeMap(
stats,
{ _, stat -> buffer.writeEnum(stat) },
{ _, stat -> stat.encode(buffer) }
stats,
{ _, stat -> buffer.writeEnum(stat) },
{ _, stat -> stat.encode(buffer) }
)
buffer.writeCollection(seats) { _, seat -> seat.encode(buffer) }
buffer.writeCollection(conditions) { _, condition -> buffer.writeString(condition.getString()) }
buffer.writeNullable(controller) { _, controller -> controller.encode(buffer) }
buffer.writeNullable(behaviour) { _, behaviour ->
behaviour.encode(buffer)
}
}
fun calculate(stat: RidingStat, style: RidingStyle, boosts: Int): Float {
@@ -67,4 +72,4 @@ class RidingProperties(
fun hasStat(stat: RidingStat, style: RidingStyle): Boolean {
return stats[stat]?.ranges?.containsKey(style) == true
}
}
}
@@ -1,18 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.riding
/**
* Honestly having a base interface is probably unnecessary I'm just considering whether there's going to be some
* kind of shared state later.
*
* @author Hiroku
* @since October 6th, 2024
*/
interface RidingState
@@ -19,4 +19,4 @@ enum class RidingStyle {
LAND,
LIQUID,
AIR
}
}
@@ -9,7 +9,6 @@
package com.cobblemon.mod.common.api.riding
import com.cobblemon.mod.common.api.net.Encodable
import com.cobblemon.mod.common.api.riding.controller.RidingAnimation
import com.cobblemon.mod.common.entity.PoseType
import com.cobblemon.mod.common.util.readString
import com.cobblemon.mod.common.util.writeString
@@ -0,0 +1,93 @@
/*
* 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.riding.behaviour
import com.cobblemon.mod.common.api.riding.RidingStyle
import com.cobblemon.mod.common.entity.PoseType
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import net.minecraft.resources.ResourceLocation
import net.minecraft.util.SmoothDouble
import net.minecraft.world.entity.LivingEntity
import net.minecraft.world.entity.player.Player
import net.minecraft.world.phys.Vec2
import net.minecraft.world.phys.Vec3
/**
* Represents the behaviour of a Pokemon when being ridden.
* This is intended to contain the logic for how a Pokemon should behave when being ridden.
*
* This class should remain stateless as it is intended to be shared between multiple instances of Pokemon.
*
* @author landonjw
*/
interface RidingBehaviour<Settings : RidingBehaviourSettings, State : RidingBehaviourState> {
val key: ResourceLocation
fun getRidingStyle(settings: Settings, state: State): RidingStyle
fun isActive(settings: Settings, state: State, vehicle: PokemonEntity): Boolean
fun tick(settings: Settings, state: State, vehicle: PokemonEntity, driver: Player, input: Vec3) {}
fun pose(settings: Settings, state: State, vehicle: PokemonEntity): PoseType
fun speed(settings: Settings, state: State, vehicle: PokemonEntity, driver: Player): Float
fun clampPassengerRotation(settings: Settings, state: State, entity: PokemonEntity, driver: LivingEntity) {}
fun updatePassengerRotation(settings: Settings, state: State, entity: PokemonEntity, driver: LivingEntity) {}
fun rotation(settings: Settings, state: State, vehicle: PokemonEntity, driver: LivingEntity): Vec2
fun velocity(settings: Settings, state: State, vehicle: PokemonEntity, driver: Player, input: Vec3): Vec3
fun angRollVel(settings: Settings, state: State, vehicle: PokemonEntity, driver: Player, deltaTime: Double): Vec3
fun rotationOnMouseXY(
settings: Settings,
state: State,
vehicle: PokemonEntity,
driver: Player,
mouseY: Double,
mouseX: Double,
mouseYSmoother: SmoothDouble,
mouseXSmoother: SmoothDouble,
sensitivity: Double,
deltaTime: Double
): Vec3
fun canJump(settings: Settings, state: State, vehicle: PokemonEntity, driver: Player): Boolean
fun setRideBar(settings: Settings, state: State, vehicle: PokemonEntity, driver: Player): Float
fun jumpForce(settings: Settings, state: State, vehicle: PokemonEntity, driver: Player, jumpStrength: Int): Vec3
fun gravity(settings: Settings, state: State, vehicle: PokemonEntity, regularGravity: Double): Double
fun rideFovMultiplier(settings: Settings, state: State, vehicle: PokemonEntity, driver: Player): Float
fun useAngVelSmoothing(settings: Settings, state: State, vehicle: PokemonEntity): Boolean
fun useRidingAltPose(settings: Settings, state: State, vehicle: PokemonEntity, driver: Player): ResourceLocation
fun inertia(settings: Settings, state: State, vehicle: PokemonEntity): Double
fun shouldRoll(settings: Settings, state: State, vehicle: PokemonEntity): Boolean
fun turnOffOnGround(settings: Settings, state: State, vehicle: PokemonEntity): Boolean
fun dismountOnShift(settings: Settings, state: State, vehicle: PokemonEntity): Boolean
fun shouldRotatePokemonHead(settings: Settings, state: State, vehicle: PokemonEntity): Boolean
fun shouldRotatePlayerHead(settings: Settings, state: State, vehicle: PokemonEntity): Boolean
fun createDefaultState(settings: Settings): State
}
@@ -0,0 +1,26 @@
/*
* 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.riding.behaviour
import com.cobblemon.mod.common.api.net.Decodable
import com.cobblemon.mod.common.api.net.Encodable
import net.minecraft.resources.ResourceLocation
import net.minecraft.world.phys.Vec3
/**
* Represents static settings of a riding behaviour.
* Values in this class are intended to be constant and not change during the riding process.
* Typically this will be initialized for each pokemon form during deserialization
* to determine how they should ride.
*
* @author landonjw
*/
interface RidingBehaviourSettings: Encodable, Decodable {
val key: ResourceLocation
}
@@ -0,0 +1,95 @@
/*
* 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.riding.behaviour
import com.cobblemon.mod.common.util.ifClient
import com.cobblemon.mod.common.util.ifServer
import net.minecraft.network.FriendlyByteBuf
import net.minecraft.world.phys.Vec3
/**
* Represents the state of a Pokemon when being ridden.
* This is intended to contain mutable state that is passed between the client and server
* or temporary state that is used during the riding process.
*
* This will be destroyed when the a user dismounts the Pokemon.
*
* @author landonjw
*/
open class RidingBehaviourState {
open val rideVelocity: SidedRidingState<Vec3> = ridingState(Vec3.ZERO, Side.BOTH)
open val stamina: SidedRidingState<Float> = ridingState(1.0F, Side.BOTH)
open fun reset() {
rideVelocity.set(Vec3.ZERO, true)
stamina.set(1.0F, true)
}
open fun copy(): RidingBehaviourState {
val copy = RidingBehaviourState()
copy.rideVelocity.set(rideVelocity.get(), true)
copy.stamina.set(stamina.get(), true)
return copy
}
open fun shouldSync(previous: RidingBehaviourState): Boolean {
if (previous.rideVelocity.get() != rideVelocity.get()) return true
if (previous.stamina.get() != stamina.get()) return true
return false
}
open fun encode(buffer: FriendlyByteBuf) {
buffer.writeVec3(rideVelocity.get())
buffer.writeFloat(stamina.get())
}
open fun decode(buffer: FriendlyByteBuf) {
rideVelocity.set(buffer.readVec3(), true)
stamina.set(buffer.readFloat(), true)
}
}
fun <T> ridingState(value: T, side: Side) = SidedRidingState(value, side)
class SidedRidingState<T>(private var value: T, val side: Side) {
fun get() = value
fun set(value: T, forced: Boolean = false) {
if (forced) {
this.value = value
}
else {
when (side) {
Side.BOTH -> { this.value = value }
Side.CLIENT -> { ifClient { this.value = value } }
Side.SERVER -> { ifServer { this.value = value } }
}
}
}
override fun equals(other: Any?): Boolean {
if (other is SidedRidingState<*>) {
return value == other.value
}
return super.equals(other)
}
override fun hashCode(): Int {
return value.hashCode()
}
}
enum class Side {
SERVER, CLIENT, BOTH
}
enum class DriverSide {
LOCAL, REMOTE, BOTH
}
@@ -0,0 +1,41 @@
/*
* 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.riding.behaviour
import com.cobblemon.mod.common.api.riding.behaviour.types.*
import com.cobblemon.mod.common.api.riding.behaviour.types.composite.CompositeBehaviour
import net.minecraft.resources.ResourceLocation
object RidingBehaviours {
val behaviours = mutableMapOf<ResourceLocation, RidingBehaviour<RidingBehaviourSettings, RidingBehaviourState>>()
init {
register(BirdAirBehaviour.KEY, BirdAirBehaviour())
register(DolphinBehaviour.KEY, DolphinBehaviour())
register(GenericLandBehaviour.KEY, GenericLandBehaviour())
register(GenericSwimBehaviour.KEY, GenericSwimBehaviour())
register(GliderAirBehaviour.KEY, GliderAirBehaviour())
register(HelicopterBehaviour.KEY, HelicopterBehaviour())
register(JetAirBehaviour.KEY, JetAirBehaviour())
register(SwimDashBehaviour.KEY, SwimDashBehaviour())
register(VehicleLandBehaviour.KEY, VehicleLandBehaviour())
register(HoverBehaviour.KEY, HoverBehaviour())
register(CompositeBehaviour.KEY, CompositeBehaviour())
}
fun register(key: ResourceLocation, behaviour: RidingBehaviour<out RidingBehaviourSettings, out RidingBehaviourState>) {
if (behaviours.contains(key)) error("Behaviour already registered to key $key")
behaviours[key] = RidingController(behaviour) as RidingBehaviour<RidingBehaviourSettings, RidingBehaviourState>
}
fun get(key: ResourceLocation): RidingBehaviour<RidingBehaviourSettings, RidingBehaviourState> {
if (!behaviours.contains(key)) error("Behaviour not registered to key $key")
return behaviours[key]!!
}
}
@@ -0,0 +1,183 @@
/*
* 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.riding.behaviour
import com.cobblemon.mod.common.api.riding.RidingStyle
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import com.cobblemon.mod.common.util.cobblemonResource
import net.minecraft.resources.ResourceLocation
import net.minecraft.util.SmoothDouble
import net.minecraft.world.entity.LivingEntity
import net.minecraft.world.entity.player.Player
import net.minecraft.world.phys.Vec2
import net.minecraft.world.phys.Vec3
/**
* Small wrapper around a RidingBehaviour to provide sane defaults in the event that the behaviour is not active.
*
* @author landonjw
*/
class RidingController<Settings : RidingBehaviourSettings, State : RidingBehaviourState>(val behaviour: RidingBehaviour<Settings, State>) : RidingBehaviour<Settings, State> {
override val key = behaviour.key
override fun getRidingStyle(settings: Settings, state: State): RidingStyle {
return behaviour.getRidingStyle(settings, state)
}
override fun isActive(settings: Settings, state: State, vehicle: PokemonEntity) =
behaviour.isActive(settings, state, vehicle)
override fun tick(settings: Settings, state: State, vehicle: PokemonEntity, driver: Player, input: Vec3) =
behaviour.tick(settings, state, vehicle, driver, input)
override fun pose(settings: Settings, state: State, vehicle: PokemonEntity) =
behaviour.pose(settings, state, vehicle)
override fun speed(settings: Settings, state: State, vehicle: PokemonEntity, driver: Player): Float {
if (!isActive(settings, state, vehicle)) return 0.0F
return behaviour.speed(settings, state, vehicle, driver)
}
override fun clampPassengerRotation(settings: Settings, state: State, vehicle: PokemonEntity, driver: LivingEntity) {
if (!isActive(settings, state, vehicle)) return
return behaviour.clampPassengerRotation(settings, state, vehicle, driver)
}
override fun rotation(settings: Settings, state: State, vehicle: PokemonEntity, driver: LivingEntity): Vec2 {
if (!isActive(settings, state, vehicle)) return driver.rotationVector
return behaviour.rotation(settings, state, vehicle, driver)
}
override fun velocity(
settings: Settings,
state: State,
vehicle: PokemonEntity,
driver: Player,
input: Vec3
): Vec3 {
if (!isActive(settings, state, vehicle)) return Vec3.ZERO
return behaviour.velocity(settings, state, vehicle, driver, input)
}
override fun angRollVel(
settings: Settings,
state: State,
vehicle: PokemonEntity,
driver: Player,
deltaTime: Double
): Vec3 {
if (!isActive(settings, state, vehicle)) return Vec3.ZERO
return behaviour.angRollVel(settings, state, vehicle, driver, deltaTime)
}
override fun rotationOnMouseXY(
settings: Settings,
state: State,
vehicle: PokemonEntity,
driver: Player,
mouseY: Double,
mouseX: Double,
mouseYSmoother: SmoothDouble,
mouseXSmoother: SmoothDouble,
sensitivity: Double,
deltaTime: Double
): Vec3 {
if (!isActive(settings, state, vehicle)) return Vec3.ZERO
return behaviour.rotationOnMouseXY(
settings,
state,
vehicle,
driver,
mouseY,
mouseX,
mouseYSmoother,
mouseXSmoother,
sensitivity,
deltaTime
)
}
override fun canJump(settings: Settings, state: State, vehicle: PokemonEntity, driver: Player): Boolean {
if (!isActive(settings, state, vehicle)) return false
return behaviour.canJump(settings, state, vehicle, driver)
}
override fun shouldRotatePlayerHead(settings: Settings, state: State, vehicle: PokemonEntity): Boolean {
if (!isActive(settings, state, vehicle)) return false
return behaviour.shouldRotatePlayerHead(settings, state, vehicle)
}
override fun shouldRotatePokemonHead(settings: Settings, state: State, vehicle: PokemonEntity): Boolean {
if (!isActive(settings, state, vehicle)) return false
return behaviour.shouldRotatePokemonHead(settings, state, vehicle)
}
override fun dismountOnShift(settings: Settings, state: State, vehicle: PokemonEntity): Boolean {
if (!isActive(settings, state, vehicle)) return false
return behaviour.dismountOnShift(settings, state, vehicle)
}
override fun turnOffOnGround(settings: Settings, state: State, vehicle: PokemonEntity): Boolean {
if (!isActive(settings, state, vehicle)) return false
return behaviour.turnOffOnGround(settings, state, vehicle)
}
override fun shouldRoll(settings: Settings, state: State, vehicle: PokemonEntity): Boolean {
if (!isActive(settings, state, vehicle)) return false
return behaviour.shouldRoll(settings, state, vehicle)
}
override fun inertia(settings: Settings, state: State, vehicle: PokemonEntity): Double {
if (!isActive(settings, state, vehicle)) return 0.5
return behaviour.inertia(settings, state, vehicle)
}
override fun useRidingAltPose(settings: Settings, state: State, vehicle: PokemonEntity, driver: Player): ResourceLocation {
if (!isActive(settings, state, vehicle)) return cobblemonResource("no_pose")
return behaviour.useRidingAltPose(settings, state, vehicle, driver)
}
override fun useAngVelSmoothing(settings: Settings, state: State, vehicle: PokemonEntity): Boolean {
if (!isActive(settings, state, vehicle)) return true
return behaviour.useAngVelSmoothing(settings, state, vehicle)
}
override fun rideFovMultiplier(settings: Settings, state: State, vehicle: PokemonEntity, driver: Player): Float {
if (!isActive(settings, state, vehicle)) return 1.0F
return behaviour.rideFovMultiplier(settings, state, vehicle, driver)
}
override fun gravity(settings: Settings, state: State, vehicle: PokemonEntity, regularGravity: Double): Double {
if (!isActive(settings, state, vehicle)) return regularGravity
return behaviour.gravity(settings, state, vehicle, regularGravity)
}
override fun jumpForce(
settings: Settings,
state: State,
vehicle: PokemonEntity,
driver: Player,
jumpStrength: Int
): Vec3 {
if (!isActive(settings, state, vehicle)) return Vec3.ZERO
return behaviour.jumpForce(settings, state, vehicle, driver, jumpStrength)
}
override fun setRideBar(settings: Settings, state: State, vehicle: PokemonEntity, driver: Player): Float {
if (!isActive(settings, state, vehicle)) return 0.0F
return behaviour.setRideBar(settings, state, vehicle, driver)
}
override fun createDefaultState(settings: Settings): State {
return behaviour.createDefaultState(settings)
}
}
@@ -0,0 +1,561 @@
/*
* 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.riding.behaviour.types
import com.bedrockk.molang.Expression
import com.bedrockk.molang.runtime.MoLangMath.lerp
import com.cobblemon.mod.common.Cobblemon
import com.cobblemon.mod.common.OrientationControllable
import com.cobblemon.mod.common.api.riding.RidingStyle
import com.cobblemon.mod.common.api.riding.behaviour.*
import com.cobblemon.mod.common.api.riding.posing.PoseOption
import com.cobblemon.mod.common.api.riding.posing.PoseProvider
import com.cobblemon.mod.common.entity.PoseType
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import com.cobblemon.mod.common.pokemon.Pokemon
import com.cobblemon.mod.common.util.*
import com.cobblemon.mod.common.util.math.geometry.toRadians
import net.minecraft.client.Minecraft
import net.minecraft.network.FriendlyByteBuf
import net.minecraft.network.RegistryFriendlyByteBuf
import net.minecraft.resources.ResourceLocation
import net.minecraft.util.SmoothDouble
import net.minecraft.world.entity.LivingEntity
import net.minecraft.world.entity.player.Player
import net.minecraft.world.phys.Vec2
import net.minecraft.world.phys.Vec3
import org.joml.Vector3f
import kotlin.math.*
class BirdAirBehaviour : RidingBehaviour<BirdAirSettings, BirdAirState> {
companion object {
val KEY = cobblemonResource("air/bird")
}
override val key: ResourceLocation = KEY
override fun getRidingStyle(settings: BirdAirSettings, state: BirdAirState): RidingStyle {
return RidingStyle.AIR
}
val poseProvider = PoseProvider<BirdAirSettings, BirdAirState>(PoseType.HOVER)
.with(PoseOption(PoseType.FLY) { _, state, _ -> state.rideVelocity.get().z > 0.2 })
override fun isActive(settings: BirdAirSettings, state: BirdAirState, vehicle: PokemonEntity): Boolean {
return true
}
override fun pose(settings: BirdAirSettings, state: BirdAirState, vehicle: PokemonEntity): PoseType {
return poseProvider.select(settings, state, vehicle)
}
override fun speed(
settings: BirdAirSettings,
state: BirdAirState,
vehicle: PokemonEntity,
driver: Player
): Float {
return state.rideVelocity.get().length().toFloat()
}
override fun rotation(
settings: BirdAirSettings,
state: BirdAirState,
vehicle: PokemonEntity,
driver: LivingEntity
): Vec2 {
return Vec2(driver.xRot * 0.5f, driver.yRot)
}
override fun velocity(
settings: BirdAirSettings,
state: BirdAirState,
vehicle: PokemonEntity,
driver: Player,
input: Vec3
): Vec3 {
var yVel = 0.0
var leftForce = 0.0
var upForce = 0.0
var forwardForce = 0.0
//Perform ride velocity update
calculateRideSpaceVel(settings, state, vehicle, driver)
//Translate ride space velocity to world space velocity.
val controller = (driver as? OrientationControllable)?.orientationController
if (controller != null) {
//Need to deadzone this when straight up or down
upForce += -1.0 * sin(Math.toRadians(controller.pitch.toDouble())) * state.rideVelocity.get().z
forwardForce += cos(Math.toRadians(controller.pitch.toDouble())) * state.rideVelocity.get().z
upForce += cos(Math.toRadians(controller.pitch.toDouble())) * state.rideVelocity.get().y
forwardForce += sin(Math.toRadians(controller.pitch.toDouble())) * state.rideVelocity.get().y
}
//Bring the ride out of the sky when stamina is depleted.
if (state.stamina.get() <= 0.0) {
upForce -= 0.3
}
val altitudeLimit = vehicle.runtime.resolveDouble(settings.jumpExpr)
//Only limit altitude if altitude is not infinite
if (!vehicle.runtime.resolveBoolean(settings.infiniteAltitude)) {
//Provide a hard limit on altitude
upForce = if (vehicle.y >= altitudeLimit && upForce > 0) 0.0 else upForce
}
val velocity = Vec3(state.rideVelocity.get().x , upForce, forwardForce)
return velocity
}
/*
* Calculates the change in the ride space vector due to player input and ride state
*/
fun calculateRideSpaceVel(settings: BirdAirSettings, state: BirdAirState, vehicle: PokemonEntity, driver: Player) {
//retrieve stats
val topSpeed = vehicle.runtime.resolveDouble(settings.speedExpr)
val glideTopSpeed = vehicle.runtime.resolveDouble(settings.glidespeedExpr)
val accel = vehicle.runtime.resolveDouble(settings.accelerationExpr)
val staminaStat = vehicle.runtime.resolveDouble(settings.staminaExpr)
var glideSpeedChange = 0.0
val currSpeed = state.rideVelocity.get().length()
//Flag for determining if player is actively inputting
var activeInput = false
var newVelocity = Vec3(state.rideVelocity.get().x, state.rideVelocity.get().y, state.rideVelocity.get().z)
//speed up and slow down based on input
if (driver.zza != 0.0f && state.stamina.get() > 0.0) {
//make sure it can't exceed top speed
val forwardInput = when {
driver.zza > 0 && newVelocity.z > topSpeed -> 0.0
driver.zza < 0 && newVelocity.z < (-topSpeed / 3.0) -> 0.0
else -> driver.zza.sign
}
newVelocity = Vec3(
newVelocity.x,
newVelocity.y,
(newVelocity.z + (accel * forwardInput.toDouble())))
activeInput = true
}
val controller = (driver as? OrientationControllable)?.orientationController
if (controller != null) {
//Base glide speed change on current pitch of the ride.
glideSpeedChange = sin(Math.toRadians(controller.pitch.toDouble()))
glideSpeedChange = glideSpeedChange * 0.25
//TODO: Possibly create a deadzone around parallel where glide doesn't affect speed?
if (glideSpeedChange <= 0.0) {
//Ensures that a propelling force is still able to be applied when
//climbing in height
if (driver.zza <= 0) {
//speed decrease should be 2x speed increase?
//state.currSpeed = max(state.currSpeed + (0.0166) * glideSpeedChange, 0.0 )
newVelocity = Vec3(
newVelocity.x,
newVelocity.y,
lerp( newVelocity.z, 0.0,glideSpeedChange * -0.0166 * 2 )
)
}
} else {
// only add to the speed if it hasn't exceeded the current
//glide angles maximum amount of speed that it can give.
//state.currSpeed = min(state.currSpeed + ((0.0166 * 2) * glideSpeedChange), maxGlideSpeed)
newVelocity = Vec3(
newVelocity.x,
newVelocity.y,
min(newVelocity.z + ((0.0166 * 2) * glideSpeedChange), glideTopSpeed)
)
}
}
//Vertical movement based on driver input.
val vertTopSpeed = topSpeed / 2.0
val vertInput = when {
driver.jumping && state.rideVelocity.get().length() < 0.3 -> 1.0
driver.isShiftKeyDown && state.rideVelocity.get().length() < 0.3 -> -1.0
else -> 0.0
}
if (vertInput != 0.0 && state.stamina.get() > 0.0) {
newVelocity = Vec3(
newVelocity.x,
(newVelocity.y + (accel * vertInput)).coerceIn(-vertTopSpeed, vertTopSpeed),
newVelocity.z)
activeInput = true
}
else {
newVelocity = Vec3(
newVelocity.x,
lerp(newVelocity.y, 0.0, vertTopSpeed / 20.0),
newVelocity.z)
}
//Check if the ride should be gliding
if (driver.isLocalPlayer) {
if (activeInput && state.stamina.get() > 0.0) {
state.gliding.set(false)
} else {
state.gliding.set(true)
}
}
//TODO: Reintroduce stamina drain once stats start to be polished and tweaked
// //Only perform stamina logic if the ride does not have infinite stamina
// if (!vehicle.runtime.resolveBoolean(settings.infiniteStamina)) {
// if (activeInput) {
// state.stamina.set(state.stamina.get() - (0.05 / staminaStat).toFloat())
// }
//
// //Lose a base amount of stamina just for being airborne
// state.stamina.set(state.stamina.get() - (0.01 / staminaStat).toFloat())
// }
// else
// {
// state.stamina.set(1.0f)
// }
//air resistance
if( abs(newVelocity.z) > 0) {
newVelocity = newVelocity.subtract(0.0, 0.0, min(0.0015 * newVelocity.z.sign, newVelocity.z))
}
state.rideVelocity.set(newVelocity)
}
override fun angRollVel(
settings: BirdAirSettings,
state: BirdAirState,
vehicle: PokemonEntity,
driver: Player,
deltaTime: Double
): Vec3 {
if (driver !is OrientationControllable) return Vec3.ZERO
val controller = (driver as OrientationControllable).orientationController
//limit rolling based on handling and current speed.
//modulated by speed so that when flapping idle in air you are ont wobbling around to look around
//TODO: Tie handling into yaw rate
val handling = vehicle.runtime.resolveDouble(settings.handlingExpr)
val topSpeed = vehicle.runtime.resolveDouble(settings.speedExpr)
//This rotation limit will be used to know if the ride has exceeded it and its needs correcting.
val rotMin = 15.0
val rotLimit = max(handling * sqrt(normalizeVal(state.rideVelocity.get().length(), 0.0, topSpeed)), rotMin)
var yawDeltaDeg = deltaTime * handling * sin(Math.toRadians(controller.roll.toDouble())) //sin(Math.toRadians(controller.roll.toDouble())) * abs(cos(Math.toRadians(controller.pitch.toDouble())))
val trueYawDelt = yawDeltaDeg * abs(cos(Math.toRadians(controller.pitch.toDouble())))
//val pitchedYawDelt = yawDeltaDeg - trueYawDelt
controller.applyGlobalYaw(trueYawDelt.toFloat())
//Calculate correcting roll force.
val correctionRate = 5.0
if(abs(controller.roll) > rotLimit && state.rideVelocity.get().length() < 0.2) {
state.currRollCorrectionForce.set(
state.currRollCorrectionForce.get() + ((abs(controller.roll) - rotLimit) / 180 - rotLimit) * controller.roll.sign * correctionRate * deltaTime * 0.01
)
} else {
state.currRollCorrectionForce.set(
//reduce rollCorrection gradually
lerp(state.currRollCorrectionForce.get(), 0.0, deltaTime * 0.98)
)
}
//yaw, pitch, roll
return Vec3(0.0, 0.0, state.currRollCorrectionForce.get())
}
override fun rotationOnMouseXY(
settings: BirdAirSettings,
state: BirdAirState,
vehicle: PokemonEntity,
driver: Player,
mouseY: Double,
mouseX: Double,
mouseYSmoother: SmoothDouble,
mouseXSmoother: SmoothDouble,
sensitivity: Double,
deltaTime: Double
): Vec3 {
if (driver !is OrientationControllable) return Vec3.ZERO
val controller = (driver as OrientationControllable).orientationController
val handling = vehicle.runtime.resolveDouble(settings.handlingExpr)
val topSpeed = vehicle.runtime.resolveDouble(settings.speedExpr)
//Smooth out mouse input.
val smoothingSpeed = 4.0
val invertRoll = if (Cobblemon.config.invertRoll) -1 else 1
val invertPitch = if (Cobblemon.config.invertPitch) -1 else 1
val mouseXc = (mouseX).coerceIn(-60.0, 60.0)
val mouseYc = (mouseY).coerceIn(-60.0, 60.0)
val xInput = mouseXSmoother.getNewDeltaValue(mouseXc * 0.1 * invertRoll, deltaTime * smoothingSpeed);
val yInput = mouseYSmoother.getNewDeltaValue(mouseYc * 0.1 * invertPitch, deltaTime * smoothingSpeed);
//limit rolling based on handling and current speed.
//modulated by speed so that when flapping idle in air you are ont wobbling around to look around
val rotMin = 15.0
var rollForce = xInput
val rotLimit = max(90 * sqrt(normalizeVal(state.rideVelocity.get().length(), 0.0, topSpeed)), rotMin)
//Limit roll by non linearly decreasing inputs towards
// a rotation limit based on the current distance from
// that rotation limit
if (abs(controller.roll + rollForce) < rotLimit) {
if (sign(rollForce) == sign(controller.roll).toDouble()) {
//Grab how far the current roll is away from the roll limit
val d = abs(abs(controller.roll) - rotLimit)
rollForce *= (d.pow(2)) / (rotLimit.pow(2))
}
} else { //if (sign(rollForce) == sign(controller.roll).toDouble()) {
rollForce *= max(abs(sin(controller.pitch.toRadians())),0.1f)
}
//Give the ability to yaw with x mouse input when at low speeds.
val yawForce = xInput * ( 1.0 - sqrt(normalizeVal(state.rideVelocity.get().length(), 0.0, topSpeed)))
//Yaw locally a bit when up or down so that its more intuitive to make it out of a dive or a straight vertical
//climb
val yawForcePitched = xInput * sin(Math.toRadians(abs(controller.pitch.toDouble()))) * 0.25
//Apply yaw globally as we don't want roll or pitch changes due to local yaw when looking up or down.
if (controller.upVector.dot(Vector3f(0f,1f,0f)) > 0) {
controller.applyGlobalYaw(yawForce.toFloat())
}
// Pitch up globally
controller.applyGlobalPitch(-1 * yInput.toFloat())
// roll to 0 if pitching and not upside down. This is to prevent odd back and forth wobbling when
// pitching globally and experiencing axis changes
if (controller.upVector.dot(Vector3f(0f,1f,0f)) > 0) {
// correct roll equal to the amount the ride is pitching (yInput)
// correct roll only when near to horizontal (cos(pitch))
// correct roll proportional to how rolled the ride currently is
rollForce += controller.roll * -0.01 * abs(yInput) * abs(cos(controller.pitch.toRadians())) * abs(sin(controller.roll.toRadians()))
}
//yaw, pitch, roll
return Vec3(0.0, 0.0, rollForce)
}
/*
* Normalizes the given value between a min and a max.
* The result is clamped between 0.0 and 1.0, where 0.0 represents x is at or below min
* and 1.0 represents x is at or above it.
*/
private fun normalizeVal(x: Double, min: Double, max: Double): Double {
require(max > min) { "max must be greater than min" }
return ((x - min) / (max - min)).coerceIn(0.0, 1.0)
}
override fun canJump(
settings: BirdAirSettings,
state: BirdAirState,
vehicle: PokemonEntity,
driver: Player
): Boolean {
return false
}
override fun setRideBar(
settings: BirdAirSettings,
state: BirdAirState,
vehicle: PokemonEntity,
driver: Player
): Float {
return (state.stamina.get() / 1.0f)
}
override fun jumpForce(
settings: BirdAirSettings,
state: BirdAirState,
vehicle: PokemonEntity,
driver: Player,
jumpStrength: Int
): Vec3 {
return Vec3.ZERO
}
override fun gravity(
settings: BirdAirSettings,
state: BirdAirState,
vehicle: PokemonEntity,
regularGravity: Double
): Double {
return 0.0
}
override fun rideFovMultiplier(
settings: BirdAirSettings,
state: BirdAirState,
vehicle: PokemonEntity,
driver: Player
): Float {
val topSpeed = vehicle.runtime.resolveDouble(settings.speedExpr)
val glideTopSpeed = vehicle.runtime.resolveDouble(settings.glidespeedExpr)
//Must I ensure that topspeed is greater than minimum?
val normalizedGlideSpeed = normalizeVal(state.rideVelocity.get().length(), topSpeed, glideTopSpeed)
//Only ever want the fov change to be a max of 0.2 and for it to have non linear scaling.
return 1.0f + normalizedGlideSpeed.pow(2).toFloat() * 0.2f
}
override fun useAngVelSmoothing(
settings: BirdAirSettings,
state: BirdAirState,
vehicle: PokemonEntity
): Boolean {
return false
}
override fun useRidingAltPose(
settings: BirdAirSettings,
state: BirdAirState,
vehicle: PokemonEntity,
driver: Player
): ResourceLocation {
if (state.gliding.get()) {
return cobblemonResource("gliding")
}
return cobblemonResource("no_pose")
}
override fun inertia(settings: BirdAirSettings, state: BirdAirState, vehicle: PokemonEntity): Double {
return 0.5
}
override fun shouldRoll(settings: BirdAirSettings, state: BirdAirState, vehicle: PokemonEntity): Boolean {
return true
}
override fun turnOffOnGround(settings: BirdAirSettings, state: BirdAirState, vehicle: PokemonEntity): Boolean {
return false
}
override fun dismountOnShift(settings: BirdAirSettings, state: BirdAirState, vehicle: PokemonEntity): Boolean {
return false
}
override fun shouldRotatePokemonHead(
settings: BirdAirSettings,
state: BirdAirState,
vehicle: PokemonEntity
): Boolean {
return false
}
override fun shouldRotatePlayerHead(
settings: BirdAirSettings,
state: BirdAirState,
vehicle: PokemonEntity
): Boolean {
return true
}
override fun createDefaultState(settings: BirdAirSettings) = BirdAirState()
}
class BirdAirSettings : RidingBehaviourSettings {
override val key = BirdAirBehaviour.KEY
var infiniteAltitude: Expression = "false".asExpression()
private set
var infiniteStamina: Expression = "false".asExpression()
private set
//max y level for the ride
var jumpExpr: Expression = "q.get_ride_stats('JUMP', 'AIR', 200.0, 128.0)".asExpression()
var handlingExpr: Expression = "q.get_ride_stats('SKILL', 'AIR', 135.0, 45.0)".asExpression()
var speedExpr: Expression = "q.get_ride_stats('SPEED', 'AIR', 1.0, 0.35)".asExpression()
var accelerationExpr: Expression = "q.get_ride_stats('ACCELERATION', 'AIR', (1.0 / (20.0 * 3.0)), (1.0 / (20.0 * 8.0)))".asExpression()
var staminaExpr: Expression = "q.get_ride_stats('STAMINA', 'AIR', 120.0, 20.0)".asExpression()
var glidespeedExpr: Expression = "q.get_ride_stats('SPEED', 'AIR', 2.0, 1.0)".asExpression()
private set
override fun encode(buffer: RegistryFriendlyByteBuf) {
buffer.writeResourceLocation(key)
buffer.writeExpression(infiniteAltitude)
buffer.writeExpression(infiniteStamina)
buffer.writeExpression(glidespeedExpr)
buffer.writeExpression(jumpExpr)
buffer.writeExpression(handlingExpr)
buffer.writeExpression(speedExpr)
buffer.writeExpression(accelerationExpr)
buffer.writeExpression(staminaExpr)
}
override fun decode(buffer: RegistryFriendlyByteBuf) {
infiniteAltitude = buffer.readExpression()
infiniteStamina = buffer.readExpression()
glidespeedExpr = buffer.readExpression()
jumpExpr = buffer.readExpression()
handlingExpr = buffer.readExpression()
speedExpr = buffer.readExpression()
accelerationExpr = buffer.readExpression()
staminaExpr = buffer.readExpression()
}
}
class BirdAirState : RidingBehaviourState() {
var gliding = ridingState(false, Side.CLIENT)
var lastGlide = ridingState(-100L, Side.CLIENT)
var currRollCorrectionForce = ridingState(0.0, Side.CLIENT)
override fun encode(buffer: FriendlyByteBuf) {
super.encode(buffer)
buffer.writeFloat(stamina.get())
buffer.writeBoolean(gliding.get())
}
override fun decode(buffer: FriendlyByteBuf) {
super.decode(buffer)
gliding.set(buffer.readBoolean(), forced = true)
}
override fun reset() {
super.reset()
gliding.set(false, forced = true)
lastGlide.set(-100L, forced = true)
currRollCorrectionForce.set(0.0, forced = true)
}
override fun toString(): String {
return "BirdAirState(rideVelocity=${rideVelocity.get()}, stamina=${stamina.get()}, gliding=${gliding.get()})"
}
override fun copy() = BirdAirState().also {
it.rideVelocity.set(this.rideVelocity.get(), forced = true)
it.stamina.set(this.stamina.get(), forced = true)
it.gliding.set(this.gliding.get(), forced = true)
it.lastGlide.set(this.lastGlide.get(), forced = true)
it.currRollCorrectionForce.set(this.currRollCorrectionForce.get(), forced = true)
}
override fun shouldSync(previous: RidingBehaviourState): Boolean {
if (previous !is BirdAirState) return false
if (previous.gliding.get() != gliding.get()) return true
return super.shouldSync(previous)
}
}

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