Compare commits

..
Author SHA1 Message Date
Landon Wills 0d4eaa464a Fix event logic 2025-11-18 06:00:29 -05:00
Jackson Bowes ac3628d907 Merge branch 'ufo-turning-and-head-rot-fix' into 'main'
Fix various bugs with riding.

See merge request cable-mc/cobblemon!1998
2025-11-18 00:32:11 -06:00
jackowes 4563770835 - fix nonJumping horses from falling through to Tpose when trying to jump. The in_air flag checks for the player.jumping flag so its true for a moment. Block this from being true when horse has no jump. 2025-11-17 23:00:13 -06:00
jackowes cc80f69c47 - Fix jet bug/mishap
- Fixed ride sounds not working in multiplayer
- Made the velocity threshold lower for ridesounds so that they can be heard in more 'normal' situations.
- Revert player head rotation changes for rollables.
2025-11-17 22:56:30 -06:00
Landon 128366f9c2 Merge branch '1.7-spawns-update' into 'main'
Updated spawns for Marill, Bidoof, Rufflet, and Tadbulb lines.

See merge request cable-mc/cobblemon!1996
2025-11-18 04:43:51 +00:00
Landon ddd63ac841 Merge branch 'Aprijuice-Recipe-Change' into 'main'
Energy Root added to Aprijuice recipes & slight update to compost values.

See merge request cable-mc/cobblemon!1995
2025-11-18 03:57:18 +00:00
Veraxiel 118a682451 Updated spawns for Marill, Bidoof, Rufflet, and Tadbulb lines. 2025-11-17 22:26:13 -05:00
Landon d202efc0a9 Merge branch 'validate-op-permissions-riding' into 'main'
Add is OP player check to riding stats debug GUI

See merge request cable-mc/cobblemon!1988
2025-11-18 03:16:00 +00:00
Carmendar 81a1314493 Energy Root added to Aprijuice recipes & slight update to compost values. 2025-11-17 21:08:16 -06:00
Jackson Bowes a316329359 Merge branch 'very-minor-molang-change' into 'main'
Fix boats and truthy values

See merge request cable-mc/cobblemon!1993
2025-11-17 16:29:54 -06:00
jackowes ea59981b58 - fix ufo momentum by rotating the rideVelocity vector by the induced ride yaw. 2025-11-17 15:22:41 -06:00
JPAKx4 960460ec08 Fix Boats being 'in_air' in water and vice versa. 2025-11-17 13:58:06 -06:00
JPAKx4 8d587c5287 Fix unintendid behaviour, shouldn't actually change anything currently though. 2025-11-17 13:35:19 -06:00
Guilherme Pereira e0b79c9bab change is op check to use cobblemon permissions validator 2025-11-17 09:36:56 -03:00
Polymeta 6206330b76 Merge branch 'getting-statistical' into 'main'
Getting statistical and minor Advancement fixes

See merge request cable-mc/cobblemon!1760
2025-11-17 09:30:28 +00:00
Polymeta 7b137fbe14 Merge branch 'Saccharine-Tree-Biome-List-Update' into 'main'
Saccharine tree biome list update

See merge request cable-mc/cobblemon!1990
2025-11-17 09:21:35 +00:00
Landon 4d472d0b36 Merge branch 'molang-json-interaction' into 'main'
Molang json interaction

See merge request cable-mc/cobblemon!1934
2025-11-17 09:10:40 +00:00
Slippy fd442211d3 Change Saccharine Tree Rarity 2025-11-17 03:07:58 -06:00
Landon 144f857a3b Merge branch 'fix-blocks-traveled-requirement' into 'main'
Fix Blocks Traveled requirement

See merge request cable-mc/cobblemon!1979
2025-11-17 08:20:35 +00:00
lion 80131e57f8 Fix Blocks Traveled requirement 2025-11-17 08:20:35 +00:00
Slippy 30d89a2704 Make Saccharine Trees a little less common 2025-11-17 02:04:51 -06:00
Landon 5e147545b7 Merge branch 'advancing-advancements' into 'main'
Advancing Advancements for Cobblemon 1.7.0

See merge request cable-mc/cobblemon!1974
2025-11-17 07:59:41 +00:00
Landon e962079cda Merge branch 'remove-poke-puff' into 'main'
Disable Poké Puffs temporarily

See merge request cable-mc/cobblemon!1989
2025-11-17 07:30:41 +00:00
lion 6f934cfbd4 Disable Poké Puffs temporarily 2025-11-17 07:30:41 +00:00
MoeBoy76 47ecef81a6 fix changelog errors 2025-11-17 18:02:04 +11:00
MoeBoy76 16762ae933 Merge branch 'main' of https://gitlab.com/cable-mc/cobblemon into getting-statistical 2025-11-17 17:56:53 +11:00
MoeBoy76 ba47f6a833 remove species check from catch trigger 2025-11-17 17:56:26 +11:00
dhi_holo 522ffefd0a Stone fix and Z-fix
All Evolution Stone blocks (besides Nether Fire Stone Ore) now need Iron to mine, and Display Cases now look better in more contexts
2025-11-17 16:04:15 +10:00
dhi_holo e17ca360df Merge branch 'main' into advancing-advancements 2025-11-17 15:46:04 +10:00
Landon e18d5837af Merge branch 'riding-molang-electric-bogaloo' into 'main'
Switch asMoLangValue from the states to the behaviour to allow for more dynamic options.

See merge request cable-mc/cobblemon!1986
2025-11-17 05:15:10 +00:00
Landon 65ae67d9ac Merge branch 'disable-nvb' into 'main'
Disable third_person_view_bobbing Config.

See merge request cable-mc/cobblemon!1987
2025-11-17 05:15:08 +00:00
Paul 05c77a6156 Hitbox improvements for melee attack, also don't randomly attack piglins or slimes or creepers 2025-11-17 15:11:50 +10:00
Paul 8ae6792785 Fixed fossil substitutes not working, fixed aspects not working in fossil tank rendering, fixed slowpoke tail aspects being added to everything 2025-11-17 11:21:23 +10:00
Guilherme Pereira 5f67fc167a add is op player check to riding stats debug gui 2025-11-16 20:16:08 -03:00
JPAKx4 0eee6e8634 Merge remote-tracking branch 'origin/riding-molang-electric-bogaloo' into riding-molang-electric-bogaloo
# Conflicts:
#	common/src/main/kotlin/com/cobblemon/mod/common/api/riding/behaviour/types/air/BirdBehaviour.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/api/riding/behaviour/types/air/HoverBehaviour.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/api/riding/behaviour/types/air/JetBehaviour.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/api/riding/behaviour/types/air/RocketBehaviour.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/api/riding/behaviour/types/land/HorseBehaviour.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/api/riding/behaviour/types/land/MinekartBehaviour.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/api/riding/behaviour/types/land/VehicleBehaviour.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/api/riding/behaviour/types/liquid/BoatBehaviour.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/api/riding/behaviour/types/liquid/BurstBehaviour.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/api/riding/behaviour/types/liquid/DolphinBehaviour.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/api/riding/behaviour/types/liquid/SubmarineBehaviour.kt
2025-11-16 15:10:45 -06:00
JPAKx4 a16a7c31fe Switch asMoLangValue from the states to the behaviour to allow for more dynamic options. 2025-11-16 15:10:07 -06:00
JPAKx4 a4254df0ca Disable third_person_view_bobbing Config. 2025-11-16 12:02:25 -06:00
JPAKx4 21df52daf7 Switch asMoLangValue from the states to the behaviour to allow for more dynamic options. 2025-11-16 11:49:08 -06:00
Landon 5e81e26c69 Merge branch 'molang-riding' into 'main'
Updates to riding to work better in Molang

See merge request cable-mc/cobblemon!1984
2025-11-16 15:33:38 +00:00
Hiroku d103629fd2 Merge branch '1.7-spawns-update' into 'main'
1.7 spawns update

See merge request cable-mc/cobblemon!1983
2025-11-16 09:27:54 +00:00
JPAKx4 6e2a0cd3b9 Switch to using ObjectValues for states to support riding styles with multiple properties. Added a few useful properties that can now be accessed through get_riding_state(name). 2025-11-16 07:12:59 +00:00
Veraxiel 37f6010381 Edit to Popplio line spawns. 2025-11-15 23:44:38 -05:00
Hiroku 798dd64f84 Merge branch 'RestoreSheepShearing' into 'main'
Restore Sheep Shearing

See merge request cable-mc/cobblemon!1982
2025-11-16 03:43:58 +00:00
Paul c1acf8494c Slowpoke tails are snipped a bit less short 2025-11-16 13:15:44 +10:00
Veraxiel d4601326a7 Removed Water and Lava block tags. Updated spawns using those tags to use the blocks directly. 2025-11-15 22:09:50 -05:00
JazzMcNade a037af6948 Allow herding sheep to eat grass, fix typo 2025-11-15 20:55:58 -06:00
JazzMcNade 517ac94b8d Restore sheep shearing and eating grass to restore wool 2025-11-15 20:26:31 -06:00
Paul b5ec2b28fd Merge remote-tracking branch 'origin/main' 2025-11-16 12:14:50 +10:00
Paul f45a4b784b Fixed percentSum being exceeded during multi-pass spawns, closes #1778 2025-11-16 12:14:35 +10:00
Hiroku 91dda046d8 Merge branch 'revert-transition-logic' into 'main'
Revert transition logic so land mounts can be consistently mounted

See merge request cable-mc/cobblemon!1981
2025-11-16 01:47:59 +00:00
Landon Wills 49577d2518 Revert transition logic so land mounts can be consistently mounted 2025-11-15 19:29:36 -05:00
Landon 2bad8ec673 Merge branch 'implement_pokemon' into 'main'
Implement pokemon

See merge request cable-mc/cobblemon!1945
2025-11-15 22:44:48 +00:00
Carmendar 1524e9c476 smol species fixes. 2025-11-15 15:55:14 -06:00
Carmendar c8ad0cd7e7 Merge branch 'main' into implement_pokemon
# Conflicts:
#	common/src/main/resources/data/cobblemon/species/generation1/aerodactyl.json
#	common/src/main/resources/data/cobblemon/species/generation1/arcanine.json
#	common/src/main/resources/data/cobblemon/species/generation1/blastoise.json
#	common/src/main/resources/data/cobblemon/species/generation1/charizard.json
#	common/src/main/resources/data/cobblemon/species/generation1/dewgong.json
#	common/src/main/resources/data/cobblemon/species/generation1/dragonite.json
#	common/src/main/resources/data/cobblemon/species/generation1/gyarados.json
#	common/src/main/resources/data/cobblemon/species/generation1/lapras.json
#	common/src/main/resources/data/cobblemon/species/generation1/mrmime.json
#	common/src/main/resources/data/cobblemon/species/generation1/nidoking.json
#	common/src/main/resources/data/cobblemon/species/generation1/parasect.json
#	common/src/main/resources/data/cobblemon/species/generation1/rhydon.json
#	common/src/main/resources/data/cobblemon/species/generation1/rhyhorn.json
#	common/src/main/resources/data/cobblemon/species/generation1/seaking.json
#	common/src/main/resources/data/cobblemon/species/generation1/tauros.json
#	common/src/main/resources/data/cobblemon/species/generation1/venusaur.json
#	common/src/main/resources/data/cobblemon/species/generation2/ariados.json
#	common/src/main/resources/data/cobblemon/species/generation2/forretress.json
#	common/src/main/resources/data/cobblemon/species/generation2/girafarig.json
#	common/src/main/resources/data/cobblemon/species/generation2/heracross.json
#	common/src/main/resources/data/cobblemon/species/generation2/piloswine.json
#	common/src/main/resources/data/cobblemon/species/generation2/ursaring.json
#	common/src/main/resources/data/cobblemon/species/generation3/altaria.json
#	common/src/main/resources/data/cobblemon/species/generation3/camerupt.json
#	common/src/main/resources/data/cobblemon/species/generation3/claydol.json
#	common/src/main/resources/data/cobblemon/species/generation3/flygon.json
#	common/src/main/resources/data/cobblemon/species/generation3/latias.json
#	common/src/main/resources/data/cobblemon/species/generation3/latios.json
#	common/src/main/resources/data/cobblemon/species/generation3/metagross.json
#	common/src/main/resources/data/cobblemon/species/generation3/relicanth.json
#	common/src/main/resources/data/cobblemon/species/generation3/salamence.json
#	common/src/main/resources/data/cobblemon/species/generation3/sharpedo.json
#	common/src/main/resources/data/cobblemon/species/generation3/slaking.json
#	common/src/main/resources/data/cobblemon/species/generation3/tropius.json
#	common/src/main/resources/data/cobblemon/species/generation3/wailmer.json
#	common/src/main/resources/data/cobblemon/species/generation3/wailord.json
#	common/src/main/resources/data/cobblemon/species/generation4/bastiodon.json
#	common/src/main/resources/data/cobblemon/species/generation4/bronzong.json
#	common/src/main/resources/data/cobblemon/species/generation4/drifblim.json
#	common/src/main/resources/data/cobblemon/species/generation4/dusknoir.json
#	common/src/main/resources/data/cobblemon/species/generation4/garchomp.json
#	common/src/main/resources/data/cobblemon/species/generation4/gastrodon.json
#	common/src/main/resources/data/cobblemon/species/generation4/lickilicky.json
#	common/src/main/resources/data/cobblemon/species/generation4/magnezone.json
#	common/src/main/resources/data/cobblemon/species/generation4/mamoswine.json
#	common/src/main/resources/data/cobblemon/species/generation4/rhyperior.json
#	common/src/main/resources/data/cobblemon/species/generation4/staraptor.json
#	common/src/main/resources/data/cobblemon/species/generation4/togekiss.json
#	common/src/main/resources/data/cobblemon/species/generation5/bouffalant.json
#	common/src/main/resources/data/cobblemon/species/generation5/braviary.json
#	common/src/main/resources/data/cobblemon/species/generation5/crustle.json
#	common/src/main/resources/data/cobblemon/species/generation5/darmanitan.json
#	common/src/main/resources/data/cobblemon/species/generation5/golurk.json
#	common/src/main/resources/data/cobblemon/species/generation5/hydreigon.json
#	common/src/main/resources/data/cobblemon/species/generation5/klinklang.json
#	common/src/main/resources/data/cobblemon/species/generation5/serperior.json
#	common/src/main/resources/data/cobblemon/species/generation5/volcarona.json
#	common/src/main/resources/data/cobblemon/species/generation5/zebstrika.json
#	common/src/main/resources/data/cobblemon/species/generation6/gogoat.json
#	common/src/main/resources/data/cobblemon/species/generation6/noivern.json
#	common/src/main/resources/data/cobblemon/species/generation6/skiddo.json
#	common/src/main/resources/data/cobblemon/species/generation6/tyrantrum.json
#	common/src/main/resources/data/cobblemon/species/generation7/dhelmise.json
#	common/src/main/resources/data/cobblemon/species/generation7/mudsdale.json
#	common/src/main/resources/data/cobblemon/species/generation8/corviknight.json
#	common/src/main/resources/data/cobblemon/species/generation8/dragapult.json
#	common/src/main/resources/data/cobblemon/species/generation8a/sneasler.json
#	common/src/main/resources/data/cobblemon/species/generation8a/ursaluna.json
#	common/src/main/resources/data/cobblemon/species/generation8a/wyrdeer.json
#	common/src/main/resources/data/cobblemon/species/generation9/cyclizar.json
#	common/src/main/resources/data/cobblemon/species/generation9/dondozo.json
#	common/src/main/resources/data/cobblemon/species/generation9/dudunsparce.json
#	common/src/main/resources/data/cobblemon/species/generation9/espathra.json
#	common/src/main/resources/data/cobblemon/species/generation9/farigiraf.json
#	common/src/main/resources/data/cobblemon/species/generation9/kilowattrel.json
#	common/src/main/resources/data/cobblemon/species/generation9/orthworm.json
#	common/src/main/resources/data/cobblemon/species/generation9/revavroom.json
2025-11-15 15:53:14 -06:00
Landon db1108f7ef Merge branch 'more-more-riding-fixes' into 'main'
Bunch of riding fixes

See merge request cable-mc/cobblemon!1978
2025-11-15 20:53:21 +00:00
Kenji_64 33a4e31b60 Fixed Wartortle's shiny shell not being green 2025-11-15 19:51:14 +01:00
Test 7cb4e96a64 Merge branch 'main' of https://gitlab.com/cable-mc/cobblemon 2025-11-15 12:49:39 -05:00
Test ef0f997682 asset updates 2025-11-15 12:48:58 -05:00
Paul 2988a29e28 Merge remote-tracking branch 'origin/main' 2025-11-15 21:59:56 +10:00
Paul fe59748bf6 Rescraped - fixed inverted fire immunity and implemented explicit drowsy and rouse chances 2025-11-15 21:59:47 +10:00
Polymeta 0235bc108e Merge branch '1.7-spawns-update' into 'main'
Fix to Cursola spawn. Updated Dreepy line spawns.

See merge request cable-mc/cobblemon!1980
2025-11-15 10:45:18 +00:00
Carmendar 1526c2f037 Merge branch 'main' into implement_pokemon 2025-11-15 04:30:45 -06:00
Carmendar 408cf8c5ca One last poser tweak for the night. 2025-11-15 04:29:59 -06:00
Hiroku 895f8877b1 Merge branch 'neo-fixes-sometimes' into 'main'
Handful of bug fixes, probably more to come.

Closes #1215, #1341, #1719, and #1740

See merge request cable-mc/cobblemon!1975
2025-11-15 10:18:40 +00:00
Neovitalism aab4f3c7aa I like my kneecaps. 2025-11-15 03:31:28 -06:00
violet ceb70dbf2d Merge remote-tracking branch 'origin/implement_pokemon' into implement_pokemon 2025-11-15 04:26:14 -05:00
Carmendar 6d46992ad7 More poser tweaks. 2025-11-15 03:25:53 -06:00
violet 84242194ba fixed drampa look 2025-11-15 04:25:52 -05:00
violet 529e4bef46 fixed espurr line posers 2025-11-15 04:07:10 -05:00
violet aa1658bb5d fixed alolan muk's portrait 2025-11-15 03:55:16 -05:00
violet 068df2b138 added eelektross and eelektrik placeholder animations + fixed look animations 2025-11-15 03:47:56 -05:00
Veraxiel 6fe68e117f Fix to Cursola spawn. Updated Dreepy line spawns. 2025-11-15 03:33:21 -05:00
Neovitalism 0724c21509 initialize instead 2025-11-15 01:56:38 -06:00
Carmendar 3499758203 Darmanitan Zen poser fix. 2025-11-15 00:29:54 -06:00
Landon 330f60f2d9 Merge branch 'slowpoke-snip' into 'main'
Slowpoke tail snip snip

See merge request cable-mc/cobblemon!1973
2025-11-15 06:28:09 +00:00
RedGenesectNinja 7d97df3407 Fixed Shiny Spring, Summer and Winter Sawsbuck using the wrong models 2025-11-15 00:17:06 -06:00
Paul dfb8ff5aa2 Removed time check that should not be there 2025-11-15 16:11:24 +10:00
Carmendar 22b0e0612a Vanillite line shiny textures for real. 2025-11-14 23:57:48 -06:00
Carmendar e52c63d565 Metagross jump stat adjustment. 2025-11-14 23:52:45 -06:00
Carmendar fe7f72cb3d Merge remote-tracking branch 'origin/implement_pokemon' into implement_pokemon 2025-11-14 23:51:50 -06:00
Carmendar 8187905987 Adjusted walk speed for Gogoat. 2025-11-14 23:51:04 -06:00
RedGenesectNinja 11b3043e6c Merge remote-tracking branch 'origin/implement_pokemon' into implement_pokemon 2025-11-14 22:47:24 -06:00
RedGenesectNinja 8d871ac949 Fixed Dragonair's shiny not working 2025-11-14 22:47:04 -06:00
Carmendar 8f7a523404 stat tweaks. 2025-11-14 22:40:22 -06:00
jackowes 7a74c72df2 - Fix hover not being able to be mounted on the ground and autodismounting you when you touch ground. Theres more changes tatn I thought it would have needed here... so hopefully nothing breaks. 2025-11-14 21:19:14 -06:00
Hiroku 31b136af05 Merge branch 'minor-code-cleanup' into 'main'
Attempted to fix stuff that failed, but at least I did some house cleaning.

See merge request cable-mc/cobblemon!1977
2025-11-15 02:50:07 +00:00
Hiroku 592e438c56 Merge branch 'pokedex-zoom' into 'main'
Fix pokedex zooming sensitivity.

See merge request cable-mc/cobblemon!1976
2025-11-15 02:47:22 +00:00
Carmendar bb98992635 Surface mount tweaks. 2025-11-14 20:02:34 -06:00
JPAKx4 abdc03be8c Fix pokedex zooming sensitivity. 2025-11-14 20:02:27 -06:00
JPAKx4 bfcc4516ff Attempted to fix stuff that failed, but at least I did some house cleaning. 2025-11-14 19:50:42 -06:00
Paul a4a46d20cd missed a lil sumtin [skip-ci] 2025-11-15 11:17:36 +10:00
Paul 12ec7b1e3d Merge remote-tracking branch 'origin/main' 2025-11-15 11:16:24 +10:00
Paul 6fcbbb1e73 Removed tooltip for mob effect values since it's meant to be a secret 2025-11-15 11:16:16 +10:00
Landon Wills d3984843e2 Run scraper 2025-11-14 19:32:31 -05:00
Carmendar 7a14c51df2 Merge remote-tracking branch 'origin/implement_pokemon' into implement_pokemon 2025-11-14 18:05:45 -06:00
Carmendar a7b023203f Merge branch 'main' into implement_pokemon 2025-11-14 18:04:18 -06:00
jackowes 81a241d4a1 - Make in_air more sophisticated to allow for jump animations to start more in line with when the vehicle actually jumps.
- Allow player head rotations on UFO/hover, jet, dolphin, and submarine.
2025-11-14 16:41:21 -06:00
jackowes 7ccb05fcb9 - Fixed incorrect hover transition velocity handoff.
- Fixed metagross walking in air
2025-11-14 16:06:48 -06:00
jackowes 32e81eff4e - Adjust jet running out of stamina to be more forgiving and graceful. Also remove the accidental ability to hover in air sort of after stamina drains.
- Change getRenderOrientation to return true orientation so that when you are the driver of the entity then it mirrors orientation. This is because you are the client that sets the rotation and interoplation is not needed.
2025-11-14 12:39:57 -06:00
jackowes 4ea704bd95 - Make remember ride camera default to false. 2025-11-14 11:07:39 -06:00
jackowes 497a686599 - make the motion sick camera have 0 roll. 2025-11-14 10:54:35 -06:00
jackowes b986823b2c - Fix rocket transition when in water.
- Fix transitions to water for all styles. (Was previously not allowing land to transition to if it was in water but its head was out of water)
2025-11-14 10:39:26 -06:00
Neovitalism 534a7e67e1 Merge branch 'main' into neo-fixes-sometimes 2025-11-14 10:20:02 -06:00
Neovitalism e47f014ebd Anti Team Rocket
Fixes two old bugs to stop players from stealing NPC pokémon.

For some reason, even though pokemon are added to an NPCPartyStore, their storeCoordinates are completely unset, acting as if nobody owns it. This is a good enough solution until it can be further looked into where the party is built, I'm just not knowledgeable enough in that department currently.

Fixes https://gitlab.com/cable-mc/cobblemon/-/issues/1215 and https://gitlab.com/cable-mc/cobblemon/-/issues/1341
2025-11-14 10:18:41 -06:00
Polymeta 651ba5b9ba move vanilla fix into fabric mixin as it breaks neoforge
Signed-off-by: Polymeta <40173118+Polymeta@users.noreply.github.com>
2025-11-14 16:12:45 +00:00
MoeBoy76 2b64174cfe fix input order which causes logic bug 2025-11-15 00:56:58 +11:00
MoeBoy76 918282893c Merge branch 'main' of https://gitlab.com/cable-mc/cobblemon into getting-statistical 2025-11-15 00:50:37 +11:00
Paul 74435945e9 Removed tooltip for food values since it's a bit redundant 2025-11-14 23:20:42 +10:00
Paul 6bf5e1491d Removed poke puffs access until it can be rebalanced 2025-11-14 23:14:22 +10:00
Hiroku 488f38c690 Merge branch 'removable-features' into 'main'
Adds the ability to hide certain features from rendering in the StatsWidget.

See merge request cable-mc/cobblemon!1914
2025-11-14 12:39:40 +00:00
violet dbbca02619 centiskorch texture tweaks 2025-11-14 05:52:46 -05:00
violet c50d5841d8 Merge remote-tracking branch 'origin/implement_pokemon' into implement_pokemon 2025-11-14 05:51:05 -05:00
violet 5489cfb4b0 fixed bellibolt's look anims 2025-11-14 05:39:07 -05:00
violet e421de547f SLOWPOKE TAILS NOW DROP WHEN YOU KILL THEM 2025-11-14 05:30:24 -05:00
violet 075dcdb9e9 BRAND NEW COBBLEMON EXCLUSIVE FURFROU FORMS PROPERLY IMPLEMENTED 2025-11-14 04:53:22 -05:00
Carmendar 2ebe8d6434 breach jump for Dragapult 2025-11-14 02:53:18 -06:00
Carmendar d7c77f5f3f a few ride stats adjusted ahead of scraper 2025-11-14 02:50:10 -06:00
Carmendar 572682a23a Merge branch 'main' into implement_pokemon 2025-11-14 01:36:27 -06:00
Carmendar 6241865f95 Grounded again 2025-11-14 01:34:02 -06:00
dhi_holo 67dbda3113 Final Checks
Fixed the icons being outdated formattings, we are good to gold
2025-11-14 17:33:33 +10:00
Carmendar c50d3183e6 Submarine expression tweak 2025-11-14 01:22:35 -06:00
dhi_holo 9eae394ff5 Merge branch 'advancing-advancements' of https://gitlab.com/cable-mc/cobblemon into advancing-advancements 2025-11-14 17:15:14 +10:00
MoeBoy76 76b640984c changelog
[skip-ci]
2025-11-14 18:13:40 +11:00
dhi_holo 72d142a781 Merge branch 'main' into advancing-advancements 2025-11-14 17:08:21 +10:00
MoeBoy76 af1df22e4d ride stat trigger logic finalisation, added getBaseRideStat method to check the minimum value of a stat and updated the advancement 2025-11-14 18:07:15 +11:00
Landon d1b7dc6934 Merge branch 'making-pi-equal-3' into 'main'
Fix major camera issues.

See merge request cable-mc/cobblemon!1972
2025-11-14 06:58:05 +00:00
Neovitalism e2fdf3cffc Change Species#create() to use the species identifier.
Uses the identifier for the species in the name when using Species#create to avoid discrepancies between the name and identifier causing issues. (Like in the case of Type: Null, Farfetch'd, Ho-oh, and many others.)

Fixes https://gitlab.com/cable-mc/cobblemon/-/issues/1740 - thanks for finding this one!
2025-11-14 00:49:31 -06:00
Paul 4a68e53968 Slowpoke tail snip snip 2025-11-14 16:44:09 +10:00
JPAKx4 282bb4784e Accessor grabs the wrong forwards (FORWARDS vs forwards, what is this VIM?) so make it not do that. Fixes the major camera issues from the last two days. 2025-11-14 00:10:24 -06:00
dhi_holo 66787bfea4 Merge branch 'main' into advancing-advancements 2025-11-14 15:03:10 +10:00
dhi_holo c113e68488 Moomoo Mistake
Fixed lang string for moomoo milk tooltip
2025-11-14 15:03:05 +10:00
Hiroku a8267b8ee0 Merge branch 'molang-oh-molang' into 'main'
Removed the additional DoubleValue in seen_credits and is_in_dialogue

See merge request cable-mc/cobblemon!1971
2025-11-14 05:00:28 +00:00
Spicy 81f36b2b15 Removed the additional DoubleValue in seen_credits and is_in_dialogue 2025-11-13 22:49:10 -06:00
Hiroku 73e96740d6 Merge branch 'something-funny-and-creative-dot-mp4' into 'main'
Add 180deg rotation, I should test better for sure.

See merge request cable-mc/cobblemon!1970
2025-11-14 04:06:23 +00:00
JPAKx4 d53f9e5c63 Add 180deg rotation, I should test better for sure. 2025-11-13 21:20:11 -06:00
Hiroku 560bd75fd0 Merge branch 'fix/vanilla-connection' into 'main'
fix: fix vanilla connection with the cobblemon mods

See merge request cable-mc/cobblemon!1969
2025-11-14 02:30:25 +00:00
Paul 8850d38820 Rescraped behaviours to amend swim ability 2025-11-14 11:18:23 +10:00
Carmendar 8284b04426 Merge branch 'main' into implement_pokemon
# Conflicts:
#	common/src/main/resources/data/cobblemon/species/generation1/rattata.json
#	common/src/main/resources/data/cobblemon/species/generation2/unown.json
#	common/src/main/resources/data/cobblemon/species/generation3/latias.json
#	common/src/main/resources/data/cobblemon/species/generation3/latios.json
#	common/src/main/resources/data/cobblemon/species/generation3/shuppet.json
#	common/src/main/resources/data/cobblemon/species/generation5/hydreigon.json
#	common/src/main/resources/data/cobblemon/species/generation5/volcarona.json
#	common/src/main/resources/data/cobblemon/species/generation9/wiglett.json
2025-11-13 18:16:41 -06:00
Neovitalism ca91d42ddf Shuffle around PlayerMixin#getDataFromShoulderPokemon
Fixes https://gitlab.com/cable-mc/cobblemon/-/issues/1719
Removes unnecessary logic from the server by putting it into the clientside block.
2025-11-13 18:06:47 -06:00
terrainwax 34232b33c7 fix: fix vanilla connection with the cobblemon mods 2025-11-13 22:30:12 +01:00
Landon 03c5a34fc8 Merge branch 'mixin-fix' into 'main'
Avoid relying on local player in common mixin

See merge request cable-mc/cobblemon!1968
2025-11-13 17:29:19 +00:00
Landon Wills 866db3d350 Avoid relying on local player in common mixin 2025-11-13 11:44:02 -05:00
Landon ee51a8a34b Merge branch 'more-misc-additions' into 'main'
More misc additions

See merge request cable-mc/cobblemon!1950
2025-11-13 13:18:32 +00:00
Deltric 2769733c51 More misc additions 2025-11-13 13:18:32 +00:00
dhi_holo f1bdaad97d Merge branch 'main' into advancing-advancements 2025-11-13 19:29:15 +10:00
dhi_holo f725e5fcba Improve max_ride_stats description 2025-11-13 19:28:40 +10:00
Landon 8ae79d8e44 Merge branch 'jackowes-riding-fixes' into 'main'
various riding bug fixes

See merge request cable-mc/cobblemon!1966
2025-11-13 09:28:17 +00:00
violet 2237e1eeca added missing emissive textures for magmar, magmortar, torracat, incineroar, sizzlipede, & centiskorch 2025-11-13 04:24:36 -05:00
Hiroku 6f08d610eb Merge branch 'we-dont-hang-anymore' into 'main'
Fixes Fabric server hanging on shutdown while players are logged in

See merge request cable-mc/cobblemon!1964
2025-11-13 09:19:04 +00:00
Hiroku 75f3db16aa Merge branch 'more-poke-snack-stuff' into 'main'
More Poké Snack stuff

Closes #1761

See merge request cable-mc/cobblemon!1931
2025-11-13 09:11:53 +00:00
Hiroku e4ee6b29ab Merge branch 'remove-shadow-people' into 'main'
Remove shadow people from appearing on mounts

See merge request cable-mc/cobblemon!1967
2025-11-13 09:08:42 +00:00
Watuneni iteite cb6b2b9ec5 Translated using Weblate (Japanese)
Currently translated at 94.3% (8447 of 8957 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/ja/
2025-11-13 09:07:00 +00:00
geumu 8eafe14f66 Translated using Weblate (Korean)
Currently translated at 61.5% (5513 of 8957 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/ko/
2025-11-13 09:07:00 +00:00
Paul 8176e14981 Merge remote-tracking branch 'weblate/lang-updates' 2025-11-13 19:05:24 +10:00
Paul 7d956500f2 Scraped behaviours 2025-11-13 19:04:55 +10:00
Landon Wills c6853b84a6 Remove shadow people from appearing on mounts 2025-11-13 03:58:59 -05:00
dhi_holo bb54f8414e Merge branch 'main' into advancing-advancements 2025-11-13 18:17:07 +10:00
Carmendar 99c7d39705 Grounded. 2025-11-13 01:42:08 -06:00
Polymeta 3cb4984d51 Merge branch 'shine-bright-like-an-evo-stone' into 'main'
Update Lighting Values

See merge request cable-mc/cobblemon!1951
2025-11-13 07:30:10 +00:00
dhi_holo 930ed59234 Update Lighting Values 2025-11-13 07:30:10 +00:00
jackowes 3ea1918bc2 - Fix hand rotations on mount. The mixin that fixes it wasn't adjusted for the orientation refactor. 2025-11-13 00:55:11 -06:00
Carmendar bdd27078b5 Merge branch 'main' into implement_pokemon 2025-11-13 00:33:06 -06:00
jackowes 1dee9bc630 - Move game pause orientation protections to only the lerp factor. This is to prevent camera lerping while the game is paused. It was previously at the top of the setRotations CameraMixin function which would convert you back to vanilla rotations when paused.
- clamp local rideXrotations
- Fix player head rotations while riding.
- Lessen upwards boost on takeoff
2025-11-12 23:09:06 -06:00
Landon d761f2b4dc Merge branch 'riding-go-brr' into 'main'
Many Riding Fixes

See merge request cable-mc/cobblemon!1963
2025-11-13 04:56:11 +00:00
Test 0d6028706d Merge branch 'main' of https://gitlab.com/cable-mc/cobblemon 2025-11-12 23:15:25 -05:00
Test 63d6851482 disable sacch dispenser interaction for now 2025-11-12 23:15:04 -05:00
dhi_holo 7c3fdbc921 Merge branch 'main' into advancing-advancements 2025-11-13 14:06:59 +10:00
RedGenesectNinja 9596f08957 Fixed Dusknoir's shiny not working and Updated Bronzong's textures 2025-11-12 21:12:00 -06:00
MoeBoy76 d9433960cd fml, forgot the license 2025-11-13 13:09:02 +11:00
MoeBoy76 89b6fd56b6 Merge remote-tracking branch 'origin/getting-statistical' into getting-statistical 2025-11-13 12:52:58 +11:00
MoeBoy76 10c441e3cd worked out rod casting, updated changelog 2025-11-13 12:52:36 +11:00
MoeBoy76 461b22efa8 Merge branch 'main' of https://gitlab.com/cable-mc/cobblemon into getting-statistical
# Conflicts:
#	common/src/main/resources/assets/cobblemon/lang/en_us.json
2025-11-13 12:44:17 +11:00
Carmendar 57a19909aa Merge branch 'main' into implement_pokemon 2025-11-12 19:32:00 -06:00
MoeBoy76 dc1473919e riding trigger added, added empty_bait check to reel in trigger 2025-11-13 12:24:16 +11:00
Carmendar ee20986ee0 Merge remote-tracking branch 'origin/implement_pokemon' into implement_pokemon 2025-11-12 19:23:57 -06:00
RedGenesectNinja 436aa5ea75 Updated textures for a handful of Pokemon 2025-11-12 19:14:19 -06:00
Carmendar e49f761417 Poser fixes and cries added. 2025-11-12 19:09:38 -06:00
Carmendar 95e3ab213a anim fixes for Scorbunny and Sneasler 2025-11-12 18:48:14 -06:00
Apion 7c3158c63b Merge branch 'particle-sounds-1.7' into 'main'
Refactored move sound file names, added all new move sounds

See merge request cable-mc/cobblemon!1965
2025-11-13 00:35:43 +00:00
Teggy e9e41933fe Translated using Weblate (Spanish)
Currently translated at 84.6% (7578 of 8957 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/es/
2025-11-13 00:30:11 +00:00
Nico Merenq 7c7fd6c982 Translated using Weblate (Russian)
Currently translated at 75.4% (6757 of 8957 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/ru/
2025-11-13 00:30:09 +00:00
geumu 6ec2820dd8 Translated using Weblate (Korean)
Currently translated at 59.9% (5367 of 8957 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/ko/
2025-11-13 00:30:07 +00:00
321retrogamer b1054bdf11 Various move-related Sound and Action effect tweaks.
Fixes timing for various Action Effects to better fit their sound design. Additionally, updates sounds for Infestation and Ice Beam and re-adds Ember and Flamethrower sound cues to their respective Action Effects.
2025-11-12 17:49:38 -06:00
Neovitalism 3b227ba3a2 Fixes fabric server hanging on shutdown 2025-11-12 16:01:01 -06:00
JPAKx4 96049abb98 Fix Merge issues 2025-11-12 15:20:36 -06:00
JPAKx4 d661e88a96 Merge branch 'main' into riding-go-brr 2025-11-12 15:19:25 -06:00
Apion 8510e05177 Remove redundant local field in MountedCameraRenderer.kt 2025-11-12 16:13:56 -05:00
JPAKx4 af4fe4d09d Merge branch 'main' into riding-go-brr
# Conflicts:
#	common/src/main/java/com/cobblemon/mod/common/mixin/client/CameraMixin.java
#	common/src/main/kotlin/com/cobblemon/mod/common/client/render/camera/MountedCameraRenderer.kt
2025-11-12 14:09:14 -06:00
Apion 8b2ffd0f29 Merge branch 'apion-bugfix' into 'main'
Fix bug with camera mixin on NeoForge

See merge request cable-mc/cobblemon!1956
2025-11-12 19:57:34 +00:00
Apion 18cebc794b Clean up variable names in CameraMixin 2025-11-12 14:11:14 -05:00
Apion 64e84dab64 Merge remote-tracking branch 'origin/main' into apion-bugfix
# Conflicts:
#	common/src/main/java/com/cobblemon/mod/common/mixin/client/CameraMixin.java
#	common/src/main/kotlin/com/cobblemon/mod/common/client/render/camera/MountedCameraRenderer.kt
2025-11-12 13:21:18 -05:00
JPAKx4 9c5535a014 Fix offsets being rotated and offsets being applied twice. Changed default third person offset (negotiable, no idea good values). Fix no view bobbing. Add dismount location logic from horses, might need more testing or accounting for other mount types. 2025-11-12 12:02:03 -06:00
Nico Merenq 5993c1e588 Translated using Weblate (Russian)
Currently translated at 71.8% (6433 of 8957 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/ru/
2025-11-12 16:40:16 +00:00
geumu e8f7983dd2 Translated using Weblate (Korean)
Currently translated at 59.5% (5338 of 8957 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/ko/
2025-11-12 16:40:14 +00:00
Watuneni iteite bdd172bd2d Translated using Weblate (Japanese)
Currently translated at 94.2% (8446 of 8957 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/ja/
2025-11-12 16:40:12 +00:00
Paul 13842de7d6 Merge remote-tracking branch 'origin/main' 2025-11-12 23:26:31 +10:00
Paul f05e059445 Lil fixes oopsy 2025-11-12 23:26:22 +10:00
Polymeta 038d9e858c Merge branch 'mechanics-sync' into 'main'
Mechanics sync

See merge request cable-mc/cobblemon!1960
2025-11-12 13:12:49 +00:00
lion 9913826e24 Mechanics sync 2025-11-12 13:12:49 +00:00
Polymeta 8f971cc3d6 Merge branch '1.7-spawns-update' into 'main'
Updated all spawn files. Changed dead_coral preset into a block tag.

See merge request cable-mc/cobblemon!1962
2025-11-12 11:38:03 +00:00
Veraxiel 33c74372a4 Updated all spawn files. Changed dead_coral preset into a block tag. 2025-11-12 05:48:29 -05:00
Polymeta 5f11f4bdd6 Merge branch 'Saccharine-Tree-Biome-List-Update' into 'main'
Updated biome list for saccharine tree

See merge request cable-mc/cobblemon!1959
2025-11-12 09:55:01 +00:00
Polymeta 13b4bdc204 Merge branch 'SaccHiveGenerationRebalance' into 'main'
SaccHiveGenerationRebalance

See merge request cable-mc/cobblemon!1961
2025-11-12 09:54:49 +00:00
Paul 451ae00da1 Drops scrape 2025-11-12 19:11:39 +10:00
Carmendar 0c33de61b9 Species file updates for Tauros, Salamence, Latias, Latios and Staraptor. 2025-11-12 03:05:12 -06:00
Carmendar 91a3fb5031 Removed Kilowattrel mounted run. 2025-11-12 03:04:32 -06:00
Carmendar 3a46b2c218 Updated look posing for Tropius, Garchomp and Pidove. 2025-11-12 03:03:28 -06:00
Carmendar 2f631ddc64 Ursaring texture fix 2025-11-12 03:02:39 -06:00
Paul a8cc8278d3 Liechi berry should target the right biome 2025-11-12 18:57:03 +10:00
Carmendar 2a2ef6ff7d Removed mount 2025-11-12 02:42:32 -06:00
Carmendar d3d94a3614 Adjusted Dragonite flying pose when mounted. 2025-11-12 02:42:03 -06:00
Carmendar f34cc3072b Cutiefly Shoulder poses. 2025-11-12 02:41:12 -06:00
Carmendar 68bff6a40b Jet Handling expression tweak. 2025-11-12 00:45:26 -06:00
Landon 58c0136ad1 Merge branch 'quick-misc-additions' into 'main'
Misc Changes

See merge request cable-mc/cobblemon!1941
2025-11-12 06:39:48 +00:00
Deltric 45238058cb Misc Changes 2025-11-12 06:39:47 +00:00
JPAKx4 a326befcef Fix offsets being rotated and offsets being applied twice 2025-11-11 22:38:43 -06:00
JazzMcNade 52d8887514 Natural trees increased to 50% hives, Grown trees increased to 10% hives 2025-11-11 20:45:24 -06:00
Test 02ae8065ac Set duration for displaying ride controls in config to 0 by default 2025-11-12 01:43:01 +00:00
dhi_holo 2a6381d610 Eggant Is Here Now 2025-11-12 10:47:12 +10:00
dhi_holo 93dba4f3b8 Merge branch 'main' into advancing-advancements 2025-11-12 10:43:55 +10:00
Slippy c37c608010 Updated biome list for saccharine tree 2025-11-11 18:27:42 -06:00
Carmendar a7e7c2e814 Merge branch 'main' into implement_pokemon 2025-11-11 17:52:15 -06:00
Nico Merenq 09c4ae96bf Translated using Weblate (Russian)
Currently translated at 70.9% (6352 of 8957 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/ru/
2025-11-11 22:50:22 +00:00
Guilherme Pereira 367264b06e Merge branch 'main' of gitlab.com:cable-mc/cobblemon into more-poke-snack-stuff 2025-11-11 14:52:37 -03:00
Guilherme Pereira 3631fa909d Merge branch 'more-poke-snack-stuff' of gitlab.com:cable-mc/cobblemon into more-poke-snack-stuff 2025-11-11 14:51:41 -03:00
Guilherme Pereira fc29826bc7 fix cakes not being rendered properly on multiplayer 2025-11-11 14:51:18 -03:00
MoeBoy76 6bf62b3f9d change debug message to log as error 2025-11-11 11:05:38 +00:00
Carmendar 00be470281 Alolan Rattata fix. 2025-11-11 02:58:28 -06:00
geumu 8fb93dd488 Translated using Weblate (Korean)
Currently translated at 55.2% (4949 of 8957 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/ko/
2025-11-11 08:19:44 +00:00
Carmendar 57afbe79c2 Orthworm and Honedge line texture fixes. 2025-11-11 00:49:30 -06:00
Carmendar d5f336ce73 Merge branch 'main' into implement_pokemon 2025-11-11 00:48:17 -06:00
Neovitalism b863554c84 Changed to use the aspects of the pokémon instead of a new field. 2025-11-11 00:14:48 -06:00
Neovitalism 699d6fea17 Revert "Removable Feature Rendering"
This reverts commit d117d79d28.
2025-11-11 00:08:34 -06:00
Nico Merenq 2cd066a4c1 Translated using Weblate (Russian)
Currently translated at 69.5% (6233 of 8957 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/ru/
2025-11-11 03:11:09 +00:00
Nico Merenq 68b44db35c Translated using Weblate (Russian)
Currently translated at 67.3% (6032 of 8957 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/ru/
2025-11-10 22:22:58 +00:00
Nico Merenq 18d3fb288a Translated using Weblate (Russian)
Currently translated at 65.7% (5885 of 8957 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/ru/
2025-11-10 19:28:47 +00:00
Weblate 725b4b7e48 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-11-10 18:19:35 +00:00
geumu 28ae27b926 Translated using Weblate (Korean)
Currently translated at 55.2% (4949 of 8957 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/ko/
2025-11-10 18:19:31 +00:00
Watuneni iteite 21e9e73eee Translated using Weblate (Japanese)
Currently translated at 94.2% (8446 of 8957 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/ja/
2025-11-10 18:19:29 +00:00
Nico Merenq 6bfb318e2d Translated using Weblate (Russian)
Currently translated at 65.6% (5882 of 8957 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/ru/
2025-11-10 18:19:28 +00:00
violet b79a0b1b6f various animation fixes 2025-11-10 03:17:58 -05:00
Test b7550f7699 overlay texture 2025-11-09 23:36:55 -05:00
violet 57721d1696 Merge remote-tracking branch 'origin/implement_pokemon' into implement_pokemon 2025-11-09 22:51:33 -05:00
violet b0711528d6 tiny tweaks :3 2025-11-09 22:51:19 -05:00
violet 7e968fcff9 Murdered Shulker Forretress 2025-11-09 22:50:41 -05:00
Guilherme Pereira 9770d8ca6b Merge branch 'main' of gitlab.com:cable-mc/cobblemon into more-poke-snack-stuff 2025-11-10 00:28:24 -03:00
Watuneni iteite 04c3e182e7 Translated using Weblate (Japanese)
Currently translated at 93.5% (8376 of 8957 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/ja/
2025-11-10 02:50:43 +00:00
Test bbcfe95bac cake block, tinting updates 2025-11-09 21:03:50 -05:00
Watuneni iteite 82088651c2 Translated using Weblate (Japanese)
Currently translated at 92.7% (8312 of 8957 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/ja/
2025-11-10 01:39:38 +00:00
Carmendar e399130fda forgor one last change 2025-11-09 18:45:12 -06:00
Carmendar 0083e54f6a Galar Weezing crash fix 2025-11-09 18:27:38 -06:00
Carmendar 9512252b72 ^ 2025-11-09 14:24:41 -06:00
Carmendar 73028d4c2a Gave Dondozo basic land & fixed pivot issues with Bramblin. 2025-11-09 14:20:58 -06:00
geumu e3ead8e3e5 Translated using Weblate (Korean)
Currently translated at 50.4% (4515 of 8957 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/ko/
2025-11-09 19:29:48 +00:00
Nico Merenq 9c4b9b35ab Translated using Weblate (Russian)
Currently translated at 65.6% (5880 of 8957 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/ru/
2025-11-09 19:29:46 +00:00
Carmendar 2f5910c436 Merge branch 'main' into implement_pokemon 2025-11-09 03:09:26 -06:00
Carmendar d1197cbc0b Updated Kangaskhan poser & added held item condition. 2025-11-09 02:30:09 -06:00
Carmendar 2ccf699a86 Merge remote-tracking branch 'origin/implement_pokemon' into implement_pokemon 2025-11-09 01:37:47 -06:00
Carmendar d767420814 Wiglett lost floating privileges. 2025-11-09 01:37:08 -06:00
Carmendar 77100300b1 Fixed Luxray feet textures. 2025-11-09 01:35:05 -06:00
Carmendar 5c80fc03e2 Toxicroak remodel 2025-11-09 01:33:55 -06:00
Carmendar aa39bb84fe Fixed Lanturn t-posing on land. 2025-11-09 00:50:19 -06:00
violet a767b3d0fe Merge remote-tracking branch 'origin/implement_pokemon' into implement_pokemon 2025-11-09 01:28:31 -05:00
violet 3dbcbc34d0 ICE CREAM 2025-11-09 01:28:17 -05:00
violet 0bdadb3794 altered posers for solosis line 2025-11-09 01:20:50 -05:00
JPAKx4 ae6091fc01 Pull code out of the mixins. 2025-11-08 22:51:31 -06:00
dhi_holo 05b5782cd5 Merge branch 'main' into advancing-advancements 2025-11-09 12:54:24 +10:00
dhi_holo 0c220a8990 Berry Colour Tags
Small sorting thing to make it easier to find specific berry colours for cooking/crafting/smelting
2025-11-09 12:53:58 +10:00
Tyzillion b905888a0b Gust more like fart. 2025-11-08 20:17:23 -05:00
Tyzillion 5917e52ffc >.> 2025-11-08 20:01:05 -05:00
Tyzillion deb20cb418 Refactored move sound file names to match repo, Implemented Gust,
Added sounds to:
acid, aerialace, bodyslam, bubble, bubblebeam, bulldoze, bulletpunch, closecombat, eruption, gust, icebeam, infestation, lavaplume, magicalleaf, mist, mudbomb, powdersnow, razorleaf, shadowball, sludgebomb, thunder, thunderbolt, thundershock, watergun, waterpulse, and willowisp.
2025-11-08 19:53:02 -05:00
Apion 929e4b2391 Licenses 2025-11-08 15:43:50 -05:00
Apion c593a8b7e6 Fixed CameraMixin on neoforge 2025-11-08 15:00:22 -05:00
Apion d0fc166e09 Fix SoundEngineMixin on neoforge 2025-11-08 14:44:33 -05:00
geumu 78f752b4a1 Translated using Weblate (Korean)
Currently translated at 48.7% (4366 of 8957 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/ko/
2025-11-08 19:29:08 +00:00
Apion b4c971398d Fix BrewingStandMenuMixin on neoforge 2025-11-08 14:01:02 -05:00
geumu f0f78a01e0 Translated using Weblate (Korean)
Currently translated at 48.7% (4366 of 8957 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/ko/
2025-11-08 18:16:24 +00:00
geumu 8c36ee15cd Translated using Weblate (Korean)
Currently translated at 48.6% (4355 of 8957 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/ko/
2025-11-08 16:54:27 +00:00
阿鱼 3231d97cd3 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (8957 of 8957 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/zh_Hans/
2025-11-08 16:54:26 +00:00
Nico Merenq 9fce4d3b6b Translated using Weblate (Russian)
Currently translated at 64.7% (5801 of 8957 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/ru/
2025-11-08 16:54:25 +00:00
阿鱼 0f031545c1 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 99.1% (8877 of 8957 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/zh_Hans/
2025-11-08 08:30:14 +00:00
geumu 2b80189a79 Translated using Weblate (Korean)
Currently translated at 46.9% (4208 of 8957 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/ko/
2025-11-08 07:59:51 +00:00
geumu 2e88b0194e Translated using Weblate (Korean)
Currently translated at 46.6% (4176 of 8957 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/ko/
2025-11-08 06:51:21 +00:00
Nico Merenq b0e278d1a7 Translated using Weblate (Russian)
Currently translated at 63.3% (5674 of 8957 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/ru/
2025-11-08 06:51:12 +00:00
geumu 9c646d9d53 Translated using Weblate (Korean)
Currently translated at 46.6% (4174 of 8957 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/ko/
2025-11-08 06:51:10 +00:00
Guilherme Pereira dd19140a83 change mark chance effect to drops reroll 2025-11-07 10:33:54 -03:00
dhi_holo da787bf9bf Merge branch 'main' into advancing-advancements 2025-11-07 16:15:29 +10:00
Paul 57a839d000 Removed some test stuff I forgor about 2025-11-06 22:14:08 +10:00
Paul e77e49c8b1 Minor cleanup 2025-11-06 22:13:03 +10:00
Paul ce6d142bd4 Merge remote-tracking branch 'origin/main' into molang-json-interaction 2025-11-06 22:12:17 +10:00
MoeBoy76 f2db63164c general riding and PokéRod cast/reel stats 2025-11-05 16:05:52 +11:00
MoeBoy76 604b4d39ea Merge branch 'main' of https://gitlab.com/cable-mc/cobblemon into getting-statistical 2025-11-05 14:26:27 +11:00
Guilherme Pereira be96e45c4e change colors variable name 2025-11-04 08:41:42 -03:00
Guilherme Pereira 42eb08e715 Merge branch 'main' into more-poke-snack-stuff 2025-11-03 18:08:10 -03:00
Guilherme Pereira 03470aa623 add poke snack spawn pokemon pre and post events 2025-11-03 17:58:14 -03:00
Paul 5d3741f2e5 Added JSON file interactions for molang and function arguments for q.run_script 2025-11-02 11:23:50 +10:00
Guilherme Pereira d09d636113 add facing direction to snacks 2025-10-30 16:54:45 -03:00
Guilherme Pereira ff335f779f improve color mixing of snacks 2025-10-30 13:25:37 -03:00
Guilherme Pereira b70316e347 switch the snacks’ colors to be based on food colors again 2025-10-30 10:05:30 -03:00
Guilherme Pereira a352e67c1b lots of bugs and rowap berry effect 2025-10-29 21:42:55 -03:00
Guilherme Pereira 71297dfb3a fix nearby check for poke snack 2025-10-29 18:46:08 -03:00
Guilherme Pereira 9141694c2a Merge branch 'main' of gitlab.com:cable-mc/cobblemon into poke-snack-spawner 2025-10-29 18:00:30 -03:00
Paul 1f8fa8cae3 Prevent snacks from spawning pokemon if no players are nearby 2025-10-27 13:50:33 +10:00
Paul 42e405530c Major rework of Spawner hierarchy, removed SpawnerManagers, moved pokesnacks to be manually ticked 2025-10-27 13:40:52 +10:00
dhi_holo 5e21ac94dc Merge branch 'main' into advancing-advancements 2025-10-25 17:13:13 +10:00
Guilherme Pereira c76dfc3130 refactor poke snacks to use random ticks 2025-10-25 00:29:06 -03:00
Guilherme Pereira cca9de04a7 avoid poke snack spawners behaving weirdly 2025-10-22 21:39:08 -03:00
Guilherme Pereira 78d47004bf remove dead code 2025-10-22 21:12:19 -03:00
Guilherme Pereira 30f97e6243 move poke snack spawner creation to poke snack spawner manager 2025-10-22 21:00:35 -03:00
Neovitalism d117d79d28 Removable Feature Rendering 2025-10-22 18:56:26 -05:00
Guilherme Pereira 3d4d797e7f add bite time effect to poke snacks 2025-10-22 15:08:58 -03:00
Guilherme Pereira 39feb9cf6c hook POI system to poke snacks 2025-10-22 13:53:48 -03:00
Guilherme Pereira 8f53757879 allow poke snacks to override the default pokemon per chunk spawn limit 2025-10-22 10:30:46 -03:00
Guilherme Pereira e1d2f125d6 add bucket multiplying influence to poke snacks 2025-10-22 10:00:59 -03:00
Guilherme Pereira fa3ed69ee2 move poke snack spawner to block entity 2025-10-22 03:38:07 -03:00
Guilherme Pereira 8c02ca3576 create poke snack spawner 2025-10-21 19:45:20 -03:00
dhi_holo 1d055253d2 Merge branch 'main' into advancing-advancements 2025-10-10 16:00:30 +10:00
dhi_holo d56c5520f9 Merge branch 'main' into advancing-advancements 2025-10-04 17:26:10 +10:00
dhi_holo 89bc893f06 gamerule.healersHealPC 2025-10-04 17:25:50 +10:00
dhi_holo acc8d066e5 stOre 2025-10-03 19:17:00 +10:00
dhi_holo 6608268117 Update cobblemon.json
fixed typo
2025-10-03 14:03:35 +10:00
dhi_holo bdecab25a6 Merge branch 'main' into advancing-advancements 2025-10-03 13:38:45 +10:00
dhi_holo 81ed97a68b Update cobblemon.json
Removed removed item, added new items
2025-09-30 11:03:26 +10:00
dhi_holo 1e051deb9e Update CHANGELOG.md 2025-09-29 18:06:37 +10:00
dhi_holo 38c54e255a Chromatic Upgrades
- Removed Vivichoke advancement
- Reworded Galar Fossil advancement
- Renamed Master Rod advancement, made hidden by default
- Name tweak for IV Candy advancement
- Description update for regional delicacy advancement
- Renamed Poke Bait advancement
- Description update to ride stats
- Removed Aprijuice advancement
- Combined interaction advancements
- Added Saccharine advancement
- Moved Poke Snack advancement
- Updated some icons for advancements
2025-09-29 15:34:14 +10:00
dhi_holo e7ad38d1df Interactions and Clean Up
Added more Interaction based advancements, moved some stuff around, cleaned up visuals and description for max ride stats
2025-09-28 23:13:59 +10:00
dhi_holo 67c0abea8f Better Brush Desc 2025-09-28 21:15:54 +10:00
dhi_holo 85c1543df1 More tweaks
Brushing Pokemon advancement now works swell, Aprijuice advancement good, started work on the concept for Max Ride Stats, still need to actually get a trigger for it though
2025-09-28 17:10:15 +10:00
dhi_holo f38a1f83e2 More
Started on Bait and Brush advancements, renamed A Luring Aroma
2025-09-28 00:36:02 +10:00
dhi_holo 28785a01f6 Update revive.json
Reduced output to 1
2025-09-26 20:04:08 +10:00
dhi_holo 01c4260763 Merge branch 'main' into advancing-advancements 2025-09-25 20:05:09 +10:00
dhi_holo 150b3eb178 Snack 2025-09-25 20:05:07 +10:00
dhi_holo 5ab52d37f2 Fix Typo 2025-09-25 19:50:26 +10:00
dhi_holo ce191fd4c7 3 New, Minor Reorg
New: Cooking Regional Delicacies, Cooking EV Mochi, Cooking Poké Snack
Cleaned Up: Any Plant no longer announces to chat, Battle Win is on root, Use Candy is on Place Campfire Pot (also moves IV Candy to that tree instead)
2025-09-24 19:34:20 +10:00
MoeBoy76 9a7e349101 Merge branch 'main' of https://gitlab.com/cable-mc/cobblemon into getting-statistical 2025-09-23 09:33:46 +10:00
MoeBoy76 07a7d2a51a Statistics correctly register and if something goes wrong a more helpful crash should be thrown. 2025-09-23 09:33:28 +10:00
MoeBoy76 d2b192cb07 stats still don't register 2025-09-22 13:36:54 +10:00
MoeBoy76 d8e3e93a87 Merge branch 'main' of https://gitlab.com/cable-mc/cobblemon into getting-statistical 2025-09-22 10:06:52 +10:00
MoeBoy76 af12df38ed stats should work for NF now 2025-09-22 10:05:03 +10:00
MoeBoy76 7fb8268fae Lang tweaks 2025-08-04 10:38:54 +10:00
MoeBoy76 8b49eb1526 Stats work and Advancement fixes to match wiki 2025-08-04 10:19:25 +10:00
MoeBoy76 c6cdcf83a9 Merge branch 'main' of https://gitlab.com/cable-mc/cobblemon into getting-statistical
# Conflicts:
#	common/src/main/resources/assets/cobblemon/lang/en_us.json
2025-08-04 08:26:06 +10:00
MoeBoy76 4bf82083b4 Merge branch 'main' of https://gitlab.com/cable-mc/cobblemon into getting-statistical 2025-04-28 09:02:44 +10:00
MoeBoy76 6579fd8ebe more stats work, they load now and have lang 2025-04-23 11:02:12 +10:00
MoeBoy76 4d62ef771a Merge branch 'main' of https://gitlab.com/cable-mc/cobblemon into getting-statistical 2025-04-23 10:11:33 +10:00
MoeBoy76 7784a3a20c initial stats work 2025-04-22 09:49:47 +10:00
2602 changed files with 33861 additions and 10869 deletions

No files matched your search

+46 -7
View File
@@ -38,14 +38,15 @@
- Lightning is now affected by a Pokemon's ability/typing
- Pokémon with the ability Lightning Rod draw in lightning similar to a lightning rod block albeit with a lower priority and range, gain immunity to lightning damage, and receive a temporary damage buff.
- Pokémon with the ability Motor Drive are immune to lightning damage and receive a temporary speed buff when struck by lightning
- Pokémon with the ability Volt Absorb are immune to lightning damage and receive Regeneration II for a short duration
- Pokémon with the ability Volt Absorb are immune to lightning damage and receive Instant Health II for a short duration
- Ground type Pokémon are immune to lightning damage
- Added functionality to Everstone when held by a Pokémon; suppresses evolution notification and hides evolve button in summary interface.
- Added optional `filePath` parameter to MoLang functions to allow for global stores (ex. `../global/`). Path must end in a forward slash.
- Added new optional property `attachment_options` for most EmitterShapes to be attached to the locator/entities scale, rotation, and/or position. Position is true by default.
- Added Statistics for battles won, fled, and total, Pokémon captured (shiny and total), Pokémon released, dex entries added, trades completed, Pokémon levels gained, Pokémon evolved, fossils revived, PokéRod casts and reel-ins and Pokémon times ridden.
- Galarica Nut bushes now generate on beaches.
- Some Pokémon now pitch their bodies in the direction they're moving.
- Added new advancements Didn't Stop To Think, We Need To Cook, and Pokémon Jockey!.
- Added new advancements Didn't Stop To Think, We Need To Cook, Pokémon Jockey!, Souped-Up Stats, Culinary World Tour, Mochi Mochi!, A Luring Aroma, That's Bait, Star Pokéathlete, Home on the Range, and Just a Smackerel.
- Berries can now be smelted into their respective dyes.
- Added Syrupy Apples.
- Added `/runmolang <molang> [<npc>|<player>|<pokemon>]` command that executes a MoLang expression with the provided options as environment variables, as well as the entity (as `q.entity`) that executed the command.
@@ -58,6 +59,11 @@
- Mooshtanks will switch between their red and brown variant when hit by lightning
- Smeargle spawns with differing tail colour depending on its [Characteristic](https://bulbapedia.bulbagarden.net/wiki/Characteristic) stat
- Added smooth level-up animations to the party overlay to replace chat messages.
- Added `min_perfect_ivs` property to PokemonProperties to specify the minimum number of perfect IVs of the Pokemon.
- Added `defaultKeyItems` config option to specify which key items players always have.
- Added `scale_modifier` property to PokemonProperties to modify the scale of the Pokemon.
- Added advancement trigger to check riding stat boosts.
- Added Tasty Tail which you can get from Slowpokes if you happen to have a pair of shears. They don't mind, we asked.
### Pokémon Added
@@ -305,7 +311,6 @@
- Tauros - Paldea Blaze
- Tauros - Paldea Combat
- Dewgong
- Exeggutor - Kanto
- Corphish (updated placeholders for crustaceous tripod gait legs)
- Crawdaunt (updated placeholders for crustaceous bipedal legs)
- Dragapult
@@ -471,8 +476,7 @@
- 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.
- Removed Shulker shell Forretress.
- 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.
@@ -481,7 +485,7 @@
- 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
- Changed the recipes for Level, Lure, and Moon Balls to be cleaner
- Renamed `pokemonId` and `type` to `species` in relevant Advancement triggers for conformity, this is a breaking change.
- Renamed `pokemonId` and `type` to `species` and `evolved` to `has_evolved` in relevant Advancement triggers for conformity, this is a breaking change.
- Added a separate `species` argument to the `pick_starter`, `pasture_use` and `resurrect_pokemon` Advancement triggers.
- Made `CobblemonAgingDespawner` thresholds configurable via the config file.
- Tweaked Berry flavor data to balance cooking pot mechanics
@@ -516,8 +520,16 @@
- Updated `HatchEggEvent.Post` to include the Pokemon that hatched.
- Roseli Berry Trees now naturally generate in their preferred biomes.
- Refactored dynamic lights compat to be more future proof. The dynamic light support is only tested with LambDynamicLights, on NeoForged use that mod in combination with Sinytra Connector
- Renamed Masterful Dedication advancement to This will affect the Whiscash Population
- Changed icon for the following advancements: New Angles for Angling, Researcher Recruit, Doing my Part, Reapriforestation
- Disabled advancement Mother Nature's Bounty from appearing in chat when obtained, now only appears as a toast and in the advancements menu
- Removed Oki-Doki Vivichokey advancement
- Shulker Boxes and Traveler's Backpacks can no longer be held by Pokémon. Thanks Monocle ;) You could re-enable this with a datapack but you'd be crazy.
- Shulker Boxes and Traveler's Backpacks AND Packed Up backpacks can no longer be held by Pokémon. Thanks Monocle ;) You could re-enable this with our datapack (but you'd be crazy).
- Moomoo Milk now clears Pokémon stat changes when used in battle.
- Updated Evolution Stone Block light levels
- Added light levels to Evolution Stone Ores. These levels are reduced versions of the full blocks light levels
- Added a steps counter to the summary screen for Pokémon that require walking a certain number of steps to evolve.
### Fixes
- Fixed game crashing when removing national pokedex using datapacks
@@ -602,10 +614,17 @@
- Fixed singular Pokémon corruption causing entire storage corruption. Storages will now skip corrupted Pokémon and print an error to console.
- Fixed species additions not being able to properly mark a species as implemented.
- Fixed Pokémon item models not showing a glint when enchanted.
- Fixed the missing Terracotta Sun Stone Ore smelting and blasting recipes
- Improved experience gain from smelting evolution stone ores to better match other ore types
- Fixed some specific bag items not being dropped when used in battle.
- The Corphish line will now sink in water.
- Fixed the "use all berry bait" achievement not being progressed
- Fixed bobber hook and berry sprouts texture sizes causing mipmap issues.
- Fixed head locator not taking into account scale for positioning.
- Fixed Pokémon step counts not being saved when recalling them to a Pokéball or reentering the world.
- Fixed NPC pokémon not being linked to their NPC, which previously caused NPC pokémon to be catchable.
- Fixed an uncommon error caused by scanning a pokémon on a player's shoulder.
- Fixed a case where spawning could fail and log warnings when nothing wrong was happening.
### Developer
- A finished battle now has winners and losers set inside of `PokemonBattle` instead of them always being empty.
@@ -662,6 +681,17 @@
}
```
This will change the value of `mooshtank` from `red` to `brown` and vice versa when a lightning strikes this Pokémon. Only chains of which a value is the current value will be considered, so multiple entries for the same key with different chains can be added.
- Removed Npc interface from NPCEntity, the interface is unused and in vanilla is only implemented by VillagerEntity as a means to disable villagers with the `spawn-npcs` server property.
- Added new `Observable#subscribe` methods that take Java Consumers to make usage in Java a little cleaner.
- Annotated a bunch of Kotlin methods and fields for cleaner Java names.
- Added `PartyStore#isEmpty()`.
- Added `ElementalTypes#getRandomType()`.
- Added `IVs#getEffectiveBattleTotal()`.
- Added `IVs.MAX_TOTAL` constant.
- Added `PokemonStats#total()`.
- Add `NatureAdapter` for serializing and deserializing Natures using Gson.
- Added `Pokemon.getBaseRideStat(RidingStat)` for getting the base value of the given stat.
- Fixed `Species#create` using the species name instead of identifier, which had led to certain mismatches generating random pokémon.
### 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)
@@ -702,6 +732,7 @@
- Adds Flows for `POKEMON_HEALED`, `POKEMON_SCANNED`, `BERRY_HARVEST`, `LOOT_DROPPED`, `POKEMON_SEEN`, `COLLECT_EGG`, `HATCH_EGG`, and `EXPERIENCE_GAINED`.
- Adds Flows for `POKEMON_CATCH_RATE`, `BAIT_SET`, `BAIT_SET_PRE`, `BAIT_CONSUMED`, `POKEROD_CAST_PRE`, `POKEROD_CAST_POST`, `POKEROD_REEL`, and `BOBBER_SPAWN_POKEMON_PRE`.
- Adds Flows for `POKEMON_ASPECTS_CHANGED`, `FRIENDSHIP_UPDATED`, `CHANGE_PC_BOX_WALLPAPER_EVENT_PRE`, `CHANGE_PC_BOX_WALLPAPER_EVENT_POST`, and `FULLNESS_UPDATED`.
- Added Callback for `SERVER_STOPPING`
- MoLang triggered battles may now set the battle format, whether to clone the player's party, set level, or heal prior.
- Added Molang function for Player: `inventory`
- Adds Flows for `STARTER_CHOSEN`, `EV_GAINED`, `POKEMON_RELEASED`, `POKEMON_NICKNAMED`, `HELD_ITEM`, and `TRADE_COMPLETED` events
@@ -769,6 +800,14 @@
- Also changed the default from `cobblemon:empty_bait` to `any`
- The previous default is still available by using the above as baitId
- Added support for species-specific move action effects, using the format `{move_id}_{species}.json`.
- Added `look_at_entity_types` variable for look_at_entities to specify what entity type or entity tag to look at.
- Added `Looks At Players` behaviour preset that only sets the look target to players.
- Added various functions to `q.file` for JSON file handling in MoLang, strictly for `./config` and `./data` folders that have `/molang/` in the path:
- `q.file.save(<path>, <struct>)` Saves to the given file path with the given variable struct.
- `q.file.load(<path>)` Loads a variable struct from the given path, or gets it from the cache if it's already been loaded.
- `q.file.exists(<path>)` Returns 1 if the given file path exists.
- `q.file.clear(<path>)` Clears the given file from the cache.
- Using `q.run_script` will now allow additional arguments which will be put into `c.arg_1`, `c.arg_2`, etc.
### Particles
Added new/updated particles for the following moves:
@@ -3001,4 +3040,4 @@ Thank you so much to all of our community translators that bring the mod to the
- Added species, ability, and move translations for `ko_ko`, `jp_jp`, `fr_fr`, `es_es`, `it_it`, and `zh_cn`.
## [1.0.0 (November 12th, 2022)](#1-0-0)
- Initial release.
- Initial release.
@@ -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.duck;
import com.mongodb.lang.Nullable;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.BlockGetter;
import org.joml.Vector3f;
public interface CameraDuck {
BlockGetter cobblemon$getLevel();
@Nullable
Entity cobblemon$getEntity();
Vector3f cobblemon$getForwards();
Vector3f cobblemon$getUp();
Vector3f cobblemon$getLeft();
float cobblemon$getXRot();
void cobblemon$setXRot(float xRot);
float cobblemon$getYRot();
void cobblemon$setYRot(float yRot);
}
@@ -52,7 +52,7 @@ public abstract class BeeOccupantMixin {
var facing = state.getValue(HorizontalDirectionalBlock.FACING);
newPos = pos.relative(facing).getCenter();
newYaw = facing.toYRot();
brain.setMemory(CobblemonMemories.INSTANCE.getHIVE_LOCATION(), pos); // This needs to be set in the case that the hive was picked up and moved.
brain.setMemory(CobblemonMemories.HIVE_LOCATION, pos); // This needs to be set in the case that the hive was picked up and moved.
} else {
// Block has likely been destroyed
var center = pos.getCenter();
@@ -62,16 +62,16 @@ public abstract class BeeOccupantMixin {
center.z + level.random.nextFloat() * 0.6 - 0.3
);
newYaw = level.random.nextFloat() * 360F;
brain.eraseMemory(CobblemonMemories.INSTANCE.getHIVE_LOCATION());
brain.eraseMemory(CobblemonMemories.HIVE_LOCATION);
}
entity.yRotO = newYaw;
entity.setPos(newPos);
// Do honey logic
var hasNectar = brain.getMemory(CobblemonMemories.INSTANCE.getHAS_NECTAR()).orElse(false);
var hasNectar = brain.getMemory(CobblemonMemories.HAS_NECTAR).orElse(false);
if (hasNectar) {
// Remove nectar and reset got to hive cooldown
brain.eraseMemory(CobblemonMemories.INSTANCE.getHAS_NECTAR());
brain.setMemoryWithExpiry(CobblemonMemories.INSTANCE.getHIVE_COOLDOWN(), true, PathToBeeHiveTaskConfig.STAY_OUT_OF_HIVE_COOLDOWN);
brain.eraseMemory(CobblemonMemories.HAS_NECTAR);
brain.setMemoryWithExpiry(CobblemonMemories.HIVE_COOLDOWN, true, PathToBeeHiveTaskConfig.STAY_OUT_OF_HIVE_COOLDOWN);
// Increment honey level of the hive
if (state.is(BlockTags.BEEHIVES, (blockStateBase) -> blockStateBase.hasProperty(BeehiveBlock.HONEY_LEVEL))) {
int i = state.getValue(BeehiveBlock.HONEY_LEVEL);
@@ -97,11 +97,10 @@ public abstract class BeeOccupantMixin {
entity.save(compoundTag);
Objects.requireNonNull(compoundTag);
IGNORED_BEE_TAGS.forEach(compoundTag::remove);
Boolean hasNectar = pokemonEntity.getBrain().getMemory(CobblemonMemories.INSTANCE.getHAS_NECTAR()).orElse(false);
Boolean hasNectar = pokemonEntity.getBrain().getMemory(CobblemonMemories.HAS_NECTAR).orElse(false);
cir.setReturnValue(new BeehiveBlockEntity.Occupant(CustomData.of(compoundTag), 0, hasNectar ? 2400 : 600));
cir.cancel();
}
}
}
}
@@ -38,6 +38,7 @@ 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.Mth;
import net.minecraft.world.damagesource.DamageSource;
import net.minecraft.world.entity.EntityDimensions;
import net.minecraft.world.entity.EntityType;
@@ -221,24 +222,25 @@ public abstract class PlayerMixin extends LivingEntity implements ScannableEntit
@Nullable @Unique
private PokedexEntityData getDataFromShoulderPokemon(CompoundTag shoulderTag) {
CompoundTag pokemonTag = shoulderTag.getCompound(DataKeys.POKEMON);
if (pokemonTag.isEmpty()) return null;
Species species = PokemonSpecies.INSTANCE.getByIdentifier(ResourceLocation.parse(pokemonTag.getString(DataKeys.POKEMON_SPECIES_IDENTIFIER)));
if (species == null) return null;
String formId = pokemonTag.getString(DataKeys.POKEMON_FORM_ID);
FormData form = species.getStandardForm();
List<FormData> formList = species.getForms().stream().filter(it -> it.formOnlyShowdownId().equals(formId)).toList();
if (!formList.isEmpty()) form = formList.getFirst();
if (form == null) return null;
String genderString = pokemonTag.getString(DataKeys.POKEMON_GENDER);
if (genderString.isEmpty()) return null;
Gender gender = Gender.valueOf(genderString);
boolean shiny = pokemonTag.getBoolean(DataKeys.POKEMON_SHINY);
int level = pokemonTag.getInt(DataKeys.POKEMON_LEVEL);
Set<String> aspects = shoulderTag.getList(DataKeys.SHOULDER_ASPECTS, Tag.TAG_STRING).stream().map(Tag::getAsString).collect(Collectors.toSet());
Pokemon pokemon = new Pokemon();
Pokemon pokemon;
if (level().isClientSide) {
CompoundTag pokemonTag = shoulderTag.getCompound(DataKeys.POKEMON);
if (pokemonTag.isEmpty()) return null;
Species species = PokemonSpecies.getByIdentifier(ResourceLocation.parse(pokemonTag.getString(DataKeys.POKEMON_SPECIES_IDENTIFIER)));
if (species == null) return null;
String formId = pokemonTag.getString(DataKeys.POKEMON_FORM_ID);
FormData form = species.getStandardForm();
List<FormData> formList = species.getForms().stream().filter(it -> it.formOnlyShowdownId().equals(formId)).toList();
if (!formList.isEmpty()) form = formList.getFirst();
if (form == null) return null;
String genderString = pokemonTag.getString(DataKeys.POKEMON_GENDER);
if (genderString.isEmpty()) return null;
Gender gender = Gender.valueOf(genderString);
boolean shiny = pokemonTag.getBoolean(DataKeys.POKEMON_SHINY);
int level = pokemonTag.getInt(DataKeys.POKEMON_LEVEL);
Set<String> aspects = shoulderTag.getList(DataKeys.SHOULDER_ASPECTS, Tag.TAG_STRING).stream().map(Tag::getAsString).collect(Collectors.toSet());
pokemon = new Pokemon();
pokemon.setSpecies(species);
pokemon.setForm(form);
pokemon.setGender(gender);
@@ -249,7 +251,7 @@ public abstract class PlayerMixin extends LivingEntity implements ScannableEntit
PlayerPartyStore party = Cobblemon.INSTANCE.getStorage().getParty(this.getUUID(), this.registryAccess());
pokemon = party.get(shoulderTag.getUUID(DataKeys.SHOULDER_UUID));
}
return new PokedexEntityData(pokemon, null);
return (pokemon == null) ? null : new PokedexEntityData(pokemon, null);
}
@Override
@@ -317,7 +319,7 @@ public abstract class PlayerMixin extends LivingEntity implements ScannableEntit
@Override
public void cobblemon$setRideXRot(float rideXRot) {
this.cobblemon$rideXRot = rideXRot;
this.cobblemon$rideXRot = Mth.wrapDegrees(rideXRot);
}
@Override
@@ -327,7 +329,7 @@ public abstract class PlayerMixin extends LivingEntity implements ScannableEntit
@Override
public void cobblemon$setRideYRot(float rideYRot) {
this.cobblemon$rideYRot = rideYRot;
this.cobblemon$rideYRot = Mth.wrapDegrees(rideYRot);
}
@Override
@@ -29,5 +29,4 @@ public class RecipeBookSettingsMixin {
private void cobblemon$init(CallbackInfo ci) {
states.put(RecipeBookType.valueOf("COOKING_POT"), new RecipeBookSettings.TypeSettings(true, true));
}
}
@@ -55,86 +55,6 @@ public abstract class SoundEngineMixin implements SoundEngineDuck {
@Shadow
public abstract boolean isActive(SoundInstance sound);
@Inject(method = "play",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/client/sounds/ChannelAccess$ChannelHandle;execute(Ljava/util/function/Consumer;)V"
),
cancellable = true
)
private void cobblemon$overrideChannelExecute(
SoundInstance sound,
CallbackInfo ci,
@Local(name = "h") float h,
@Local(name = "i") float i,
@Local(name = "g") float g,
@Local(name = "bl2") boolean bl2,
@Local(name = "bl3") boolean bl3,
@Local(name = "bl") boolean bl,
@Local(name = "vec3") Vec3 vec3,
@Local(name = "channelHandle") ChannelAccess.ChannelHandle handle
) {
if (!(sound instanceof RideLoopSound rideSound)) return;
if (handle == null) return;
handle.execute((channel) -> {
channel.setPitch(i);
channel.setVolume(h);
if (rideSound.getRideAttenuation() == RideAttenuationModel.LINEAR) {
channel.linearAttenuation(g);
} else if (rideSound.getRideAttenuation() == RideAttenuationModel.EXPONENTIAL){
((ChannelDuck) channel).cobblemon$inverseAttenuation(g);
} else {
channel.disableAttenuation();
}
// Apply low pass filter if the rideSound dictate that it should be muffled
if (rideSound.getShouldMuffle()) {
((ChannelDuck) channel).cobblemon$applyLowPassFilter(1.0f, rideSound.getMuffleAmount());
} else {
((ChannelDuck) channel).cobblemon$clearFilters();
}
channel.setLooping(bl2 && !bl3);
channel.setSelfPosition(vec3);
channel.setRelative(bl);
});
}
@Inject(
method = "tickNonPaused",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/client/sounds/ChannelAccess$ChannelHandle;execute(Ljava/util/function/Consumer;)V",
ordinal = 0
)
)
private void cobblemon$tickableSoundTick(
CallbackInfo ci,
@Local(name = "tickableSoundInstance") TickableSoundInstance instance,
@Local(name = "channelHandle", ordinal = 0) ChannelAccess.ChannelHandle handle,
@Local(name = "f", ordinal = 0) float volume,
@Local(name = "g", ordinal = 0) float pitch,
@Local(name = "vec3", ordinal = 0) Vec3 vec3
) {
if (!(instance instanceof RideLoopSound rideSound)) return;
handle.execute(channel -> {
channel.setVolume(volume);
channel.setPitch(pitch);
channel.setSelfPosition(vec3);
// Apply low pass filter if the rideSound dictate that it should be muffled
if (rideSound.getShouldMuffle()) {
((ChannelDuck) channel).cobblemon$applyLowPassFilter(1.0f, rideSound.getMuffleAmount());
} else {
((ChannelDuck) channel).cobblemon$clearFilters();
}
});
}
/** Resumes the Source belonging to the queried SoundInstance. */
private void resume(SoundInstance sound) {
ChannelAccess.ChannelHandle sourceManager = this.instanceToChannel.get(sound);
@@ -1,20 +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.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();
}
@@ -27,7 +27,6 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(BrewingStandMenu.class)
public abstract class BrewingStandMenuMixin {
@Inject(method = "<init>(ILnet/minecraft/world/entity/player/Inventory;Lnet/minecraft/world/Container;Lnet/minecraft/world/inventory/ContainerData;)V", at = @At("TAIL"))
private void captureLevel(int containerId, Inventory playerInventory, Container brewingStandContainer, ContainerData brewingStandData, CallbackInfo ci) {
var recipeManager = playerInventory.player.level().getRecipeManager();
@@ -37,9 +36,4 @@ public abstract class BrewingStandMenuMixin {
}
}
}
@WrapOperation(method = "quickMoveStack", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/inventory/BrewingStandMenu$PotionSlot;mayPlaceItem(Lnet/minecraft/world/item/ItemStack;)Z"))
private boolean cobblemon$isPotionBottle(ItemStack stack, Operation<Boolean> original, @Local(argsOnly = true) Player player) {
return BrewingStandRecipe.Companion.isBottle(stack, player.level().getRecipeManager()) || original.call(stack);
}
}
@@ -8,97 +8,58 @@
package com.cobblemon.mod.common.mixin.client;
import com.cobblemon.mod.common.Cobblemon;
import com.cobblemon.mod.common.OrientationControllable;
import com.cobblemon.mod.common.api.orientation.OrientationController;
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.duck.RidePassenger;
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity;
import com.cobblemon.mod.common.duck.CameraDuck;
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
import com.llamalad7.mixinextras.sugar.Local;
import com.mojang.blaze3d.Blaze3D;
import net.minecraft.client.Camera;
import net.minecraft.client.Minecraft;
import net.minecraft.util.Mth;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.phys.Vec3;
import org.jetbrains.annotations.Nullable;
import org.joml.Matrix3f;
import org.joml.Quaternionf;
import org.joml.Vector3f;
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;
@Mixin(Camera.class)
public abstract class CameraMixin {
@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;
public abstract class CameraMixin implements CameraDuck {
@Shadow private float eyeHeight;
@Shadow private float eyeHeightOld;
@Shadow private BlockGetter level;
@Shadow private Entity entity;
@Final @Shadow private Vector3f forwards;
@Final @Shadow private Vector3f up;
@Final @Shadow private Vector3f left;
@Shadow private float yRot;
@Shadow private float xRot;
@Shadow protected abstract void setPosition(Vec3 pos);
@Shadow private float partialTickTime;
// Used to help in camera rotation rendering when transitioning
// from rolled to unrolled.
@Unique private float cobblemon$returnTimer = 0;
@Unique private float cobblemon$rollAngleStart = 0;
@Unique private double cobblemon$lastHandledRotationTime = Double.MIN_VALUE;
@Unique private double cobblemon$frameTime = 0.0;
// Used to as the render rotation for the motion sick camera.
@Unique @Nullable private Quaternionf cobblemon$smoothRotation = null;
@Inject(method = "setRotation", at = @At("HEAD"), cancellable = true)
public void cobblemon$setRotation(float f, float g, CallbackInfo ci) {
// Calculate the current frametime
double d = Blaze3D.getTime();
this.cobblemon$frameTime = (this.cobblemon$lastHandledRotationTime != Double.MIN_VALUE) ? d - this.cobblemon$lastHandledRotationTime : 0.0;
this.cobblemon$lastHandledRotationTime = d;
// Do no camera rotations if the game is paused
if(Minecraft.getInstance().isPaused()) return;
// Don't assume the camera to be attached to an entity. Ponder Scenes from create et.al. for example aren't.
if (this.entity == null) return;
var vehicle = this.entity.getVehicle();
if (!(vehicle instanceof OrientationControllable controllableVehicle)) return;
var instance = (Camera)(Object)this;
// If the current vehicle has no orientation then return and perform
// vanilla camera rotations
var vehicleController = controllableVehicle.getOrientationController();
if (vehicleController.getOrientation() == null) return;
// If the controller has been deactivated but the orientation isn't null yet
// then perform transition from rolled ride/camera to vanilla
if (!vehicleController.isActive() && vehicleController.getOrientation() != null) {
cobblemon$applyTransitionRotation(vehicleController, ci);
} else { // Otherwise perform cobblemon specific camera rotation and set transition helper variables
cobblemon$applyRotation();
this.cobblemon$returnTimer = 0;
this.cobblemon$rollAngleStart = instance.rotation().getEulerAnglesYXZ(new Vector3f()).z();
ci.cancel();
}
@Override public BlockGetter cobblemon$getLevel() {
return level;
}
@Override public Entity cobblemon$getEntity() {
return entity;
}
@Override public Vector3f cobblemon$getForwards() { return forwards; }
@Override public Vector3f cobblemon$getUp() { return up; }
@Override public Vector3f cobblemon$getLeft() { return left; }
@Override public float cobblemon$getXRot() { return xRot; }
@Override public void cobblemon$setXRot(float xRot) { this.xRot = xRot; }
@Override public float cobblemon$getYRot() { return yRot; }
@Override public void cobblemon$setYRot(float yRot) { this.yRot = yRot; }
@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) {
Entity entity = instance.getEntity();
@@ -107,177 +68,22 @@ public abstract class CameraMixin {
if(vehicle instanceof Rideable){
Vec3 position = MountedCameraRenderer.INSTANCE.getCameraPosition(
instance,
entity,
vehicle,
x,
y,
z,
thirdPersonReverse,
eyeHeightOld,
eyeHeight
instance,
entity,
vehicle,
thirdPersonReverse,
eyeHeight,
eyeHeightOld
);
if(position != null){
if(position != null) {
setPosition(position);
return;
}
}
// reset the rotation values if it is now not being ridden.
cobblemon$smoothRotation = null;
MountedCameraRenderer.INSTANCE.setSmoothRotation(null);
original.call(instance, x, y, z);
}
@Unique
private void cobblemon$applyRotation(){
var driver = this.entity;
if (!(driver.getVehicle() instanceof OrientationControllable controllableVehicle) ||
controllableVehicle.getOrientationController().getOrientation() == null ||
!controllableVehicle.getOrientationController().getActive()
) return;
// Grab the driver and vehicle orientation controllers.
var vehicleController = controllableVehicle.getOrientationController();
var isDriving = driver.getControlledVehicle() != null;
// Grab the ride orientation
var newRotation = new Quaternionf();
// If the player is driving then use the current orientation since the driver sets it.
// If not then use the smoothed render orientation for passengers otherwise the vehicle rotation will be jerky
if (isDriving) {
newRotation = vehicleController.getOrientation().normal(new Matrix3f()).getNormalizedRotation(new Quaternionf());
} else {
newRotation = vehicleController.getRenderOrientation(this.partialTickTime);
}
// Unroll the current rotation if no roll is requested and not currently freelooking.
if (Cobblemon.config.getDisableRoll()) {
// Init the smooth rotation if it has not been set yet.
if (cobblemon$smoothRotation == null) {
cobblemon$smoothRotation = new Quaternionf().set(this.rotation);
}
var rideAngs = newRotation.getEulerAnglesYXZ(new Vector3f());
var cameraAngs = cobblemon$smoothRotation.getEulerAnglesYXZ(new Vector3f());
// var vehicle = (PokemonEntity)driver.getVehicle();
// var vel = vehicle.getRidingAnimationData().getVelocitySpring().getInterpolated(this.partialTickTime, 0);
// // Grab the target yaw as the current rides yaw. If the horizontal velocity is high enough to be used to
// // derive a yaw then use it.
// var targetYaw = (double) rideAngs.y();
// if ( vel.horizontalDistance() > 0.01) {
// // lerp the new rotation towards this y rot at a rate proportional to the horizontal movement speed?
// targetYaw = Mth.wrapDegrees(Math.toDegrees(Mth.atan2(vel.x(), vel.z())) + 180.0f);
// }
var degDiff = Mth.degreesDifference((float)Math.toDegrees(cameraAngs.y()), (float)Math.toDegrees(rideAngs.y));
var pitchDeadzoneDeg = 15.0; // x degrees of deadzone about +-90 degrees of pitch.
var pitchDeg = vehicleController.getPitch();
// ConsiderPitch to be already 90 if within the deadzone around it.
var cutoffPitch = Math.min(1.0,(Mth.abs(pitchDeg) / (90.0f - pitchDeadzoneDeg))) * 90.0f * Math.signum(pitchDeg);
var lerpRateMod = Mth.cos((float)Math.toRadians(cutoffPitch));
// Apply smoothing from the cameras current yaw to the yaw of the velocity vector of the ride.
var k = 10.0f; // Some smoothing constant k
var smoothingFactor = lerpRateMod * cobblemon$frameTime * k;
var newYaw = cameraAngs.y() + (Math.toRadians(degDiff) * smoothingFactor);
var newPitch = (float)Mth.lerp(cobblemon$frameTime * k, cameraAngs.x(), rideAngs.x());
//var newYaw = (float)Mth.lerp(smoothingFactor, cameraAngs.y(), rideAngs.y());
var maxRoll = Math.toRadians(15.0f);
var newRoll = (float)Mth.lerp(cobblemon$frameTime * k / 2.0, cameraAngs.z(), Math.abs(lerpRateMod) * Math.sin(rideAngs.z()) * maxRoll);
// Set rotations
var smoothedRot = new Quaternionf().rotateYXZ((float)newYaw, newPitch, newRoll);
cobblemon$smoothRotation.set(smoothedRot);
newRotation.set(smoothedRot);
}
var rotationOffset = 0;
if (Minecraft.getInstance().options.getCameraType().isMirrored()) {
newRotation.rotateY((float)Math.toRadians(180));
rotationOffset = 180;
}
// Get the drivers local look angle in relation to the ride and apply it.
if (vehicleController.getActive()) {
var vehicleMatrix = new Matrix3f().set(newRotation);
var driverMatrix = new Matrix3f();// Base the driver
var playerRotater = (RidePassenger)driver;
newRotation = vehicleMatrix.mul(
driverMatrix.rotateYXZ(
-Mth.DEG_TO_RAD * (playerRotater.cobblemon$getRideYRot()),
-Mth.DEG_TO_RAD * playerRotater.cobblemon$getRideXRot(),
0.0f)
).normal(new Matrix3f()).getNormalizedRotation(new Quaternionf());
}
this.rotation.set(newRotation);
var eulerAngs = newRotation.getEulerAnglesXYZ(new Vector3f());
this.xRot = eulerAngs.x() * Mth.RAD_TO_DEG;
this.yRot = eulerAngs.y() * Mth.RAD_TO_DEG;
// Set the drivers rotations to match
var driverEulerAngs = new Quaternionf(this.rotation).getEulerAnglesYXZ(new Vector3f());
driver.setXRot(-driverEulerAngs.x() * Mth.RAD_TO_DEG + rotationOffset);
driver.setYRot(180.0f - (driverEulerAngs.y() * Mth.RAD_TO_DEG));
OrientationController.Companion.getFORWARDS().rotate(this.rotation, this.forwards);
OrientationController.Companion.getUP().rotate(this.rotation, this.up);
OrientationController.Companion.getLEFT().rotate(this.rotation, this.left);
}
@Unique
private void cobblemon$applyTransitionRotation(
OrientationController vehicleController,
CallbackInfo ci
) {
// If the transition has just started then
if (this.cobblemon$returnTimer == 0.0) {
MountedCameraRenderer.INSTANCE.resetDriverRotations((Camera)(Object)this, this.entity);
}
if(this.cobblemon$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.
float interpolatedRoll = Mth.lerp(this.cobblemon$returnTimer, this.cobblemon$rollAngleStart, 0.0f);
float pitch = (float) Math.toRadians(-this.entity.getXRot());
float yaw = (float) Math.toRadians(180 - this.entity.getYRot());
Quaternionf interRot = new Quaternionf();
interRot.rotationYXZ(yaw, pitch, interpolatedRoll);
this.rotation.set(interRot);
var eulerAngs = interRot.getEulerAnglesXYZ(new Vector3f());
this.xRot = eulerAngs.x() * Mth.RAD_TO_DEG;
this.yRot = eulerAngs.y() * Mth.RAD_TO_DEG;
OrientationController.Companion.getFORWARDS().rotate(this.rotation, this.forwards);
OrientationController.Companion.getUP().rotate(this.rotation, this.up);
OrientationController.Companion.getLEFT().rotate(this.rotation, this.left);
if(cobblemon$rollAngleStart == 0){
this.cobblemon$returnTimer = 1;
vehicleController.reset();
MountedCameraRenderer.INSTANCE.resetDriverRotations((Camera)(Object)this, this.entity);
return;
}
this.cobblemon$returnTimer += (partialTickTime * (1.0f/20.0f));
ci.cancel();
} else {
this.cobblemon$returnTimer = 1;
vehicleController.reset();
MountedCameraRenderer.INSTANCE.resetDriverRotations((Camera)(Object)this, this.entity);
}
}
@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.getThirdPersonViewBobbing()) {
original.call(instance, zoom, dy, dx);
}
}
}
@@ -69,12 +69,17 @@ public class HumanoidModelMixin {
behaviour.shouldRotateRiderHead(settings, state, pokemonEntity)
);
if (entity instanceof RidePassenger playerRotater) {
//this.head.yRot = playerRotater.cobblemon$getRideYRot();
this.head.xRot = playerRotater.cobblemon$getRideXRot();
headPitch = playerRotater.cobblemon$getRideXRot();
}
// If the player is on a rollable ride then use the ride local rotations to rotate the head
// This is to allow the player head to face the correct direction when "freelooking"
// TODO: find a way for this to work on built jars without borking head rotations.
// if (entity instanceof RidePassenger playerRotater &&
// vehicle instanceof OrientationControllable controller &&
// controller.getOrientationController().isActive()) {
// this.head.xRot = playerRotater.cobblemon$getRideXRot();
// headPitch = playerRotater.cobblemon$getRideXRot();
// this.head.yRot = playerRotater.cobblemon$getRideYRot();
// netHeadYaw = playerRotater.cobblemon$getRideYRot();
// }
if (!shouldRotatePlayerHead) {
netHeadYaw = 0f;
@@ -36,9 +36,9 @@ public class ItemInHandRendererMixin {
}
}
@Redirect(method = "renderHandsWithItems", at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/vertex/PoseStack;mulPose(Lorg/joml/Quaternionf;)V", ordinal = 1))
@Redirect(method = "renderHandsWithItems", at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/vertex/PoseStack;mulPose(Lorg/joml/Quaternionf;)V"))
private void cobblemon$renderHandswithItems(PoseStack instance, Quaternionf quaternion) {
if (!(Minecraft.getInstance().player instanceof OrientationControllable controllable && controllable.getOrientationController().isActive())) {
if (!(Minecraft.getInstance().player != null && Minecraft.getInstance().player.getVehicle() instanceof OrientationControllable controllable && controllable.getOrientationController().isActive())) {
instance.mulPose(quaternion);
}
}
@@ -122,8 +122,9 @@ public abstract class MouseHandlerMixin {
double cursorDeltaY,
@Local(argsOnly = true) double d,
@Local(argsOnly = true) double movementTime
) {
) {
PokedexUsageContext usageContext = CobblemonClient.INSTANCE.getPokedexUsageContext();
boolean returnValue = true;
if (usageContext.getScanningGuiOpen()) {
this.smoothTurnY.reset();
this.smoothTurnX.reset();
@@ -133,10 +134,11 @@ public abstract class MouseHandlerMixin {
var sensitivity = lerp(usageContext.getFovMultiplier(), spyglassSensitivity, lookSensitivity);
var yRotationFlip = this.minecraft.options.invertYMouse().get() ? -1 : 1;
player.turn(this.accumulatedDX * sensitivity, (this.accumulatedDY * sensitivity * yRotationFlip));
returnValue = false;
}
var vehicle = player.getVehicle();
if (!(vehicle instanceof PokemonEntity)) return true;
if (!(vehicle instanceof PokemonEntity)) return returnValue;
// Clamp player rotation if riding and the vehicle demands it
if (player.isPassenger() && vehicle instanceof PokemonEntity pokeVehicle) {
@@ -150,7 +152,7 @@ public abstract class MouseHandlerMixin {
pitchSmoother.reset();
rollSmoother.reset();
yawSmoother.reset();
return true;
return returnValue;
}
var vehicleController = controllableVehicle.getOrientationController();
@@ -221,7 +223,7 @@ public abstract class MouseHandlerMixin {
vehicleController.rotate((float) (angRot.x * 10 * d), (float) (angRot.y * 10 * d), (float) (angRot.z * 10 * d));
}
return false;
return returnValue;
}
@Inject(method = "handleAccumulatedMovement", at = @At("HEAD"))
@@ -308,6 +310,7 @@ public abstract class MouseHandlerMixin {
playerRotater.cobblemon$setRideXRot(playerRotater.cobblemon$getRideXRot() + f);
playerRotater.cobblemon$setRideYRot(playerRotater.cobblemon$getRideYRot() + g);
playerRotater.cobblemon$setRideXRot(Mth.clamp(playerRotater.cobblemon$getRideXRot(), -90.0F, 90.0F));
playerRotater.cobblemon$setRideYRot(Mth.clamp(playerRotater.cobblemon$getRideYRot(), -105.0F, 105.0F));
if (player.getVehicle() != null) {
player.getVehicle().onPassengerTurned(player);
}
@@ -52,7 +52,7 @@ public class RecipeBookCategoriesMixin {
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.LEEK_AND_POTATO_STEW)));
types.add(cobblemon$createCategory("COOKING_POT_MEDICINES", $VALUES.length + 2, new ItemStack(CobblemonItems.POTION)));
types.add(cobblemon$createCategory("COOKING_POT_COMPLEX_DISHES", $VALUES.length + 3, new ItemStack(CobblemonItems.POKE_PUFF)));
types.add(cobblemon$createCategory("COOKING_POT_COMPLEX_DISHES", $VALUES.length + 3, new ItemStack(CobblemonItems.APRIJUICE_RED)));
types.add(cobblemon$createCategory("COOKING_POT_MISC", $VALUES.length + 4, new ItemStack(CobblemonItems.PROTEIN)));
$VALUES = types.toArray(RecipeBookCategories[]::new);
}
@@ -13,6 +13,7 @@ import com.cobblemon.mod.common.duck.RidePassenger;
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity;
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
import net.minecraft.client.player.LocalPlayer;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.world.entity.Entity;
@@ -68,6 +69,7 @@ public abstract class EntityMixin {
)
private void cobblemon$modifyEyePosition_partial(float partialTicks, CallbackInfoReturnable<Vec3> cir) {
var entity = (Entity)(Object)this;
if (entity.level().isClientSide) return;
if (!(entity instanceof Player player)) return;
if (!(player instanceof RidePassenger ridePassenger)) return;
if (!(player.getVehicle() instanceof OrientationControllable vehicle)) return;
@@ -78,7 +80,6 @@ public abstract class EntityMixin {
// TODO: Determine if it needs partialtick involved.
Vec3 customEyePos = ridePassenger.cobblemon$getRideEyePos();
cir.setReturnValue(customEyePos);
}
@Inject(
@@ -88,6 +89,7 @@ public abstract class EntityMixin {
)
private void cobblemon$modifyEyePosition_noPartial(CallbackInfoReturnable<Vec3> cir) {
var entity = (Entity)(Object)this;
if (entity.level().isClientSide) return;
if (!(entity instanceof Player player)) return;
if (!(player instanceof RidePassenger ridePassenger)) return;
if (!(player.getVehicle() instanceof OrientationControllable vehicle)) return;
@@ -19,6 +19,7 @@ import com.cobblemon.mod.common.api.drop.ItemDropEntry
import com.cobblemon.mod.common.api.events.CobblemonEvents
import com.cobblemon.mod.common.api.events.CobblemonEvents.DATA_SYNCHRONIZED
import com.cobblemon.mod.common.api.interaction.RequestManager
import com.cobblemon.mod.common.api.molang.MoLangLoadedFilesCache
import com.cobblemon.mod.common.api.molang.ObjectValue
import com.cobblemon.mod.common.api.permission.PermissionValidator
import com.cobblemon.mod.common.api.pokeball.catching.calculators.CaptureCalculator
@@ -44,6 +45,7 @@ import com.cobblemon.mod.common.api.spawning.CobblemonSpawningZoneGenerator
import com.cobblemon.mod.common.api.spawning.position.AreaSpawnablePositionResolver
import com.cobblemon.mod.common.api.spawning.SpawningZoneGenerator
import com.cobblemon.mod.common.api.starter.StarterHandler
import com.cobblemon.mod.common.api.stats.CobblemonStats
import com.cobblemon.mod.common.api.storage.PokemonStoreManager
import com.cobblemon.mod.common.api.storage.adapter.conversions.ReforgedConversion
import com.cobblemon.mod.common.api.storage.adapter.database.MongoDBStoreAdapter
@@ -79,6 +81,7 @@ import com.cobblemon.mod.common.events.EntityCallbackHandler
import com.cobblemon.mod.common.events.CallbackHandler
import com.cobblemon.mod.common.events.PokedexHandler
import com.cobblemon.mod.common.events.ServerTickHandler
import com.cobblemon.mod.common.events.StatHandler
import com.cobblemon.mod.common.net.messages.client.settings.ServerSettingsPacket
import com.cobblemon.mod.common.permission.LaxPermissionValidator
import com.cobblemon.mod.common.platform.events.PlatformEvents
@@ -88,6 +91,8 @@ import com.cobblemon.mod.common.pokemon.aspects.COSMETIC_SLOT_ASPECT
import com.cobblemon.mod.common.pokemon.aspects.GENDER_ASPECT
import com.cobblemon.mod.common.pokemon.aspects.SHINY_ASPECT
import com.cobblemon.mod.common.pokemon.evolution.variants.BlockClickEvolution
import com.cobblemon.mod.common.pokemon.feature.SlowpokeTailRegrowthSpeciesFeature
import com.cobblemon.mod.common.pokemon.feature.SlowpokeTailRegrowthSpeciesFeatureProvider
import com.cobblemon.mod.common.pokemon.feature.TagSeasonResolver
import com.cobblemon.mod.common.pokemon.helditem.CobblemonHeldItemManager
import com.cobblemon.mod.common.pokemon.properties.*
@@ -162,6 +167,8 @@ object Cobblemon {
val serverPlayerStructs = mutableMapOf<UUID, ObjectValue<Player>>()
val statistics: CobblemonStats = CobblemonStats
@JvmStatic
val builtinPacks = listOf<CobblemonPack>(
CobblemonPack(id = "adorncompatibility", name = "Adorn Compatibility", packType = PackType.CLIENT_RESOURCES, activationBehaviour = ResourcePackActivationBehaviour.ALWAYS_ENABLED, neededMods = setOf("adorn")),
@@ -302,7 +309,13 @@ object Cobblemon {
SpeciesFeatures.register(
DataKeys.HAS_BEEN_SHEARED,
FlagSpeciesFeatureProvider(keys = listOf(DataKeys.HAS_BEEN_SHEARED), default = false))
FlagSpeciesFeatureProvider(keys = listOf(DataKeys.HAS_BEEN_SHEARED), default = false)
)
SpeciesFeatures.register(
SlowpokeTailRegrowthSpeciesFeature.NAME,
SlowpokeTailRegrowthSpeciesFeatureProvider
)
CustomPokemonProperty.register(UncatchableProperty)
CustomPokemonProperty.register(BattleCloneProperty)
@@ -331,6 +344,7 @@ object Cobblemon {
}
PlatformEvents.SERVER_STARTING.subscribe { event ->
val server = event.server
MoLangLoadedFilesCache.initialize(server)
playerDataManager = PlayerInstancedDataStoreManager().also { it.setup(server) }
val mongoClient: MongoClient?
@@ -433,6 +447,7 @@ object Cobblemon {
fun registerEventHandlers() {
AdvancementHandler.registerListeners()
PokedexHandler.registerListeners()
StatHandler.registerListeners()
}
fun getLevel(dimension: ResourceKey<Level>): Level? {
@@ -11,16 +11,26 @@ package com.cobblemon.mod.common
import net.minecraft.world.entity.schedule.Activity
object CobblemonActivities {
@JvmField
val activities = mutableListOf<Activity>()
@JvmField
val BATTLING = register(Activity("battling"))
@JvmField
val ACTION_EFFECT = register(Activity("action_effect"))
@JvmField
val NPC_CHATTING = register(Activity("npc_chatting"))
@JvmField
val POKEMON_SLEEPING_ACTIVITY = register(Activity("pokemon_sleeping"))
@JvmField
val POKEMON_GROW_CROP = register(Activity("pokemon_grow_crop"))
@JvmField
val POKEMON_SLEEP_ON_TRAINER_BED = register(Activity("pokemon_sleep_on_trainer_bed"))
@JvmField
val POKEMON_HERD = register(Activity("pokemon_herd"))
@JvmField
val POKEMON_POLLINATION = register(Activity("pokemon_pollination"))
@JvmStatic
fun register(activity: Activity): Activity {
activities.add(activity)
return activity
@@ -60,13 +60,13 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
// Evolution Ores
@JvmField
val DAWN_STONE_ORE = evolutionStoneOre("dawn_stone_ore")
val DAWN_STONE_ORE = evolutionStoneOre("dawn_stone_ore", 7)
@JvmField
val DUSK_STONE_ORE = evolutionStoneOre("dusk_stone_ore")
@JvmField
val FIRE_STONE_ORE = evolutionStoneOre("fire_stone_ore")
val FIRE_STONE_ORE = evolutionStoneOre("fire_stone_ore", 10)
@JvmField
val NETHER_FIRE_STONE_ORE = evolutionStoneOre("nether_fire_stone_ore")
val NETHER_FIRE_STONE_ORE = this.create("nether_fire_stone_ore", DropExperienceBlock(UniformInt.of(1, 2), BlockBehaviour.Properties.of().mapColor(MapColor.NETHER).instrument(NoteBlockInstrument.BASEDRUM).requiresCorrectToolForDrops().strength(3.0F, 3.0F).sound(SoundType.NETHER_ORE).lightLevel{10}))
@JvmField
val ICE_STONE_ORE = evolutionStoneOre("ice_stone_ore")
@JvmField
@@ -74,24 +74,24 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
@JvmField
val MOON_STONE_ORE = evolutionStoneOre("moon_stone_ore")
@JvmField
val DRIPSTONE_MOON_STONE_ORE = evolutionStoneOre("dripstone_moon_stone_ore")
val DRIPSTONE_MOON_STONE_ORE = this.create("dripstone_moon_stone_ore", DropExperienceBlock(UniformInt.of(1, 2), BlockBehaviour.Properties.of().mapColor(MapColor.TERRACOTTA_BROWN).instrument(NoteBlockInstrument.BASEDRUM).requiresCorrectToolForDrops().strength(3.0F, 3.0F).sound(SoundType.DRIPSTONE_BLOCK)))
@JvmField
val SHINY_STONE_ORE = evolutionStoneOre("shiny_stone_ore")
val SHINY_STONE_ORE = evolutionStoneOre("shiny_stone_ore", 12)
@JvmField
val SUN_STONE_ORE = evolutionStoneOre("sun_stone_ore")
val SUN_STONE_ORE = evolutionStoneOre("sun_stone_ore", 2)
@JvmField
val TERRACOTTA_SUN_STONE_ORE = evolutionStoneOre("terracotta_sun_stone_ore")
val TERRACOTTA_SUN_STONE_ORE = this.create("terracotta_sun_stone_ore", DropExperienceBlock(UniformInt.of(1, 2), BlockBehaviour.Properties.of().mapColor(MapColor.COLOR_ORANGE).instrument(NoteBlockInstrument.BASEDRUM).requiresCorrectToolForDrops().strength(3.0F, 3.0F).lightLevel{2}))
@JvmField
val THUNDER_STONE_ORE = evolutionStoneOre("thunder_stone_ore")
val THUNDER_STONE_ORE = evolutionStoneOre("thunder_stone_ore", 6)
@JvmField
val WATER_STONE_ORE = evolutionStoneOre("water_stone_ore")
@JvmField
val DEEPSLATE_DAWN_STONE_ORE = this.deepslateEvolutionStoneOre("deepslate_dawn_stone_ore")
val DEEPSLATE_DAWN_STONE_ORE = this.deepslateEvolutionStoneOre("deepslate_dawn_stone_ore", 7)
@JvmField
val DEEPSLATE_DUSK_STONE_ORE = this.deepslateEvolutionStoneOre("deepslate_dusk_stone_ore")
@JvmField
val DEEPSLATE_FIRE_STONE_ORE = this.deepslateEvolutionStoneOre("deepslate_fire_stone_ore")
val DEEPSLATE_FIRE_STONE_ORE = this.deepslateEvolutionStoneOre("deepslate_fire_stone_ore", 10)
@JvmField
val DEEPSLATE_ICE_STONE_ORE = this.deepslateEvolutionStoneOre("deepslate_ice_stone_ore")
@JvmField
@@ -99,11 +99,11 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
@JvmField
val DEEPSLATE_MOON_STONE_ORE = this.deepslateEvolutionStoneOre("deepslate_moon_stone_ore")
@JvmField
val DEEPSLATE_SHINY_STONE_ORE = this.deepslateEvolutionStoneOre("deepslate_shiny_stone_ore")
val DEEPSLATE_SHINY_STONE_ORE = this.deepslateEvolutionStoneOre("deepslate_shiny_stone_ore", 12)
@JvmField
val DEEPSLATE_SUN_STONE_ORE = this.deepslateEvolutionStoneOre("deepslate_sun_stone_ore")
val DEEPSLATE_SUN_STONE_ORE = this.deepslateEvolutionStoneOre("deepslate_sun_stone_ore", 2)
@JvmField
val DEEPSLATE_THUNDER_STONE_ORE = this.deepslateEvolutionStoneOre("deepslate_thunder_stone_ore")
val DEEPSLATE_THUNDER_STONE_ORE = this.deepslateEvolutionStoneOre("deepslate_thunder_stone_ore", 6)
@JvmField
val DEEPSLATE_WATER_STONE_ORE = this.deepslateEvolutionStoneOre("deepslate_water_stone_ore")
@@ -454,7 +454,7 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
@JvmField
val SOUL_CAMPFIRE = create("soul_campfire", CampfireBlock(BlockBehaviour.Properties.of().sound(SoundType.WOOD).noOcclusion().pushReaction(PushReaction.BLOCK).mapColor(MapColor.PODZOL).strength(2.0F).lightLevel{9}, true))
@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
@@ -577,75 +577,145 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
private val berries = mutableMapOf<ResourceLocation, BerryBlock>()
@JvmField
val AGUAV_BERRY = this.berryBlock("aguav")
@JvmField
val APICOT_BERRY = this.berryBlock("apicot")
@JvmField
val ASPEAR_BERRY = this.berryBlock("aspear")
@JvmField
val BABIRI_BERRY = this.berryBlock("babiri")
@JvmField
val BELUE_BERRY = this.berryBlock("belue")
@JvmField
val BLUK_BERRY = this.berryBlock("bluk")
@JvmField
val CHARTI_BERRY = this.berryBlock("charti")
@JvmField
val CHERI_BERRY = this.berryBlock("cheri")
@JvmField
val CHESTO_BERRY = this.berryBlock("chesto")
@JvmField
val CHILAN_BERRY = this.berryBlock("chilan")
@JvmField
val CHOPLE_BERRY = this.berryBlock("chople")
@JvmField
val COBA_BERRY = this.berryBlock("coba")
@JvmField
val COLBUR_BERRY = this.berryBlock("colbur")
@JvmField
val CORNN_BERRY = this.berryBlock("cornn")
@JvmField
val CUSTAP_BERRY = this.berryBlock("custap")
@JvmField
val DURIN_BERRY = this.berryBlock("durin")
@JvmField
val EGGANT_BERRY = this.berryBlock("eggant")
@JvmField
val ENIGMA_BERRY = this.berryBlock("enigma")
@JvmField
val FIGY_BERRY = this.berryBlock("figy")
@JvmField
val GANLON_BERRY = this.berryBlock("ganlon")
@JvmField
val GREPA_BERRY = this.berryBlock("grepa")
@JvmField
val HABAN_BERRY = this.berryBlock("haban")
@JvmField
val HONDEW_BERRY = this.berryBlock("hondew")
@JvmField
val HOPO_BERRY = this.berryBlock("hopo")
@JvmField
val IAPAPA_BERRY = this.berryBlock("iapapa")
@JvmField
val JABOCA_BERRY = this.berryBlock("jaboca")
@JvmField
val KASIB_BERRY = this.berryBlock("kasib")
@JvmField
val KEBIA_BERRY = this.berryBlock("kebia")
@JvmField
val KEE_BERRY = this.berryBlock("kee")
@JvmField
val KELPSY_BERRY = this.berryBlock("kelpsy")
@JvmField
val LANSAT_BERRY = this.berryBlock("lansat")
@JvmField
val LEPPA_BERRY = this.berryBlock("leppa")
@JvmField
val LIECHI_BERRY = this.berryBlock("liechi")
@JvmField
val LUM_BERRY = this.berryBlock("lum")
@JvmField
val MAGO_BERRY = this.berryBlock("mago")
@JvmField
val MAGOST_BERRY = this.berryBlock("magost")
@JvmField
val MARANGA_BERRY = this.berryBlock("maranga")
@JvmField
val MICLE_BERRY = this.berryBlock("micle")
@JvmField
val NANAB_BERRY = this.berryBlock("nanab")
@JvmField
val NOMEL_BERRY = this.berryBlock("nomel")
@JvmField
val OCCA_BERRY = this.berryBlock("occa")
@JvmField
val ORAN_BERRY = this.berryBlock("oran")
@JvmField
val PAMTRE_BERRY = this.berryBlock("pamtre")
@JvmField
val PASSHO_BERRY = this.berryBlock("passho")
@JvmField
val PAYAPA_BERRY = this.berryBlock("payapa")
@JvmField
val PECHA_BERRY = this.berryBlock("pecha")
@JvmField
val PERSIM_BERRY = this.berryBlock("persim")
@JvmField
val PETAYA_BERRY = this.berryBlock("petaya")
@JvmField
val PINAP_BERRY = this.berryBlock("pinap")
@JvmField
val POMEG_BERRY = this.berryBlock("pomeg")
@JvmField
val QUALOT_BERRY = this.berryBlock("qualot")
@JvmField
val RABUTA_BERRY = this.berryBlock("rabuta")
@JvmField
val RAWST_BERRY = this.berryBlock("rawst")
@JvmField
val RAZZ_BERRY = this.berryBlock("razz")
@JvmField
val RINDO_BERRY = this.berryBlock("rindo")
@JvmField
val ROSELI_BERRY = this.berryBlock("roseli")
@JvmField
val ROWAP_BERRY = this.berryBlock("rowap")
@JvmField
val SALAC_BERRY = this.berryBlock("salac")
@JvmField
val SHUCA_BERRY = this.berryBlock("shuca")
@JvmField
val SITRUS_BERRY = this.berryBlock("sitrus")
@JvmField
val SPELON_BERRY = this.berryBlock("spelon")
@JvmField
val STARF_BERRY = this.berryBlock("starf")
@JvmField
val TAMATO_BERRY = this.berryBlock("tamato")
@JvmField
val TANGA_BERRY = this.berryBlock("tanga")
@JvmField
val TOUGA_BERRY = this.berryBlock("touga")
@JvmField
val WACAN_BERRY = this.berryBlock("wacan")
@JvmField
val WATMEL_BERRY = this.berryBlock("watmel")
@JvmField
val WEPEAR_BERRY = this.berryBlock("wepear")
@JvmField
val WIKI_BERRY = this.berryBlock("wiki")
@JvmField
val YACHE_BERRY = this.berryBlock("yache")
//val BINDING_SOIL = this.create("binding_soil", BindingSoilBlock(BlockBehaviour.Properties.of()))
@@ -713,8 +783,10 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
}
private fun evolutionStoneOre(name: String) = this.create(name, DropExperienceBlock(UniformInt.of(1, 2), BlockBehaviour.Properties.ofFullCopy(Blocks.IRON_ORE)))
private fun evolutionStoneOre(name: String, lightLevel: Int) = this.create(name, DropExperienceBlock(UniformInt.of(1, 2), BlockBehaviour.Properties.ofFullCopy(Blocks.IRON_ORE).lightLevel { lightLevel }))
private fun deepslateEvolutionStoneOre(name: String) = this.create(name, DropExperienceBlock(UniformInt.of(1, 2), BlockBehaviour.Properties.ofFullCopy(Blocks.DEEPSLATE_IRON_ORE)))
private fun deepslateEvolutionStoneOre(name: String, lightLevel: Int) = this.create(name, DropExperienceBlock(UniformInt.of(1, 2), BlockBehaviour.Properties.ofFullCopy(Blocks.DEEPSLATE_IRON_ORE).lightLevel { lightLevel }))
/**
* Helper method for creating leaves
@@ -43,6 +43,7 @@ object CobblemonCosmeticItems : JsonDataRegistry<CosmeticItemAssignment> {
.registerTypeAdapter(ResourceLocation::class.java, IdentifierAdapter)
.create()
@JvmField
val cosmeticItems = mutableListOf<CosmeticItemAssignment>()
override fun reload(data: Map<ResourceLocation, CosmeticItemAssignment>) {
@@ -55,7 +56,9 @@ object CobblemonCosmeticItems : JsonDataRegistry<CosmeticItemAssignment> {
CosmeticItemAssignmentSyncPacket(cosmeticItems).sendToPlayer(player)
}
@JvmStatic
fun findValidForPokemon(pokemon: Pokemon) = cosmeticItems.filter { it.pokemon.any { it.matches(pokemon) } }
@JvmStatic
fun findValidCosmeticForPokemonAndItem(registryAccess: RegistryAccess, pokemon: Pokemon, itemStack: ItemStack) = cosmeticItems
.filter { it.pokemon.any { it.matches(pokemon) } }
.flatMap { it.cosmeticItems }
@@ -21,61 +21,73 @@ import net.minecraft.resources.ResourceLocation
object CobblemonItemComponents : PlatformRegistry<Registry<DataComponentType<*>>, ResourceKey<Registry<DataComponentType<*>>>, DataComponentType<*>>() {
@JvmField
val POKEMON_ITEM: DataComponentType<PokemonItemComponent> = create("pokemon_item", DataComponentType.builder<PokemonItemComponent>()
.persistent(PokemonItemComponent.CODEC)
.networkSynchronized(PokemonItemComponent.PACKET_CODEC)
.build())
@JvmField
val HELD_ITEM_EFFECT: DataComponentType<HeldItemEffectComponent> = create("held_item_effect", DataComponentType.builder<HeldItemEffectComponent>()
.persistent(HeldItemEffectComponent.CODEC)
.networkSynchronized(HeldItemEffectComponent.PACKET_CODEC)
.build())
@JvmField
val BAIT: DataComponentType<RodBaitComponent> = create("bait", DataComponentType.builder<RodBaitComponent>()
.persistent(RodBaitComponent.CODEC)
.networkSynchronized(RodBaitComponent.PACKET_CODEC)
.build())
@JvmField
val POT_DATA: DataComponentType<PotComponent> = create("cooking_pot_item", DataComponentType.builder<PotComponent>()
.persistent(PotComponent.CODEC)
.networkSynchronized(PotComponent.PACKET_CODEC)
.build())
@JvmField
val BAIT_EFFECTS: DataComponentType<BaitEffectsComponent> = create("bait_effects", DataComponentType.builder<BaitEffectsComponent>()
.persistent(BaitEffectsComponent.CODEC)
.networkSynchronized(BaitEffectsComponent.PACKET_CODEC)
.build())
@JvmField
val FLAVOUR: DataComponentType<FlavourComponent> = create("flavour", DataComponentType.builder<FlavourComponent>()
.persistent(FlavourComponent.CODEC)
.networkSynchronized(FlavourComponent.PACKET_CODEC)
.build())
@JvmField
val RIDE_BOOST: DataComponentType<RideBoostsComponent> = create("ride_boosts", DataComponentType.builder<RideBoostsComponent>()
.persistent(RideBoostsComponent.CODEC)
.networkSynchronized(RideBoostsComponent.PACKET_CODEC)
.build())
@JvmField
val FOOD_COLOUR: DataComponentType<FoodColourComponent> = create("food_colour", DataComponentType.builder<FoodColourComponent>()
.persistent(FoodColourComponent.CODEC)
.networkSynchronized(FoodColourComponent.PACKET_CODEC)
.build())
@JvmField
val INGREDIENT: DataComponentType<IngredientComponent> = create("ingredient", DataComponentType.builder<IngredientComponent>()
.persistent(IngredientComponent.CODEC)
.networkSynchronized(IngredientComponent.PACKET_CODEC)
.build())
@JvmField
val FOOD: DataComponentType<FoodComponent> = create("food", DataComponentType.builder<FoodComponent>()
.persistent(FoodComponent.CODEC)
.networkSynchronized(FoodComponent.PACKET_CODEC)
.build())
@JvmField
val MOB_EFFECTS: DataComponentType<MobEffectsComponent> = create("mob_effects", DataComponentType.builder<MobEffectsComponent>()
.persistent(MobEffectsComponent.CODEC)
.networkSynchronized(MobEffectsComponent.PACKET_CODEC)
.build())
@JvmField
val CRAFTED: DataComponentType<Boolean> = create("crafted", DataComponentType.builder<Boolean>()
.persistent(Codec.BOOL)
.networkSynchronized(ByteBufCodecs.BOOL)
@@ -382,8 +382,8 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
@JvmField
val SINISTER_TEA = create("sinister_tea", SinisterTeaItem())
@JvmField
val POKE_PUFF = pokepuffItem("poke_puff")
// @JvmField
// val POKE_PUFF = pokepuffItem("poke_puff")
// FOODS
@JvmField
@@ -683,7 +683,7 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
}
})
@JvmField
val ENERGY_ROOT = compostableItem("energy_root", EnergyRootItem(CobblemonBlocks.ENERGY_ROOT, Properties()), 0.60f)
val ENERGY_ROOT = compostableItem("energy_root", EnergyRootItem(CobblemonBlocks.ENERGY_ROOT, Properties()), 0.65f)
@JvmField
val REVIVAL_HERB = compostableItem("revival_herb", RevivalHerbItem(CobblemonBlocks.REVIVAL_HERB))
@JvmField
@@ -693,9 +693,9 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
@JvmField
val REMEDY = compostableItem("remedy", RemedyItem(RemedyItem.NORMAL), 0.65f)
@JvmField
val FINE_REMEDY = compostableItem("fine_remedy", RemedyItem(RemedyItem.FINE), 0.75f)
val FINE_REMEDY = compostableItem("fine_remedy", RemedyItem(RemedyItem.FINE), 0.85f)
@JvmField
val SUPERB_REMEDY = compostableItem("superb_remedy", RemedyItem(RemedyItem.SUPERB), 0.85f)
val SUPERB_REMEDY = compostableItem("superb_remedy", RemedyItem(RemedyItem.SUPERB), 1f)
@JvmField
val MOOMOO_MILK = create("moomoo_milk", MoomooMilk(Item.Properties().craftRemainder(Items.GLASS_BOTTLE).stacksTo((16))))
@@ -915,7 +915,7 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
@JvmField
val ASSAULT_VEST = heldItem("assault_vest")
@JvmField
val BIG_ROOT = compostableBlockItem("big_root", CobblemonBlocks.BIG_ROOT, 0.40f)
val BIG_ROOT = compostableBlockItem("big_root", CobblemonBlocks.BIG_ROOT, 0.30f)
@JvmField
val BINDING_BAND = heldItem("binding_band")
@JvmField
@@ -1063,15 +1063,15 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
@JvmField
val ZOOM_LENS = heldItem("zoom_lens")
@JvmField
val MENTAL_HERB = compostableHeldItem("mental_herb", null, 1F)
val MENTAL_HERB = compostableHeldItem("mental_herb", null, 0.85F)
@JvmField
val MIRROR_HERB = compostableHeldItem("mirror_herb", null, 1F)
val MIRROR_HERB = compostableHeldItem("mirror_herb", null, 0.85F)
@JvmField
val MISTY_SEED = heldItem("misty_seed")
@JvmField
val POWER_HERB = compostableHeldItem("power_herb", null, 1F)
val POWER_HERB = compostableHeldItem("power_herb", null, 0.85F)
@JvmField
val WHITE_HERB = compostableHeldItem("white_herb", null, 1F)
val WHITE_HERB = compostableHeldItem("white_herb", null, 0.85F)
@JvmField
val BRIGHT_POWDER = heldItem("bright_powder")
@JvmField
@@ -16,6 +16,8 @@ import com.cobblemon.mod.common.mechanics.AprijuicesMechanic
import com.cobblemon.mod.common.mechanics.BerriesMechanic
import com.cobblemon.mod.common.mechanics.PotionsMechanic
import com.cobblemon.mod.common.mechanics.RemediesMechanic
import com.cobblemon.mod.common.mechanics.SlowpokeTailsMechanic
import com.cobblemon.mod.common.net.messages.client.data.CobblemonMechanicsSyncPacket
import com.cobblemon.mod.common.util.adapters.ExpressionAdapter
import com.cobblemon.mod.common.util.adapters.ExpressionLikeAdapter
import com.cobblemon.mod.common.util.cobblemonResource
@@ -39,14 +41,24 @@ object CobblemonMechanics : DataRegistry {
var berries = BerriesMechanic()
var potions = PotionsMechanic()
var aprijuices = AprijuicesMechanic()
var slowpokeTails = SlowpokeTailsMechanic()
override fun sync(player: ServerPlayer) {}
override fun sync(player: ServerPlayer) {
CobblemonMechanicsSyncPacket(
this.remedies,
this.berries,
this.potions,
this.aprijuices,
this.slowpokeTails
).sendToPlayer(player)
}
override fun reload(manager: ResourceManager) {
remedies = loadMechanic(manager, "remedies", RemediesMechanic::class.java)
berries = loadMechanic(manager, "berries", BerriesMechanic::class.java)
potions = loadMechanic(manager, "potions", PotionsMechanic::class.java)
aprijuices = loadMechanic(manager, "aprijuices", AprijuicesMechanic::class.java)
slowpokeTails = loadMechanic(manager, "slowpoke_tails", SlowpokeTailsMechanic::class.java)
}
private fun <T> loadMechanic(manager: ResourceManager, name: String, clazz: Class<T>): T {
@@ -30,49 +30,80 @@ object CobblemonMemories {
* get serialized during relogs. This makes sense for things like battles which
* do not survive a relog therefore any memory of it should be temporary.
*/
@JvmField
val BATTLING_POKEMON = register("battling_pokemon", ListCodec(UUIDUtil.CODEC, 0, 31))
@JvmField
val NPC_BATTLING = register("npc_battling", PrimitiveCodec.BOOL)
@JvmField
val DIALOGUES = register<List<ActiveDialogue>>("npc_dialogues")
@JvmField
val ACTIVE_ACTION_EFFECT = register<ActionEffectContext>("active_action_effect")
@JvmField
val POKEMON_FLYING = register("pokemon_flying", PrimitiveCodec.BOOL)
@JvmField
val POKEMON_DROWSY = register("pokemon_drowsy", PrimitiveCodec.BOOL)
@JvmField
val POKEMON_SLEEPING = register("pokemon_sleeping", PrimitiveCodec.BOOL)
@JvmField
val POKEMON_BATTLE = register<UUID>("pokemon_battle")
@JvmField
val PATH_COOLDOWN = register<Boolean>("path_cooldown")
@JvmField
val TARGETED_BATTLE_POKEMON = register<UUID>("targeted_battle_pokemon")
@JvmField
val NEAREST_VISIBLE_ATTACKER = register<LivingEntity>("nearest_visible_attacker")
@JvmField
val NEARBY_GROWABLE_CROPS = register<BlockPos>("nearby_growable_crops")
@JvmField
val NEARBY_SWEET_BERRY_BUSH = register<BlockPos>("nearest_sweet_berry_bush")
@JvmField
val DISABLE_WALK_TO_BERRY_BUSH = register<Boolean>("disable_walk_to_berry_bush")
@JvmField
val TIME_TRYING_TO_REACH_BERRY_BUSH = register<Int>("time_trying_to_reach_berry_bush")
@JvmField
val IS_CONSUMING_ITEM = register<Boolean>("is_consuming_item")
@JvmField
val RECENTLY_ATE_GRASS = register<Boolean>("recently_ate_grass")
@JvmField
val HIVE_LOCATION = register<BlockPos>("hive_location", BlockPos.CODEC)
@JvmField
val HIVE_BLACKLIST = register<List<BlockPos>>("hive_blacklist")
@JvmField
val HIVE_COOLDOWN = register<Boolean>("hive_cooldown")
@JvmField
val NEARBY_FLOWER = register<BlockPos>("nearby_flower", BlockPos.CODEC)
@JvmField
val PATH_TO_NEARBY_FLOWER_COOLDOWN = register<Boolean>("path_to_nearby_flower_cooldown")
@JvmField
val HAS_NECTAR = register<Boolean>("has_nectar", PrimitiveCodec.BOOL)
@JvmField
val NEARBY_SACC_LEAVES = register<BlockPos>("nearby_sacc_leaves", BlockPos.CODEC)
/** who am i following rn? */
@JvmField
val HERD_LEADER = register<String>("herd_leader", PrimitiveCodec.STRING)
/** how many are following me rn? */
@JvmField
val HERD_SIZE = register<Int>("herd_size") // Don't bother saving it, we'll try to keep count roughly.
@JvmField
val ATTACK_TARGET_DATA = register<CobblemonAttackTargetData>("attack_target_data") // This is used to store additional information about the attack target, such as when to give up pursuit.
@JvmField
val WANDER_CONTROL = register<CobblemonWanderControl>("wander_control")
@JvmField
val DISABLE_WALK_TO_WANTED_ITEM = register<Boolean>("disable_walk_to_wanted_item")
@JvmField
val TIME_TRYING_TO_REACH_WANTED_ITEM = register<Int>("time_trying_to_wanted_item")
@JvmStatic
fun <U> register(id: String, codec: Codec<U>): MemoryModuleType<U> {
val memoryModule = MemoryModuleType(Optional.of(codec))
memories[id] = memoryModule
return memoryModule
}
@JvmStatic
fun <U> register(id: String): MemoryModuleType<U> {
val memoryModule = MemoryModuleType<U>(Optional.empty())
memories[id] = memoryModule
return memoryModule
}
}
}
@@ -19,8 +19,10 @@ 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.CobblemonMechanicsSyncHandler
import com.cobblemon.mod.common.client.net.data.DataRegistrySyncPacketHandler
import com.cobblemon.mod.common.client.net.data.RideSettingsSyncHandler
import com.cobblemon.mod.common.client.net.debug.OpenRidingStatsDebugGUIHandler
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.PokeSnackBlockParticlesHandler
@@ -78,6 +80,7 @@ import com.cobblemon.mod.common.net.messages.client.callback.OpenPartyMoveCallba
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.RequestOpenRidingStatsDebugGUIPacket
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.PokeSnackBlockParticlesPacket
@@ -159,6 +162,7 @@ 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.OpenRidingStatsDebugGUIPacket
import com.cobblemon.mod.common.net.messages.server.debug.ServerboundUpdateRidingSettingsPacket
import com.cobblemon.mod.common.net.messages.server.debug.ServerboundUpdateRidingStatRangePacket
import com.cobblemon.mod.common.net.messages.server.debug.ServerboundUpdateRidingStatsPacket
@@ -212,6 +216,7 @@ 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.RequestOpenRidingStatsDebugGUIHandler
import com.cobblemon.mod.common.net.serverhandling.debug.ServerboundUpdateRidingSettingsHandler
import com.cobblemon.mod.common.net.serverhandling.debug.ServerboundUpdateRidingStatRangeHandler
import com.cobblemon.mod.common.net.serverhandling.debug.ServerboundUpdateRidingStatsHandler
@@ -267,10 +272,13 @@ object CobblemonNetwork {
fun ServerPlayer.sendPacket(packet: NetworkPacket<*>) {
sendPacketToPlayer(this, packet)
}
@JvmStatic
fun sendToServer(packet: NetworkPacket<*>) {
Cobblemon.implementation.networkManager.sendToServer(packet)
}
@JvmStatic
fun sendToAllPlayers(packet: NetworkPacket<*>) = sendPacketToPlayers(server()!!.playerList.players, packet)
@JvmStatic
fun sendPacketToPlayers(players: Iterable<ServerPlayer>, packet: NetworkPacket<*>) = players.forEach { sendPacketToPlayer(it, packet) }
val s2cPayloads = generateS2CPacketInfoList()
@@ -392,6 +400,7 @@ object CobblemonNetwork {
// Data registries
list.add(PacketRegisterInfo(AbilityRegistrySyncPacket.ID, AbilityRegistrySyncPacket::decode, DataRegistrySyncPacketHandler()))
list.add(PacketRegisterInfo(CobblemonMechanicsSyncPacket.ID, CobblemonMechanicsSyncPacket::decode, CobblemonMechanicsSyncHandler))
list.add(PacketRegisterInfo(MovesRegistrySyncPacket.ID, MovesRegistrySyncPacket::decode, DataRegistrySyncPacketHandler()))
list.add(PacketRegisterInfo(BerryRegistrySyncPacket.ID, BerryRegistrySyncPacket::decode, DataRegistrySyncPacketHandler()))
list.add(PacketRegisterInfo(SpeciesRegistrySyncPacket.ID, SpeciesRegistrySyncPacket::decode, DataRegistrySyncPacketHandler()))
@@ -482,6 +491,9 @@ object CobblemonNetwork {
list.add(PacketRegisterInfo(ClientboundUpdateRidingStatePacket.ID, ClientboundUpdateRidingStatePacket::decode, ClientboundUpdateRidingStateHandler))
list.add(PacketRegisterInfo(ClientboundUpdateDriverInputPacket.ID, ClientboundUpdateDriverInputPacket::decode, ClientboundUpdateDriverInputHandler))
// Debug
list.add(PacketRegisterInfo(OpenRidingStatsDebugGUIPacket.ID, OpenRidingStatsDebugGUIPacket::decode, OpenRidingStatsDebugGUIHandler))
return list
}
@@ -598,10 +610,13 @@ object CobblemonNetwork {
list.add(PacketRegisterInfo(SetEntityBehaviourPacket.ID, SetEntityBehaviourPacket::decode, SetEntityBehaviourHandler))
list.add(PacketRegisterInfo(DamageOnCollisionPacket.ID, DamageOnCollisionPacket::decode, DamageOnCollisionPacketHandler))
// Debug
list.add(PacketRegisterInfo(RequestOpenRidingStatsDebugGUIPacket.ID, RequestOpenRidingStatsDebugGUIPacket::decode, RequestOpenRidingStatsDebugGUIHandler))
return list
}
fun sendPacketToPlayer(player: ServerPlayer, packet: NetworkPacket<*>) {
Cobblemon.implementation.networkManager.sendPacketToPlayer(player, packet)
}
}
}
@@ -20,32 +20,45 @@ import net.minecraft.world.entity.ai.sensing.SensorType
object CobblemonSensors {
val sensors = mutableMapOf<String, SensorType<*>>()
@JvmField
val NPC_BATTLING = register("npc_battling", ::NPCBattlingSensor)
@JvmField
val BATTLING_POKEMON = register("battling_pokemon", ::BattlingPokemonSensor)
// val NPC_BATTLING = register("npc_battling", ::NPCBattlingSensor)
@JvmField
val POKEMON_DROWSY = register("pokemon_drowsy", ::DrowsySensor)
@JvmField
val POKEMON_ADULT = register("pokemon_adult_sensor", ::PokemonAdultSensor)
@JvmField
val POKEMON_DISTURBANCE = register("pokemon_disturbance_sensor", ::PokemonDisturbancesSensor)
@JvmField
val POKEMON_DEFEND_OWNER = register("pokemon_owner_under_attack", ::DefendOwnerSensor)
@JvmField
val NEARBY_GROWABLE_CROPS = register("nearby_growable_crops", ::PokemonGrowableCropSensor)
@JvmField
val NEARBY_BEE_HIVE = register("nearby_bee_hive", ::BeeHiveSensor)
@JvmField
val NEARBY_FLOWER = register("nearby_flower", ::FlowerSensor)
@JvmField
val NEARBY_SWEET_BERRY_BUSH = register("nearby_sweet_berry_bush", ::SweetBerryBushSensor)
@JvmField
val POKEMON_NEARBY_WANTED_ITEM = register("pokemon_nearby_wanted_item", ::PokemonItemSensor)
@JvmField
val NEARBY_SACC_LEAVES = register("nearby_sacc_leaves", ::SacLeavesSensor)
@JvmStatic
fun <E : Entity, U : Sensor<E>> register(id: String, supplier: Supplier<U>): SensorType<U> {
val sensor = SensorType(supplier)
sensors[id] = sensor
return sensor
}
}
}
@@ -23,43 +23,63 @@ import net.minecraft.resources.ResourceKey
* @since October 26th, 2022
*/
object CobblemonCriteria : PlatformRegistry<Registry<CriterionTrigger<*>>, ResourceKey<Registry<CriterionTrigger<*>>>, CriterionTrigger<*>>(){
@JvmField
val PICK_STARTER = this.create("pick_starter", SimpleCriterionTrigger(PokemonCriterion.CODEC))
@JvmField
val CATCH_POKEMON = this.create("catch_pokemon", SimpleCriterionTrigger(CaughtPokemonCriterion.CODEC))
@JvmField
val CATCH_SHINY_POKEMON = this.create("catch_shiny_pokemon", SimpleCriterionTrigger(CountableCriterion.CODEC))
@JvmField
val EGG_COLLECT = this.create("eggs_collected", SimpleCriterionTrigger(CountableCriterion.CODEC))
@JvmField
val EGG_HATCH = this.create("eggs_hatched", SimpleCriterionTrigger(CountableCriterion.CODEC))
@JvmField
val EVOLVE_POKEMON = this.create("pokemon_evolved", SimpleCriterionTrigger(EvolvePokemonCriterion.CODEC))
@JvmField
val WIN_BATTLE = this.create("battles_won", SimpleCriterionTrigger(BattleCountableCriterion.CODEC))
@JvmField
val DEFEAT_POKEMON = this.create("pokemon_defeated", SimpleCriterionTrigger(CountableCriterion.CODEC))
@JvmField
val COLLECT_ASPECT = this.create("aspects_collected", SimpleCriterionTrigger(AspectCriterion.CODEC))
@JvmField
val POKEMON_INTERACT = this.create("pokemon_interact", SimpleCriterionTrigger(PokemonInteractCriterion.CODEC))
@JvmField
val PARTY_CHECK = this.create("party", SimpleCriterionTrigger(PartyCheckCriterion.CODEC))
@JvmField
val LEVEL_UP = this.create("level_up", SimpleCriterionTrigger(LevelUpCriterion.CODEC))
@JvmField
val PASTURE_USE = this.create("pasture_use", SimpleCriterionTrigger(PokemonCriterion.CODEC))
@JvmField
val RESURRECT_POKEMON = this.create("resurrect_pokemon", SimpleCriterionTrigger(PokemonCriterion.CODEC))
@JvmField
val TRADE_POKEMON = this.create("trade_pokemon", SimpleCriterionTrigger(TradePokemonCriterion.CODEC))
@JvmField
val CAST_POKE_ROD = this.create("cast_poke_rod", SimpleCriterionTrigger(CastPokeRodCriterionCondition.CODEC))
@JvmField
val REEL_IN_POKEMON = this.create("reel_in_pokemon", SimpleCriterionTrigger(ReelInPokemonCriterionCondition.CODEC))
// Advancement criteria for [grow_tumblestone.json]
@JvmField
val PLANT_TUMBLESTONE = this.create("plant_tumblestone", SimpleCriterionTrigger(PlantTumblestoneCriterion.CODEC))
val RIDING_STAT_BOOST = this.create("riding_stat_boost", SimpleCriterionTrigger(RidingStatBoostCriterion.CODEC))
override val registry = BuiltInRegistries.TRIGGER_TYPES
override val resourceKey = Registries.TRIGGER_TYPE
}
}
@@ -32,6 +32,6 @@ class CastPokeRodCriterionCondition(
}
override fun matches(player: ServerPlayer, context: CastPokeRodContext): Boolean {
return (context.baitId == this.baitId.asIdentifierDefaultingNamespace() || this.baitId.equals("empty_bait"))
return (context.baitId == this.baitId.asIdentifierDefaultingNamespace() || this.baitId == "empty_bait")
}
}
@@ -21,23 +21,25 @@ import java.util.Optional
* @author Hiroku
* @since November 4th, 2022
*/
open class CountablePokemonTypeContext(times: Int, var species: String) : CountableContext(times)
open class CountablePokemonTypeContext(times: Int, var type: String/*, var species: String*/) : CountableContext(times)
class CaughtPokemonCriterion(
playerCtx: Optional<ContextAwarePredicate>,
val species: String,
val type : String,
//val species: String,
count: Int
): CountableCriterion<CountablePokemonTypeContext>(playerCtx, count) {
companion object {
val CODEC: Codec<CaughtPokemonCriterion> = RecordCodecBuilder.create { it.group(
EntityPredicate.ADVANCEMENT_CODEC.optionalFieldOf("player").forGetter(CaughtPokemonCriterion::playerCtx),
Codec.STRING.optionalFieldOf("species", "any").forGetter(CaughtPokemonCriterion::species),
Codec.STRING.optionalFieldOf("type", "any").forGetter(CaughtPokemonCriterion::type),
//Codec.STRING.optionalFieldOf("species", "any").forGetter(CaughtPokemonCriterion::species),
Codec.INT.optionalFieldOf("count", 0).forGetter(CaughtPokemonCriterion::count)
).apply(it, ::CaughtPokemonCriterion) }
}
override fun matches(player: ServerPlayer, context: CountablePokemonTypeContext): Boolean {
return super.matches(player, context) && (context.species == species || species == "any")
return super.matches(player, context) && (context.type == type || type == "any")// && (context.species == species || species == "any")
}
}
@@ -28,7 +28,7 @@ class LevelUpCriterion(
val CODEC: Codec<LevelUpCriterion> = RecordCodecBuilder.create { it.group(
EntityPredicate.ADVANCEMENT_CODEC.optionalFieldOf("player").forGetter(LevelUpCriterion::playerCtx),
Codec.INT.optionalFieldOf("level", 0).forGetter(LevelUpCriterion::level),
Codec.BOOL.optionalFieldOf("evolved", true).forGetter(LevelUpCriterion::evolved)
Codec.BOOL.optionalFieldOf("has_evolved", true).forGetter(LevelUpCriterion::evolved)
).apply(it, ::LevelUpCriterion) }
}
@@ -35,6 +35,6 @@ class ReelInPokemonCriterionCondition(
override fun matches(player: ServerPlayer, context: ReelInPokemonContext): Boolean {
return (context.species == this.species.asIdentifierDefaultingNamespace() || this.species == "any")
&& (context.baitId == this.baitId.asIdentifierDefaultingNamespace() || this.baitId == "any")
&& (context.baitId == this.baitId.asIdentifierDefaultingNamespace() || this.baitId == "any" || this.baitId == "empty_bait")
}
}
@@ -0,0 +1,54 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.advancement.criterion
import com.cobblemon.mod.common.api.riding.RidingStyle
import com.cobblemon.mod.common.api.riding.stats.RidingStat
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import com.mojang.serialization.Codec
import com.mojang.serialization.codecs.RecordCodecBuilder
import net.minecraft.advancements.critereon.ContextAwarePredicate
import net.minecraft.advancements.critereon.EntityPredicate
import net.minecraft.server.level.ServerPlayer
import java.util.Optional
class RidingStatBoostContext(val pokemon: PokemonEntity)
class RidingStatBoostCriterion(
playerCtx: Optional<ContextAwarePredicate>,
val rideStat: String,
val statValue : Double,
val isMax : Boolean
) : SimpleCriterionCondition<RidingStatBoostContext>(playerCtx) {
companion object {
val CODEC: Codec<RidingStatBoostCriterion> = RecordCodecBuilder.create { it.group(
EntityPredicate.ADVANCEMENT_CODEC.optionalFieldOf("player").forGetter { it.playerCtx },
Codec.STRING.optionalFieldOf("ride_stat", "any").forGetter { it.rideStat },
Codec.DOUBLE.optionalFieldOf("stat_value", 0.0).forGetter { it.statValue },
Codec.BOOL.optionalFieldOf("is_max", false).forGetter { it.isMax }
).apply(it, ::RidingStatBoostCriterion) }
}
override fun matches(player: ServerPlayer, context: RidingStatBoostContext) : Boolean {
RidingStyle.entries.forEach { ridingStyle ->
RidingStat.entries.forEach { rideStat ->
if (rideStat.name.equals(this.rideStat, true) || this.rideStat == "any") {
val max = context.pokemon.pokemon.getMaxRideBoost(rideStat).toDouble()
val min = context.pokemon.pokemon.getBaseRideStat(rideStat).toDouble()
val value = context.pokemon.getRideStat(rideStat, ridingStyle, min, max)
if ((value >= this.statValue && this.statValue > 0.0) || value == max || !context.pokemon.pokemon.canAddRideBoost(rideStat)) {
return true
}
}
}
}
return false
}
}
@@ -70,16 +70,23 @@ object Abilities : DataRegistry {
AbilityRegistrySyncPacket(all()).sendToPlayer(player)
}
@JvmStatic
fun register(ability: AbilityTemplate): AbilityTemplate {
this.abilityMap[ability.name.lowercase()] = ability
return ability
}
@JvmStatic
fun all() = this.abilityMap.values.toList()
@JvmStatic
fun first() = this.abilityMap.values.first()
@JvmStatic
fun get(name: String) = abilityMap[name.lowercase()]
@JvmStatic
fun getOrDummy(name: String) = get(name) ?: DUMMY
@JvmStatic
fun getOrException(name: String) = get(name) ?: throw IllegalArgumentException("Unable to find ability of name: $name")
@JvmStatic
fun count() = this.abilityMap.size
internal fun receiveSyncPacket(abilities: Collection<AbilityTemplate>) {
@@ -11,8 +11,7 @@ package com.cobblemon.mod.common.api.ai.config.task
import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
import com.cobblemon.mod.common.api.ai.asVariables
import com.cobblemon.mod.common.api.ai.config.task.SharedEntityVariables.SEE_DISTANCE
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMostSpecificMoLangValue
import com.cobblemon.mod.common.util.withQueryValue
import com.cobblemon.mod.common.util.resolveEntityTypes
import net.minecraft.world.entity.LivingEntity
import net.minecraft.world.entity.ai.behavior.BehaviorControl
import net.minecraft.world.entity.ai.behavior.SetEntityLookTarget
@@ -22,13 +21,16 @@ import net.minecraft.world.entity.ai.sensing.SensorType
class LookAtEntitiesTaskConfig : SingleTaskConfig {
companion object {
const val LOOK_AT_ENTITIES = "look_at_entities"
const val LOOK_AT_ENTITY_TYPES = "look_at_entity_types"
}
val condition = booleanVariable(SharedEntityVariables.LOOKING_CATEGORY, LOOK_AT_ENTITIES, true).asExpressible()
val maxDistance = numberVariable(SharedEntityVariables.LOOKING_CATEGORY, SEE_DISTANCE, 15).asExpressible()
val entityTypes = stringVariable(SharedEntityVariables.LOOKING_CATEGORY, LOOK_AT_ENTITY_TYPES, "").asExpressible()
override fun getVariables(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext) = listOf(
condition,
entityTypes,
maxDistance
).asVariables()
@@ -39,6 +41,18 @@ class LookAtEntitiesTaskConfig : SingleTaskConfig {
if (!condition.resolveBoolean(behaviourConfigurationContext.runtime)) return null
behaviourConfigurationContext.addMemories(MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES, MemoryModuleType.LOOK_TARGET)
behaviourConfigurationContext.addSensors(SensorType.NEAREST_LIVING_ENTITIES)
return SetEntityLookTarget.create(maxDistance.resolveFloat(behaviourConfigurationContext.runtime))
val lookDistance = maxDistance.resolveFloat(behaviourConfigurationContext.runtime)
val lookAtTypesText = entityTypes.resolveString(behaviourConfigurationContext.runtime)
if (lookAtTypesText.isBlank()) {
return SetEntityLookTarget.create(lookDistance)
}
val lookAtTypes = resolveEntityTypes(entity.registryAccess(), lookAtTypesText)
return if (lookAtTypes.isNotEmpty()) {
SetEntityLookTarget.create({ lookAtTypes.contains(it.type) }, lookDistance)
} else {
null
}
}
}
@@ -19,7 +19,7 @@ import net.minecraft.world.entity.ai.memory.MemoryModuleType
class MeleeAttackTaskConfig : SingleTaskConfig {
val condition = booleanVariable(SharedEntityVariables.ATTACKING_CATEGORY, "attacks_melee", true).asExpressible()
val range = numberVariable(SharedEntityVariables.ATTACKING_CATEGORY, "melee_range", 1.5F).asExpressible()
val range = numberVariable(SharedEntityVariables.ATTACKING_CATEGORY, "melee_range", 0.75F).asExpressible()
val cooldownTicks = numberVariable(SharedEntityVariables.ATTACKING_CATEGORY, "melee_cooldown", 20).asExpressible()
override fun getVariables(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext) = listOf(
@@ -85,6 +85,7 @@ object Berries : JsonDataRegistry<Berry> {
BerryRegistrySyncPacket(this.all()).sendToPlayer(player)
}
@JvmStatic
fun all() = this.berries.values.toList()
/**
@@ -93,6 +94,7 @@ object Berries : JsonDataRegistry<Berry> {
* @param identifier The identifier of the berry.
* @return The [Berry] if loaded otherwise null.
*/
@JvmStatic
fun getByIdentifier(identifier: ResourceLocation): Berry? = this.berries[identifier]
/**
@@ -101,6 +103,7 @@ object Berries : JsonDataRegistry<Berry> {
* @param name The path of the identifier of the berry under the [Cobblemon.MODID] namespace.
* @return The [Berry] if loaded otherwise null.
*/
@JvmStatic
fun getByName(name: String): Berry? = this.getByIdentifier(cobblemonResource(name))
}
@@ -9,8 +9,13 @@
package com.cobblemon.mod.common.api.cooking
import com.cobblemon.mod.common.api.riding.stats.RidingStat
import com.cobblemon.mod.common.util.math.geometry.toDegrees
import com.cobblemon.mod.common.util.math.geometry.toRadians
import net.minecraft.util.FastColor
import net.minecraft.world.item.ItemStack
import kotlin.math.atan2
import kotlin.math.cos
import kotlin.math.sin
private val colourMap = mapOf(
Flavour.SPICY to 0xFEB37D,
@@ -50,41 +55,111 @@ fun getColourMixFromFlavours(dominantFlavours: List<Flavour>, forBubbles: Boolea
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
)
return getColourMixFromColors(colors)
}
fun getColourMixFromRideStatBoosts(dominantBoosts: Iterable<RidingStat>, forBubbles: Boolean = false): Int? {
return getColourMixFromFlavours(dominantBoosts.map { it.flavour }, forBubbles)
}
// Mixing RGB colors directly often gives poor results
// Converting them to HSL and averaging hues circularly produces more natural blends
fun getColourMixFromColors(colors: List<Int>): Int? {
if (colors.isEmpty()) return null
if (colors.size == 1) return colors[0]
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
val hslColors = colors.map {
val red = FastColor.ARGB32.red(it)
val green = FastColor.ARGB32.green(it)
val blue = FastColor.ARGB32.blue(it)
rgbToHsl(red, green, blue)
}
return FastColor.ARGB32.color(
alphaSum / colors.size,
redSum / colors.size,
greenSum / colors.size,
blueSum / colors.size
val hues = hslColors.map { it.h.toDouble() }
val huesAverage = hueAverage(hues).toFloat()
val saturations = hslColors.map { it.s }
val saturationsAverage = average(saturations)
val lightness = hslColors.map { it.l }
val lightnessAverage = average(lightness)
val rgbColor = hslToRgb(huesAverage, saturationsAverage, lightnessAverage)
return FastColor.ARGB32.color(rgbColor.r, rgbColor.g, rgbColor.b)
}
// Based on https://iter.ca/post/hue-avg
fun hueAverage(hues: List<Double>): Float {
val points = hues.map { hue ->
val rad = hue.toRadians()
Pair(cos(rad), sin(rad))
}
val avgX = points.sumOf { it.first.toDouble() } / points.size
val avgY = points.sumOf { it.second.toDouble() } / points.size
var degrees = atan2(avgY, avgX).toDegrees()
if (degrees < 0) {
degrees += 360f
} else if (degrees > 360) {
degrees -= 360f
}
return degrees
}
fun average(values: List<Float>): Float {
if (values.isEmpty()) return 0f
return values.sum() / values.size
}
data class HSL(val h: Float, val s: Float, val l: Float)
fun rgbToHsl(r: Int, g: Int, b: Int): HSL {
val rf = r / 255f
val gf = g / 255f
val bf = b / 255f
val max = maxOf(rf, gf, bf)
val min = minOf(rf, gf, bf)
val delta = max - min
var h = 0f
val l = (max + min) / 2f
val s = if (delta == 0f) 0f else delta / (1f - kotlin.math.abs(2f * l - 1f))
if (delta != 0f) {
h = when (max) {
rf -> ((gf - bf) / delta) % 6f
gf -> ((bf - rf) / delta) + 2f
else -> ((rf - gf) / delta) + 4f
}
h *= 60f
if (h < 0) h += 360f
}
return HSL(h, s, l)
}
data class RGB(val r: Int, val g: Int, val b: Int)
fun hslToRgb(h: Float, s: Float, l: Float): RGB {
val c = (1f - kotlin.math.abs(2f * l - 1f)) * s
val x = c * (1f - kotlin.math.abs((h / 60f) % 2f - 1f))
val m = l - c / 2f
val (rf, gf, bf) = when {
h < 60f -> Triple(c, x, 0f)
h < 120f -> Triple(x, c, 0f)
h < 180f -> Triple(0f, c, x)
h < 240f -> Triple(0f, x, c)
h < 300f -> Triple(x, 0f, c)
else -> Triple(c, 0f, x)
}
return RGB(
((rf + m) * 255).toInt().coerceIn(0, 255),
((gf + m) * 255).toInt().coerceIn(0, 255),
((bf + m) * 255).toInt().coerceIn(0, 255)
)
}
@@ -28,12 +28,14 @@ import net.minecraft.server.level.ServerPlayer
object DialogueManager {
val activeDialogues = mutableMapOf<UUID, ActiveDialogue>()
@JvmStatic
fun startDialogue(playerEntity: ServerPlayer, dialogue: Dialogue): ActiveDialogue {
val activeDialogue = ActiveDialogue(playerEntity, dialogue)
startDialogue(activeDialogue)
return activeDialogue
}
@JvmStatic
fun startDialogue(playerEntity: ServerPlayer, npcEntity: NPCEntity, dialogue: Dialogue): ActiveDialogue {
val activeDialogue = ActiveDialogue(playerEntity, dialogue)
activeDialogue.runtime.withNPCValue("npc", npcEntity)
@@ -42,6 +44,7 @@ object DialogueManager {
return activeDialogue
}
@JvmStatic
fun startDialogue(activeDialogue: ActiveDialogue) {
activeDialogue.initialize()
if (!activeDialogue.completion.isDone) {
@@ -49,6 +52,7 @@ object DialogueManager {
}
}
@JvmStatic
fun stopDialogue(playerEntity: ServerPlayer) {
val activeDialogue = playerEntity.activeDialogue ?: return
DialogueClosedPacket(activeDialogue.dialogueId).sendToPlayer(playerEntity)
@@ -10,14 +10,12 @@ package com.cobblemon.mod.common.api.drop
import com.cobblemon.mod.common.api.events.CobblemonEvents.LOOT_DROPPED
import com.cobblemon.mod.common.api.events.drops.LootDroppedEvent
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import com.cobblemon.mod.common.pokemon.Pokemon
import kotlin.random.Random
import net.minecraft.network.RegistryFriendlyByteBuf
import net.minecraft.server.level.ServerLevel
import net.minecraft.server.level.ServerPlayer
import net.minecraft.world.entity.LivingEntity
import net.minecraft.world.item.ItemStack
import net.minecraft.world.phys.Vec3
/**
@@ -95,6 +93,16 @@ class DropTable {
pokemon: Pokemon? = null,
) {
val drops = getDrops(amount, pokemon).toMutableList()
postLootDroppedEvent(drops, entity, world, pos, player)
}
fun postLootDroppedEvent(
drops: MutableList<DropEntry>,
entity: LivingEntity?,
world: ServerLevel,
pos: Vec3,
player: ServerPlayer?,
) {
LOOT_DROPPED.postThen(
event = LootDroppedEvent(this, player, entity, drops),
ifSucceeded = { it.drops.forEach { it.drop(entity, world, pos, player) } }
@@ -110,4 +118,4 @@ class DropTable {
val entries = buffer.readInt()
repeat(entries) { this.entries.add(ItemDropEntry().decode(buffer)) }
}
}
}
@@ -20,6 +20,7 @@ import com.cobblemon.mod.common.api.events.berry.BerryHarvestEvent
import com.cobblemon.mod.common.api.events.berry.BerryMutationOfferEvent
import com.cobblemon.mod.common.api.events.berry.BerryMutationResultEvent
import com.cobblemon.mod.common.api.events.berry.BerryYieldCalculationEvent
import com.cobblemon.mod.common.api.events.cooking.PokeSnackSpawnPokemonEvent
import com.cobblemon.mod.common.api.events.drops.LootDroppedEvent
import com.cobblemon.mod.common.api.events.entity.*
import com.cobblemon.mod.common.api.events.farming.ApricornHarvestEvent
@@ -327,6 +328,12 @@ object CobblemonEvents {
@JvmField
val BOBBER_SPAWN_POKEMON_POST = EventObservable<BobberSpawnPokemonEvent.Post>()
@JvmField
val POKE_SNACK_SPAWN_POKEMON_PRE = CancelableObservable<PokeSnackSpawnPokemonEvent.Pre>()
@JvmField
val POKE_SNACK_SPAWN_POKEMON_POST = EventObservable<PokeSnackSpawnPokemonEvent.Post>()
@JvmField
val BAIT_EFFECT_REGISTRATION = EventObservable<BaitEffectFunctionRegistryEvent>()
@@ -0,0 +1,38 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.events.cooking
import com.bedrockk.molang.runtime.value.MoValue
import com.cobblemon.mod.common.api.events.Cancelable
import com.cobblemon.mod.common.api.molang.MoLangFunctions.moLangFunctionMap
import com.cobblemon.mod.common.api.spawning.detail.SpawnAction
import com.cobblemon.mod.common.block.entity.PokeSnackBlockEntity
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
interface PokeSnackSpawnPokemonEvent {
data class Pre(
val pokeSnackBlockEntity: PokeSnackBlockEntity,
val spawnAction: SpawnAction<*>,
) : Cancelable(), PokeSnackSpawnPokemonEvent {
val context = mapOf<String, MoValue>()
val functions = moLangFunctionMap(
cancelFunc
)
}
data class Post(
val pokeSnackBlockEntity: PokeSnackBlockEntity,
val spawnAction: SpawnAction<*>,
val pokemonEntity: PokemonEntity,
) : PokeSnackSpawnPokemonEvent {
val context = mapOf<String, MoValue>()
}
}
@@ -57,6 +57,7 @@ object PokeRods : JsonDataRegistry<PokeRod> {
* Gets a Pokerod from registry name.
* @return the pokerod object if found otherwise null.
*/
@JvmStatic
fun getPokeRod(name : ResourceLocation): PokeRod? = rods[name]
}
@@ -68,6 +68,7 @@ class SpawnBait(
val TYPING = cobblemonResource("typing")
val EGG_GROUP = cobblemonResource("egg_group")
val SHINY_REROLL = cobblemonResource("shiny_reroll")
val DROPS_REROLL = cobblemonResource("drops_reroll")
val HIDDEN_ABILITY_CHANCE = cobblemonResource("ha_chance")
val POKEMON_CHANCE = cobblemonResource("pokemon_chance")
val FRIENDSHIP = cobblemonResource("friendship")
@@ -85,6 +86,7 @@ class SpawnBait(
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(DROPS_REROLL) { entity, effect -> FishingSpawnCause.saveDropsReroll(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) }
@@ -53,20 +53,24 @@ object SpawnBaitEffects : JsonDataRegistry<SpawnBait> {
}
}
@JvmStatic
fun getEffectsFromRodItemStack(stack: ItemStack): List<SpawnBait.Effect> {
return getEffectsFromItemStack(stack.components.get(CobblemonItemComponents.BAIT)?.stack ?: ItemStack.EMPTY)
}
@JvmStatic
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)
}
@JvmStatic
fun getBaitIdentifiersFromItem(holder: Holder<Item>): List<ResourceLocation> {
return effectsMap.entries.filter { it.value.item.fits(holder) }.map { it.key }
}
@JvmStatic
fun getBaitFromItemStack(holder: Holder<Item>): List<SpawnBait> {
return effectsMap.values.filter { it.item.fits(holder) }
}
@@ -75,6 +79,7 @@ object SpawnBaitEffects : JsonDataRegistry<SpawnBait> {
return getBaitFromItemStack(holder).flatMap { it.effects }
}
@JvmStatic
fun getFromIdentifier(identifier: ResourceLocation): SpawnBait? {
// Check normal spawn bait registry
effectsMap[identifier]?.let { return it }
@@ -98,6 +103,7 @@ object SpawnBaitEffects : JsonDataRegistry<SpawnBait> {
}
// if it has bait effects and is not listed as a seasoning then it is a bait
@JvmStatic
fun isFishingBait(stack: ItemStack): Boolean {
val holder = stack.itemHolder
return effectsMap.values.any { it.item.fits(holder) }
@@ -11,6 +11,7 @@ package com.cobblemon.mod.common.api.fishing
import kotlin.math.ceil
object SpawnBaitUtils {
@JvmStatic
fun mergeEffects(effects: List<SpawnBait.Effect>): List<SpawnBait.Effect> {
val grouped = effects.groupBy { Pair(it.type, it.subcategory) }
@@ -69,6 +69,7 @@ object Fossils: JsonDataRegistry<Fossil> {
/**
* Gets all loaded [Fossil]s.
*/
@JvmStatic
fun all() = this.fossils.values.toList()
/**
@@ -76,6 +77,7 @@ object Fossils: JsonDataRegistry<Fossil> {
* @param identifier The identifier of the fossil.
* @return The [Fossil] if loaded, otherwise null.
*/
@JvmStatic
fun getByIdentifier(identifier: ResourceLocation): Fossil? = this.fossils[identifier]
/**
@@ -83,6 +85,7 @@ object Fossils: JsonDataRegistry<Fossil> {
* @param fossilStacks The fossil [ItemStack]'s.
* @return The [Fossil] if found, otherwise null.
*/
@JvmStatic
fun getFossilByItemStacks(fossilStacks: List<ItemStack>): Fossil? {
return this.all().firstOrNull { it.matchesIngredients(fossilStacks) }
}
@@ -92,6 +95,7 @@ object Fossils: JsonDataRegistry<Fossil> {
* @param fossilStacks The fossil [ItemStack]'s.
* @return The [Fossil] if found to be a superset, otherwise null.
*/
@JvmStatic
fun getSubFossilByItemStacks(fossilStacks: List<ItemStack>): Fossil? {
return this.all().firstOrNull { it.matchesIngredientsSubSet(fossilStacks) }
}
@@ -100,6 +104,7 @@ object Fossils: JsonDataRegistry<Fossil> {
* @param itemStack The ingredient [ItemStack].
* @return true if it's a fossil ingredient, otherwise false.
*/
@JvmStatic
fun isFossilIngredient(itemStack: ItemStack): Boolean {
return this.all().any { it.isIngredient(itemStack) }
}
@@ -57,6 +57,7 @@ object NaturalMaterials : JsonDataRegistry<List<NaturalMaterial>>{
}
}
@JvmStatic
fun isNaturalMaterial(item: ItemStack): Boolean {
val itemId = BuiltInRegistries.ITEM.getKey(item.item)
return itemId in itemMap.keys || tagMap.keys.any {
@@ -64,6 +65,7 @@ object NaturalMaterials : JsonDataRegistry<List<NaturalMaterial>>{
}
}
@JvmStatic
fun getContent(item: ItemStack): Int? {
val itemId = BuiltInRegistries.ITEM.getKey(item.item)
if (itemId in itemMap.keys) {
@@ -76,6 +78,7 @@ object NaturalMaterials : JsonDataRegistry<List<NaturalMaterial>>{
return null
}
@JvmStatic
fun getReturnItem(item: ItemStack): ResourceLocation? {
val itemId = BuiltInRegistries.ITEM.getKey(item.item)
if (itemId in itemMap.keys) {
@@ -87,4 +90,4 @@ object NaturalMaterials : JsonDataRegistry<List<NaturalMaterial>>{
}
return null
}
}
}
@@ -56,7 +56,9 @@ object Marks: JsonDataRegistry<Mark> {
/**
* Gets all loaded [Mark]s.
*/
@JvmStatic
fun all() = this.marks.values.toList()
@JvmStatic
fun identifiers(): Collection<String> = marks.keys.toSet().map { it.toString() }
/**
@@ -64,5 +66,6 @@ object Marks: JsonDataRegistry<Mark> {
* @param identifier The identifier of the mark.
* @return The [Mark] if loaded, otherwise null.
*/
@JvmStatic
fun getByIdentifier(identifier: ResourceLocation): Mark? = this.marks[identifier]
}
}
@@ -12,6 +12,7 @@ import com.bedrockk.molang.runtime.MoLangEnvironment
import com.bedrockk.molang.runtime.MoLangRuntime
import com.bedrockk.molang.runtime.MoParams
import com.bedrockk.molang.runtime.struct.ArrayStruct
import com.bedrockk.molang.runtime.struct.ContextStruct
import com.bedrockk.molang.runtime.struct.QueryStruct
import com.bedrockk.molang.runtime.struct.VariableStruct
import com.bedrockk.molang.runtime.value.DoubleValue
@@ -179,6 +180,18 @@ object MoLangFunctions {
struct.map.clear()
DoubleValue.ONE
},
"get_variable" to java.util.function.Function { params ->
val struct = params.get<VariableStruct>(0)
val variable = params.getString(1)
return@Function struct.map[variable] ?: DoubleValue.ZERO
},
"set_variable" to java.util.function.Function { params ->
val struct = params.get<VariableStruct>(0)
val variable = params.getString(1)
val value = params.get<MoValue>(2)
struct.map[variable] = value
return@Function value
},
"set_query" to java.util.function.Function { params ->
val variable = params.getString(0)
val value = params.get<MoValue>(1)
@@ -296,8 +309,12 @@ object MoLangFunctions {
val runtime = MoLangRuntime()
runtime.environment.query = params.environment.query
runtime.environment.variable = params.environment.variable
runtime.environment.context = params.environment.context
val args = params.params.subList(1, params.params.size)
runtime.environment.context = ContextStruct(
params.environment.context.map + args.mapIndexed { index, value -> "arg_${index + 1}" to value }.toMap()
)
val script = params.getString(0).asIdentifierDefaultingNamespace()
// store the args in the
CobblemonScripts.run(script, runtime) ?: DoubleValue.ZERO
},
"run_molang" to java.util.function.Function { params ->
@@ -349,7 +366,8 @@ object MoLangFunctions {
val pickupPriority = params.getIntOrNull(1) ?: 0
val pickupItem = ObtainableItem(item = item, pickupPriority = pickupPriority)
return@Function pickupItem.struct
}
},
"file" to java.util.function.Function { MoLangLoadedFilesCache.struct }
)
val biomeFunctions = mutableListOf<(Holder<Biome>) -> HashMap<String, java.util.function.Function<MoParams, Any>>>()
val worldFunctions = mutableListOf<(Holder<Level>) -> HashMap<String, java.util.function.Function<MoParams, Any>>>(
@@ -590,10 +608,10 @@ object MoLangFunctions {
}
if (player is ServerPlayer) {
map.put("seen_credits") { _ ->
DoubleValue( DoubleValue(player.seenCredits) )
DoubleValue(player.seenCredits)
}
map.put("is_in_dialogue") { _ ->
DoubleValue( DoubleValue(player.isInDialogue) )
DoubleValue(player.isInDialogue)
}
map.put("active_dialogue") { _ ->
if (player.isInDialogue) {
@@ -1886,12 +1904,43 @@ 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("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("is_drifting") { DoubleValue(pokemonEntity.isUsingAltPose(cobblemonResource("drifting"))) }
map.put("is_powered_drifting") { DoubleValue(pokemonEntity.isUsingAltPose(cobblemonResource("powered_drifting"))) }
map.put("in_air") { DoubleValue(pokemonEntity.isUsingAltPose(cobblemonResource("in_air"))) }
map.put("get_riding_state") { params ->
val name = params.getStringOrNull(0)
pokemonEntity.ifRidingAvailableSupply(DoubleValue.ZERO) { behaviour, settings, state ->
val moValue = behaviour.asMoLangValue(settings, state, pokemonEntity)
return@ifRidingAvailableSupply moValue.functions[name]?.apply(MoParams.EMPTY) as? MoValue ?: moValue
}
}
map.put("is_gliding") {
pokemonEntity.ifRidingAvailableSupply(DoubleValue.ZERO) { behaviour, settings, state ->
val moValue = behaviour.asMoLangValue(settings, state, pokemonEntity)
return@ifRidingAvailableSupply moValue.functions.get("gliding")?.apply(MoParams.EMPTY) as? MoValue ?: DoubleValue.ZERO
}
}
map.put("is_sprinting") {
pokemonEntity.ifRidingAvailableSupply(DoubleValue.ZERO) { behaviour, settings, state ->
val moValue = behaviour.asMoLangValue(settings, state, pokemonEntity)
return@ifRidingAvailableSupply moValue.functions.get("sprinting")?.apply(MoParams.EMPTY) as? MoValue ?: DoubleValue.ZERO
}
}
map.put("is_drifting") {
pokemonEntity.ifRidingAvailableSupply(DoubleValue.ZERO) { behaviour, settings, state ->
val moValue = behaviour.asMoLangValue(settings, state, pokemonEntity)
return@ifRidingAvailableSupply moValue.functions.get("drifting")?.apply(MoParams.EMPTY) as? MoValue ?: DoubleValue.ZERO
}
}
map.put("is_powered_drifting") {
pokemonEntity.ifRidingAvailableSupply(DoubleValue.ZERO) { behaviour, settings, state ->
val moValue = behaviour.asMoLangValue(settings, state, pokemonEntity)
return@ifRidingAvailableSupply moValue.functions.get("powered_drifting")?.apply(MoParams.EMPTY) as? MoValue ?: DoubleValue.ZERO
}
}
map.put("in_air") {
pokemonEntity.ifRidingAvailableSupply(DoubleValue.ZERO) { behaviour, settings, state ->
val moValue = behaviour.asMoLangValue(settings, state, pokemonEntity)
return@ifRidingAvailableSupply moValue.functions.get("in_air")?.apply(MoParams.EMPTY) as? MoValue ?: DoubleValue.ZERO
}
}
map.put("is_wild") { DoubleValue(pokemonEntity.ownerUUID == null) }
map.put("is_in_party") { DoubleValue(pokemonEntity.pokemon.storeCoordinates.get()?.store is PartyStore) }
map.put("is_ridden") { DoubleValue(pokemonEntity.hasControllingPassenger()) }
@@ -2469,6 +2518,17 @@ object MoLangFunctions {
return value
}
fun Vec3.asMoLangValue(): ObjectValue<Vec3> {
val value = ObjectValue(
obj = this
)
value.addFunction("x") { this.x }
value.addFunction("y") { this.y }
value.addFunction("z") { this.z }
return value
}
/**
* Different functions exist depending on the entity type, this tries to make the struct that's most specific to the type.
*/
@@ -2655,5 +2715,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) })
@@ -0,0 +1,114 @@
/*
* 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.molang
import com.bedrockk.molang.runtime.struct.QueryStruct
import com.bedrockk.molang.runtime.struct.VariableStruct
import com.bedrockk.molang.runtime.value.DoubleValue
import com.bedrockk.molang.runtime.value.MoValue
import com.cobblemon.mod.common.Cobblemon
import com.google.gson.GsonBuilder
import com.google.gson.JsonElement
import java.nio.file.Path
import java.util.concurrent.ConcurrentHashMap
import net.minecraft.server.MinecraftServer
import net.minecraft.world.level.storage.LevelResource
/**
* A cache for loaded MoLang files to avoid redundant file I/O operations.
* Provides functions to load, save, check existence, and clear cached files.
*
* Only files with /molang/ in their path and a .json extension within the config
* or data folders can be accessed.
*
* @author Hiroku
* @since November 1st, 2025
*/
object MoLangLoadedFilesCache {
private val gson = GsonBuilder().setPrettyPrinting().create()
val loadedFiles = ConcurrentHashMap<String, VariableStruct>()
/** Essentially the server root or world root for singleplayer. */
lateinit var baseFolder: Path
private lateinit var configFolder: Path
private lateinit var dataFolder: Path
fun initialize(server: MinecraftServer) {
baseFolder = server.getWorldPath(LevelResource.ROOT)
configFolder = baseFolder.resolve("config").normalize().toAbsolutePath()
dataFolder = baseFolder.resolve("data").normalize().toAbsolutePath()
}
val struct = QueryStruct(hashMapOf())
.addFunction("load") { params ->
val fileName = params.params[0].asString()
return@addFunction load(fileName)
}
.addFunction("save") { params ->
val fileName = params.params[0].asString()
val data = params.params[1] as VariableStruct
save(fileName, data)
return@addFunction DoubleValue.ONE
}
.addFunction("exists") { params ->
val fileName = params.params[0].asString()
val exists = exists(fileName)
return@addFunction if (exists) DoubleValue.ONE else DoubleValue.ZERO
}
.addFunction("clear") { params ->
val fileName = params.params[0].asString()
clear(fileName)
return@addFunction DoubleValue.ONE
}
private fun validatePath(fileName: String): Path? {
val filePath = baseFolder.resolve(fileName).normalize().toAbsolutePath()
if (!filePath.startsWith(configFolder) && !filePath.startsWith(dataFolder)) {
Cobblemon.LOGGER.error("MoLang attempted to access file outside of config or data folder: $fileName")
return null
} else if ("/molang/" !in fileName) {
Cobblemon.LOGGER.error("MoLang attempted to access file outside of a 'molang' subfolder: $fileName")
return null
} else if (!fileName.endsWith(".json")) {
Cobblemon.LOGGER.error("MoLang attempted to access file without a .json extension: $fileName")
return null
}
return filePath
}
fun exists(fileName: String): Boolean {
val filePath = validatePath(fileName) ?: return false
return filePath.toFile().exists()
}
fun clear(fileName: String) {
loadedFiles.remove(fileName)
}
fun load(fileName: String): VariableStruct {
return loadedFiles.getOrPut(fileName) {
val filePath = validatePath(fileName) ?: return VariableStruct()
val file = filePath.toFile()
if (!file.exists()) {
return VariableStruct()
}
val jsonElement = gson.fromJson(file.readText(), JsonElement::class.java)
MoValue.of(jsonElement) as VariableStruct
}
}
fun save(fileName: String, data: VariableStruct) {
loadedFiles[fileName] = data
val filePath = validatePath(fileName) ?: return
val file = filePath.toFile()
file.parentFile?.mkdirs()
val jsonElement = MoValue.writeToJson(data)
file.writeText(gson.toJson(jsonElement))
}
}
@@ -9,8 +9,8 @@
package com.cobblemon.mod.common.api.molang
import com.bedrockk.molang.runtime.MoLangRuntime
import com.bedrockk.molang.runtime.value.DoubleValue
import com.bedrockk.molang.runtime.value.MoValue
import com.bedrockk.molang.runtime.value.StringValue
import com.cobblemon.mod.common.api.scripting.CobblemonScripts
import net.minecraft.resources.ResourceLocation
@@ -23,11 +23,11 @@ import net.minecraft.resources.ResourceLocation
*/
class ReferenceExpression(val identifier: ResourceLocation) : ExpressionLike {
override fun resolve(runtime: MoLangRuntime, context: Map<String, MoValue>): MoValue {
return getScript()?.resolve(runtime, context) ?: DoubleValue.ZERO
return getScript()?.resolve(runtime, context) ?: StringValue(identifier.toString())
}
override fun toString(): String {
return getScript()?.getString() ?: "0"
return getScript()?.getString() ?: identifier.toString()
}
fun getScript() = CobblemonScripts.scripts[identifier]
@@ -33,6 +33,7 @@ object HiddenPowerUtil {
ElementalTypes.DARK
)
@JvmStatic
fun getHiddenPowerType(pokemon: Pokemon?): ElementalType {
if (pokemon == null) {
return ElementalTypes.NORMAL
@@ -106,12 +106,19 @@ object Moves : DataRegistry {
MovesRegistrySyncPacket(all()).sendToPlayer(player)
}
@JvmStatic
fun getByName(name: String) = allMoves[name.lowercase()]
@JvmStatic
fun getByNumericalId(id: Int) = idMapping[id]
@JvmStatic
fun getByNameOrDummy(name: String) = allMoves[name.lowercase()] ?: MoveTemplate.dummy(name.lowercase())
@JvmStatic
fun getExceptional() = getByName("tackle") ?: allMoves.values.random()
@JvmStatic
fun count() = allMoves.size
@JvmStatic
fun names(): Collection<String> = this.allMoves.keys.toSet()
@JvmStatic
fun all() = this.allMoves.values.toList()
internal fun receiveSyncPacket(moves: Collection<MoveTemplate>) {
@@ -97,6 +97,7 @@ object NPCClasses : JsonDataRegistry<NPCClass> {
override val observable = SimpleObservable<NPCClasses>()
private val npcClassesByIdentifier = hashMapOf<ResourceLocation, NPCClass>()
@JvmStatic
val classes: Collection<NPCClass>
get() = this.npcClassesByIdentifier.values
@@ -116,6 +117,7 @@ object NPCClasses : JsonDataRegistry<NPCClass> {
* @param identifier The unique [NPCClass.id] of the [NPCClass].
* @return The [NPCClass] if existing.
*/
@JvmStatic
fun getByIdentifier(identifier: ResourceLocation) = this.npcClassesByIdentifier[identifier]
/**
@@ -123,6 +125,7 @@ object NPCClasses : JsonDataRegistry<NPCClass> {
*
* @return The loaded NPC class amount.
*/
@JvmStatic
fun count() = this.npcClassesByIdentifier.size
/**
@@ -132,6 +135,7 @@ object NPCClasses : JsonDataRegistry<NPCClass> {
*
* @return A randomly selected [Species].
*/
@JvmStatic
fun random(): NPCClass = this.npcClassesByIdentifier.values.random()
fun dummy(): NPCClass {
@@ -102,6 +102,7 @@ object NPCPresets : JsonDataRegistry<NPCPreset> {
observable.emit(this)
}
@JvmStatic
fun getPreset(identifier: ResourceLocation): NPCPreset? {
return npcPresetsByIdentifier[identifier]
}
@@ -10,6 +10,7 @@ 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.client.Minecraft
import net.minecraft.util.Mth
import net.minecraft.world.entity.LivingEntity
import org.joml.Matrix3f
@@ -63,6 +64,11 @@ open class OrientationController(val entity: LivingEntity) {
}
fun getRenderOrientation(delta: Float): Quaternionf {
// Return direct orientation if this is the player that drives this entities orientation.
//TODO: Why does this break the render orientation.
// if(entity.level().isClientSide && entity.controllingPassenger == Minecraft.getInstance().player) {
// return Quaternionf().setFromUnnormalized(orientation)
// }
val old = renderOrientationO ?: renderOrientation ?: orientation ?: Matrix3f()
val new = renderOrientation ?: old
val oldQuat = Quaternionf().setFromUnnormalized(old)
@@ -78,7 +84,7 @@ open class OrientationController(val entity: LivingEntity) {
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
val dampingFactor = 0.66f // Smooth interpolation to reduce jitter of orientations recieved from the server.
renderQuat.slerp(targetQuat, dampingFactor)
val newRenderOrientation = Matrix3f()
@@ -23,11 +23,14 @@ object PastureLinkManager {
// Maps player UUID
val links = mutableMapOf<UUID, PastureLink>()
@JvmStatic
fun getLinkByPlayerId(playerId: UUID) = links[playerId]
@JvmStatic
fun createLink(playerId: UUID, link: PastureLink) {
links[playerId] = link
}
@JvmStatic
fun getLinkByPlayer(player: ServerPlayer): PastureLink? {
val link = getLinkByPlayerId(player.uuid)
if (link != null) {
@@ -40,6 +43,7 @@ object PastureLinkManager {
return link
}
@JvmStatic
fun removeAt(world: ServerLevel, pos: BlockPos) {
links.removeIf { (uuid, pastureLink) ->
val shouldRemove = world.dimensionTypeRegistration().`is`(pastureLink.dimension) && pastureLink.pos == pos
@@ -28,6 +28,7 @@ import net.minecraft.server.level.ServerPlayer
object PasturePermissionControllers {
val controllers = PrioritizedList<PasturePermissionController>()
@JvmStatic
fun permit(player: ServerPlayer, pastureBlockEntity: PokemonPastureBlockEntity): PasturePermissions {
return controllers.firstNotNullOfOrNull { it.permit(player, pastureBlockEntity) }
?: PasturePermissions(
@@ -147,6 +147,10 @@ object CobblemonPermissions {
@JvmStatic
val SEE_HIDDEN_NPCS = this.create("seehiddennpcs", PermissionLevel.CHEAT_COMMANDS_AND_COMMAND_BLOCKS)
@JvmStatic
val USE_RIDING_STATS_DEBUG = this.create("useridingstatsdebug", PermissionLevel.CHEAT_COMMANDS_AND_COMMAND_BLOCKS)
@JvmStatic
fun all(): Iterable<Permission> = this.permissions
private fun create(node: String, level: PermissionLevel): Permission {
@@ -53,100 +53,196 @@ object PokeBalls : JsonDataRegistry<PokeBall> {
// ToDo datapack pokeball type here instead
private val custom = hashMapOf<ResourceLocation, PokeBall>()
@JvmStatic
@get:JvmName("getPokeBall")
val POKE_BALL
get() = this.byName("poke_ball")
@JvmStatic
@get:JvmName("getSlateBall")
val SLATE_BALL
get() = this.byName("slate_ball")
@JvmStatic
@get:JvmName("getAzureBall")
val AZURE_BALL
get() = this.byName("azure_ball")
@JvmStatic
@get:JvmName("getVerdantBall")
val VERDANT_BALL
get() = this.byName("verdant_ball")
@JvmStatic
@get:JvmName("getRoseateBall")
val ROSEATE_BALL
get() = this.byName("roseate_ball")
@JvmStatic
@get:JvmName("getCitrineBall")
val CITRINE_BALL
get() = this.byName("citrine_ball")
@JvmStatic
@get:JvmName("getGreatBall")
val GREAT_BALL
get() = this.byName("great_ball")
@JvmStatic
@get:JvmName("getUltraBall")
val ULTRA_BALL
get() = this.byName("ultra_ball")
@JvmStatic
@get:JvmName("getMasterBall")
val MASTER_BALL
get() = this.byName("master_ball")
@JvmStatic
@get:JvmName("getSafariBall")
val SAFARI_BALL
get() = this.byName("safari_ball")
@JvmStatic
@get:JvmName("getFastBall")
val FAST_BALL
get() = this.byName("fast_ball")
@JvmStatic
@get:JvmName("getLevelBall")
val LEVEL_BALL
get() = this.byName("level_ball")
@JvmStatic
@get:JvmName("getLureBall")
val LURE_BALL
get() = this.byName("lure_ball")
@JvmStatic
@get:JvmName("getHeavyBall")
val HEAVY_BALL
get() = this.byName("heavy_ball")
@JvmStatic
@get:JvmName("getLoveBall")
val LOVE_BALL
get() = this.byName("love_ball")
@JvmStatic
@get:JvmName("getFriendBall")
val FRIEND_BALL
get() = this.byName("friend_ball")
@JvmStatic
@get:JvmName("getMoonBall")
val MOON_BALL
get() = this.byName("moon_ball")
@JvmStatic
@get:JvmName("getSportBall")
val SPORT_BALL
get() = this.byName("sport_ball")
@JvmStatic
@get:JvmName("getNetBall")
val NET_BALL
get() = this.byName("net_ball")
@JvmStatic
@get:JvmName("getDiveBall")
val DIVE_BALL
get() = this.byName("dive_ball")
@JvmStatic
@get:JvmName("getNestBall")
val NEST_BALL
get() = this.byName("nest_ball")
@JvmStatic
@get:JvmName("getRepeatBall")
val REPEAT_BALL
get() = this.byName("repeat_ball")
@JvmStatic
@get:JvmName("getTimerBall")
val TIMER_BALL
get() = this.byName("timer_ball")
@JvmStatic
@get:JvmName("getLuxuryBall")
val LUXURY_BALL
get() = this.byName("luxury_ball")
@JvmStatic
@get:JvmName("getPremierBall")
val PREMIER_BALL
get() = this.byName("premier_ball")
@JvmStatic
@get:JvmName("getDuskBall")
val DUSK_BALL
get() = this.byName("dusk_ball")
@JvmStatic
@get:JvmName("getHealBall")
val HEAL_BALL
get() = this.byName("heal_ball")
@JvmStatic
@get:JvmName("getQuickBall")
val QUICK_BALL
get() = this.byName("quick_ball")
@JvmStatic
@get:JvmName("getCherishBall")
val CHERISH_BALL
get() = this.byName("cherish_ball")
@JvmStatic
@get:JvmName("getParkBall")
val PARK_BALL
get() = this.byName("park_ball")
@JvmStatic
@get:JvmName("getDreamBall")
val DREAM_BALL
get() = this.byName("dream_ball")
@JvmStatic
@get:JvmName("getBeastBall")
val BEAST_BALL
get() = this.byName("beast_ball")
@JvmStatic
@get:JvmName("getAncientPokeBall")
val ANCIENT_POKE_BALL
get() = this.byName("ancient_poke_ball")
@JvmStatic
@get:JvmName("getAncientCitrineBall")
val ANCIENT_CITRINE_BALL
get() = this.byName("ancient_citrine_ball")
@JvmStatic
@get:JvmName("getAncientVerdantBall")
val ANCIENT_VERDANT_BALL
get() = this.byName("ancient_verdant_ball")
@JvmStatic
@get:JvmName("getAncientAzureBall")
val ANCIENT_AZURE_BALL
get() = this.byName("ancient_azure_ball")
@JvmStatic
@get:JvmName("getAncientRoseateBall")
val ANCIENT_ROSEATE_BALL
get() = this.byName("ancient_roseate_ball")
@JvmStatic
@get:JvmName("getAncientSlateBall")
val ANCIENT_SLATE_BALL
get() = this.byName("ancient_slate_ball")
@JvmStatic
@get:JvmName("getAncientIvoryBall")
val ANCIENT_IVORY_BALL
get() = this.byName("ancient_ivory_ball")
@JvmStatic
@get:JvmName("getAncientGreatBall")
val ANCIENT_GREAT_BALL
get() = this.byName("ancient_great_ball")
@JvmStatic
@get:JvmName("getAncientUltraBall")
val ANCIENT_ULTRA_BALL
get() = this.byName("ancient_ultra_ball")
@JvmStatic
@get:JvmName("getAncientHeavyBall")
val ANCIENT_HEAVY_BALL
get() = this.byName("ancient_heavy_ball")
@JvmStatic
@get:JvmName("getAncientLeadenBall")
val ANCIENT_LEADEN_BALL
get() = this.byName("ancient_leaden_ball")
@JvmStatic
@get:JvmName("getAncientGigatonBall")
val ANCIENT_GIGATON_BALL
get() = this.byName("ancient_gigaton_ball")
@JvmStatic
@get:JvmName("getAncientFeatherBall")
val ANCIENT_FEATHER_BALL
get() = this.byName("ancient_feather_ball")
@JvmStatic
@get:JvmName("getAncientWingBall")
val ANCIENT_WING_BALL
get() = this.byName("ancient_wing_ball")
@JvmStatic
@get:JvmName("getAncientJetBall")
val ANCIENT_JET_BALL
get() = this.byName("ancient_jet_ball")
@JvmStatic
@get:JvmName("getAncientOriginBall")
val ANCIENT_ORIGIN_BALL
get() = this.byName("ancient_origin_ball")
@@ -225,8 +321,10 @@ object PokeBalls : JsonDataRegistry<PokeBall> {
* Gets a Pokeball from registry name.
* @return the pokeball object if found otherwise null.
*/
@JvmStatic
fun getPokeBall(name : ResourceLocation): PokeBall? = this.custom[name] ?: this.defaults[name]
@JvmStatic
fun all() = this.defaults.filterKeys { !this.custom.containsKey(it) }.values + this.custom.values
private fun createDefault(
@@ -250,4 +348,196 @@ object PokeBalls : JsonDataRegistry<PokeBall> {
val identifier = cobblemonResource(name)
return this.custom[identifier] ?: this.defaults[identifier]!!
}
/**
* Backwards compatibility getters
*/
@JvmName("getPOKE_BALL")
@Deprecated("Use PokeBalls.getPokeBall(), provided for backwards compatibility until Cobblemon 1.8.")
fun getPOKE_BALL() = POKE_BALL
@JvmName("getSLATE_BALL")
@Deprecated("Use PokeBalls.getSlateBall(), provided for backwards compatibility until Cobblemon 1.8.")
fun getSLATE_BALL() = SLATE_BALL
@JvmName("getAZURE_BALL")
@Deprecated("Use PokeBalls.getAzureBall(), provided for backwards compatibility until Cobblemon 1.8.")
fun getAZURE_BALL() = AZURE_BALL
@JvmName("getVERDANT_BALL")
@Deprecated("Use PokeBalls.getVerdantBall(), provided for backwards compatibility until Cobblemon 1.8.")
fun getVERDANT_BALL() = VERDANT_BALL
@JvmName("getROSEATE_BALL")
@Deprecated("Use PokeBalls.getRoseateBall(), provided for backwards compatibility until Cobblemon 1.8.")
fun getROSEATE_BALL() = ROSEATE_BALL
@JvmName("getCITRINE_BALL")
@Deprecated("Use PokeBalls.getCitrineBall(), provided for backwards compatibility until Cobblemon 1.8.")
fun getCITRINE_BALL() = CITRINE_BALL
@JvmName("getGREAT_BALL")
@Deprecated("Use PokeBalls.getGreatBall(), provided for backwards compatibility until Cobblemon 1.8.")
fun getGREAT_BALL() = GREAT_BALL
@JvmName("getULTRA_BALL")
@Deprecated("Use PokeBalls.getUltraBall(), provided for backwards compatibility until Cobblemon 1.8.")
fun getULTRA_BALL() = ULTRA_BALL
@JvmName("getMASTER_BALL")
@Deprecated("Use PokeBalls.getMasterBall(), provided for backwards compatibility until Cobblemon 1.8.")
fun getMASTER_BALL() = MASTER_BALL
@JvmName("getSAFARI_BALL")
@Deprecated("Use PokeBalls.getSafariBall(), provided for backwards compatibility until Cobblemon 1.8.")
fun getSAFARI_BALL() = SAFARI_BALL
@JvmName("getFAST_BALL")
@Deprecated("Use PokeBalls.getFastBall(), provided for backwards compatibility until Cobblemon 1.8.")
fun getFAST_BALL() = FAST_BALL
@JvmName("getLEVEL_BALL")
@Deprecated("Use PokeBalls.getLevelBall(), provided for backwards compatibility until Cobblemon 1.8.")
fun getLEVEL_BALL() = LEVEL_BALL
@JvmName("getLURE_BALL")
@Deprecated("Use PokeBalls.getLureBall(), provided for backwards compatibility until Cobblemon 1.8.")
fun getLURE_BALL() = LURE_BALL
@JvmName("getHEAVY_BALL")
@Deprecated("Use PokeBalls.getHeavyBall(), provided for backwards compatibility until Cobblemon 1.8.")
fun getHEAVY_BALL() = HEAVY_BALL
@JvmName("getLOVE_BALL")
@Deprecated("Use PokeBalls.getLoveBall(), provided for backwards compatibility until Cobblemon 1.8.")
fun getLOVE_BALL() = LOVE_BALL
@JvmName("getFRIEND_BALL")
@Deprecated("Use PokeBalls.getFriendBall(), provided for backwards compatibility until Cobblemon 1.8.")
fun getFRIEND_BALL() = FRIEND_BALL
@JvmName("getMOON_BALL")
@Deprecated("Use PokeBalls.getMoonBall(), provided for backwards compatibility until Cobblemon 1.8.")
fun getMOON_BALL() = MOON_BALL
@JvmName("getSPORT_BALL")
@Deprecated("Use PokeBalls.getSportBall(), provided for backwards compatibility until Cobblemon 1.8.")
fun getSPORT_BALL() = SPORT_BALL
@JvmName("getNET_BALL")
@Deprecated("Use PokeBalls.getNetBall(), provided for backwards compatibility until Cobblemon 1.8.")
fun getNET_BALL() = NET_BALL
@JvmName("getNEST_BALL")
@Deprecated("Use PokeBalls.getNestBall(), provided for backwards compatibility until Cobblemon 1.8.")
fun getNEST_BALL() = NEST_BALL
@JvmName("getREPEAT_BALL")
@Deprecated("Use PokeBalls.getRepeatBall(), provided for backwards compatibility until Cobblemon 1.8.")
fun getREPEAT_BALL() = REPEAT_BALL
@JvmName("getTIMER_BALL")
@Deprecated("Use PokeBalls.getTimerBall(), provided for backwards compatibility until Cobblemon 1.8.")
fun getTIMER_BALL() = TIMER_BALL
@JvmName("getLUXURY_BALL")
@Deprecated("Use PokeBalls.getLuxuryBall(), provided for backwards compatibility until Cobblemon 1.8.")
fun getLUXURY_BALL() = LUXURY_BALL
@JvmName("getPREMIER_BALL")
@Deprecated("Use PokeBalls.getPremierBall(), provided for backwards compatibility until Cobblemon 1.8.")
fun getPREMIER_BALL() = PREMIER_BALL
@JvmName("getDUSK_BALL")
@Deprecated("Use PokeBalls.getDuskBall(), provided for backwards compatibility until Cobblemon 1.8.")
fun getDUSK_BALL() = DUSK_BALL
@JvmName("getHEAL_BALL")
@Deprecated("Use PokeBalls.getHealBall(), provided for backwards compatibility until Cobblemon 1.8.")
fun getHEAL_BALL() = HEAL_BALL
@JvmName("getQUICK_BALL")
@Deprecated("Use PokeBalls.getQuickBall(), provided for backwards compatibility until Cobblemon 1.8.")
fun getQUICK_BALL() = QUICK_BALL
@JvmName("getCHERISH_BALL")
@Deprecated("Use PokeBalls.getCherishBall(), provided for backwards compatibility until Cobblemon 1.8.")
fun getCHERISH_BALL() = CHERISH_BALL
@JvmName("getPARK_BALL")
@Deprecated("Use PokeBalls.getParkBall(), provided for backwards compatibility until Cobblemon 1.8.")
fun getPARK_BALL() = PARK_BALL
@JvmName("getDREAM_BALL")
@Deprecated("Use PokeBalls.getDreamBall(), provided for backwards compatibility until Cobblemon 1.8.")
fun getDREAM_BALL() = DREAM_BALL
@JvmName("getBEAST_BALL")
@Deprecated("Use PokeBalls.getBeastBall(), provided for backwards compatibility until Cobblemon 1.8.")
fun getBEAST_BALL() = BEAST_BALL
@JvmName("getANCIENT_POKE_BALL")
@Deprecated("Use PokeBalls.getAncientPokeBall(), provided for backwards compatibility until Cobblemon 1.8.")
fun getANCIENT_POKE_BALL() = ANCIENT_POKE_BALL
@JvmName("getANCIENT_CITRINE_BALL")
@Deprecated("Use PokeBalls.getAncientCitrineBall(), provided for backwards compatibility until Cobblemon 1.8.")
fun getANCIENT_CITRINE_BALL() = ANCIENT_CITRINE_BALL
@JvmName("getANCIENT_VERDANT_BALL")
@Deprecated("Use PokeBalls.getAncientVerdantBall(), provided for backwards compatibility until Cobblemon 1.8.")
fun getANCIENT_VERDANT_BALL() = ANCIENT_VERDANT_BALL
@JvmName("getANCIENT_AZURE_BALL")
@Deprecated("Use PokeBalls.getAncientAzureBall(), provided for backwards compatibility until Cobblemon 1.8.")
fun getANCIENT_AZURE_BALL() = ANCIENT_AZURE_BALL
@JvmName("getANCIENT_ROSEATE_BALL")
@Deprecated("Use PokeBalls.getAncientRoseateBall(), provided for backwards compatibility until Cobblemon 1.8.")
fun getANCIENT_ROSEATE_BALL() = ANCIENT_ROSEATE_BALL
@JvmName("getANCIENT_SLATE_BALL")
@Deprecated("Use PokeBalls.getAncientSlateBall(), provided for backwards compatibility until Cobblemon 1.8.")
fun getANCIENT_SLATE_BALL() = ANCIENT_SLATE_BALL
@JvmName("getANCIENT_IVORY_BALL")
@Deprecated("Use PokeBalls.getAncientIvoryBall(), provided for backwards compatibility until Cobblemon 1.8.")
fun getANCIENT_IVORY_BALL() = ANCIENT_IVORY_BALL
@JvmName("getANCIENT_GREAT_BALL")
@Deprecated("Use PokeBalls.getAncientGreatBall(), provided for backwards compatibility until Cobblemon 1.8.")
fun getANCIENT_GREAT_BALL() = ANCIENT_GREAT_BALL
@JvmName("getANCIENT_ULTRA_BALL")
@Deprecated("Use PokeBalls.getAncientUltraBall(), provided for backwards compatibility until Cobblemon 1.8.")
fun getANCIENT_ULTRA_BALL() = ANCIENT_ULTRA_BALL
@JvmName("getANCIENT_HEAVY_BALL")
@Deprecated("Use PokeBalls.getAncientHeavyBall(), provided for backwards compatibility until Cobblemon 1.8.")
fun getANCIENT_HEAVY_BALL() = ANCIENT_HEAVY_BALL
@JvmName("getANCIENT_LEADEN_BALL")
@Deprecated("Use PokeBalls.getAncientLeadenBall(), provided for backwards compatibility until Cobblemon 1.8.")
fun getANCIENT_LEADEN_BALL() = ANCIENT_LEADEN_BALL
@JvmName("getANCIENT_GIGATON_BALL")
@Deprecated("Use PokeBalls.getAncientGigatonBall(), provided for backwards compatibility until Cobblemon 1.8.")
fun getANCIENT_GIGATON_BALL() = ANCIENT_GIGATON_BALL
@JvmName("getANCIENT_FEATHER_BALL")
@Deprecated("Use PokeBalls.getAncientFeatherBall(), provided for backwards compatibility until Cobblemon 1.8.")
fun getANCIENT_FEATHER_BALL() = ANCIENT_FEATHER_BALL
@JvmName("getANCIENT_WING_BALL")
@Deprecated("Use PokeBalls.getAncientWingBall(), provided for backwards compatibility until Cobblemon 1.8.")
fun getANCIENT_WING_BALL() = ANCIENT_WING_BALL
@JvmName("getANCIENT_JET_BALL")
@Deprecated("Use PokeBalls.getAncientJetBall(), provided for backwards compatibility until Cobblemon 1.8.")
fun getANCIENT_JET_BALL() = ANCIENT_JET_BALL
@JvmName("getANCIENT_ORIGIN_BALL")
@Deprecated("Use PokeBalls.getAncientOriginBall(), provided for backwards compatibility until Cobblemon 1.8.")
fun getANCIENT_ORIGIN_BALL() = ANCIENT_ORIGIN_BALL
}
@@ -24,126 +24,151 @@ import net.minecraft.resources.ResourceLocation
object Natures {
private val allNatures = mutableListOf<Nature>()
@JvmField
val HARDY = registerNature(
Nature(cobblemonResource("hardy"), "cobblemon.nature.hardy",
null, null, null, null)
)
@JvmField
val LONELY = registerNature(
Nature(cobblemonResource("lonely"), "cobblemon.nature.lonely",
Stats.ATTACK, Stats.DEFENCE, Flavour.SPICY, Flavour.SOUR)
)
@JvmField
val BRAVE = registerNature(
Nature(cobblemonResource("brave"), "cobblemon.nature.brave",
Stats.ATTACK, Stats.SPEED, Flavour.SPICY, Flavour.SWEET)
)
@JvmField
val ADAMANT = registerNature(
Nature(cobblemonResource("adamant"), "cobblemon.nature.adamant",
Stats.ATTACK, Stats.SPECIAL_ATTACK, Flavour.SPICY, Flavour.DRY)
)
@JvmField
val NAUGHTY = registerNature(
Nature(cobblemonResource("naughty"), "cobblemon.nature.naughty",
Stats.ATTACK, Stats.SPECIAL_DEFENCE, Flavour.SPICY, Flavour.BITTER)
)
@JvmField
val BOLD = registerNature(
Nature(cobblemonResource("bold"), "cobblemon.nature.bold",
Stats.DEFENCE, Stats.ATTACK, Flavour.SOUR, Flavour.SPICY)
)
@JvmField
val DOCILE = registerNature(
Nature(cobblemonResource("docile"), "cobblemon.nature.docile",
null, null, null, null)
)
@JvmField
val RELAXED = registerNature(
Nature(cobblemonResource("relaxed"), "cobblemon.nature.relaxed",
Stats.DEFENCE, Stats.SPEED, Flavour.SOUR, Flavour.SWEET)
)
@JvmField
val IMPISH = registerNature(
Nature(cobblemonResource("impish"), "cobblemon.nature.impish",
Stats.DEFENCE, Stats.SPECIAL_ATTACK, Flavour.SOUR, Flavour.DRY)
)
@JvmField
val LAX = registerNature(
Nature(cobblemonResource("lax"), "cobblemon.nature.lax",
Stats.DEFENCE, Stats.SPECIAL_DEFENCE, Flavour.SOUR, Flavour.BITTER)
)
@JvmField
val TIMID = registerNature(
Nature(cobblemonResource("timid"), "cobblemon.nature.timid",
Stats.SPEED, Stats.ATTACK, Flavour.SWEET, Flavour.SPICY)
)
@JvmField
val HASTY = registerNature(
Nature(cobblemonResource("hasty"), "cobblemon.nature.hasty",
Stats.SPEED, Stats.DEFENCE, Flavour.SWEET, Flavour.SOUR)
)
@JvmField
val SERIOUS = registerNature(
Nature(cobblemonResource("serious"), "cobblemon.nature.serious",
null, null, null, null)
)
@JvmField
val JOLLY = registerNature(
Nature(cobblemonResource("jolly"), "cobblemon.nature.jolly",
Stats.SPEED, Stats.SPECIAL_ATTACK, Flavour.SWEET, Flavour.DRY)
)
@JvmField
val NAIVE = registerNature(
Nature(cobblemonResource("naive"), "cobblemon.nature.naive",
Stats.SPEED, Stats.SPECIAL_DEFENCE, Flavour.SWEET, Flavour.BITTER)
)
@JvmField
val MODEST = registerNature(
Nature(cobblemonResource("modest"), "cobblemon.nature.modest",
Stats.SPECIAL_ATTACK, Stats.ATTACK, null, null)
)
@JvmField
val MILD = registerNature(
Nature(cobblemonResource("mild"), "cobblemon.nature.mild",
Stats.SPECIAL_ATTACK, Stats.DEFENCE, Flavour.DRY, Flavour.SOUR)
)
@JvmField
val QUIET = registerNature(
Nature(cobblemonResource("quiet"), "cobblemon.nature.quiet",
Stats.SPECIAL_ATTACK, Stats.SPEED, Flavour.DRY, Flavour.SWEET)
)
@JvmField
val BASHFUL = registerNature(
Nature(cobblemonResource("bashful"), "cobblemon.nature.bashful",
null, null, null, null)
)
@JvmField
val RASH = registerNature(
Nature(cobblemonResource("rash"), "cobblemon.nature.rash",
Stats.SPECIAL_ATTACK, Stats.SPECIAL_DEFENCE, Flavour.DRY, Flavour.BITTER)
)
@JvmField
val CALM = registerNature(
Nature(cobblemonResource("calm"), "cobblemon.nature.calm",
Stats.SPECIAL_DEFENCE, Stats.ATTACK, Flavour.BITTER, Flavour.SPICY)
)
@JvmField
val GENTLE = registerNature(
Nature(cobblemonResource("gentle"), "cobblemon.nature.gentle",
Stats.SPECIAL_DEFENCE, Stats.DEFENCE, Flavour.BITTER, Flavour.SOUR)
)
@JvmField
val SASSY = registerNature(
Nature(cobblemonResource("sassy"), "cobblemon.nature.sassy",
Stats.SPECIAL_DEFENCE, Stats.SPEED, Flavour.BITTER, Flavour.SWEET)
)
@JvmField
val CAREFUL = registerNature(
Nature(cobblemonResource("careful"), "cobblemon.nature.careful",
Stats.SPECIAL_DEFENCE, Stats.SPECIAL_ATTACK, Flavour.BITTER, Flavour.DRY)
)
@JvmField
val QUIRKY = registerNature(
Nature(cobblemonResource("quirky"), "cobblemon.nature.quirky",
null, null, null, null)
@@ -153,6 +178,7 @@ object Natures {
/**
* Registers a new nature type
*/
@JvmStatic
fun registerNature(nature: Nature): Nature {
allNatures.add(nature)
return nature
@@ -162,6 +188,7 @@ object Natures {
* Gets a nature by registry name
* @return a nature type or null
*/
@JvmStatic
fun getNature(name: ResourceLocation): Nature? {
return allNatures.find { nature -> nature.name == name }
}
@@ -170,6 +197,7 @@ object Natures {
* Utility method to get a nature by string
* @return a nature type or null
*/
@JvmStatic
fun getNature(identifier: String) = getNature(cobblemonResource(identifier))
?: getNature(ResourceLocation.parse(identifier))
@@ -177,10 +205,114 @@ object Natures {
* Helper function for a random Nature
* @return a random nature type
*/
@JvmStatic
fun getRandomNature(): Nature {
return allNatures.random()
}
@JvmStatic
fun all(): Collection<Nature> = this.allNatures.toList()
/**
* Backwards compatibility getters
*/
@JvmName("getHARDY")
@Deprecated("Use Natures.HARDY, provided for backwards compatibility until Cobblemon 1.8.")
fun getHARDY() = HARDY
@JvmName("getLONELY")
@Deprecated("Use Natures.LONELY, provided for backwards compatibility until Cobblemon 1.8.")
fun getLONELY() = LONELY
@JvmName("getBRAVE")
@Deprecated("Use Natures.BRAVE, provided for backwards compatibility until Cobblemon 1.8.")
fun getBRAVE() = BRAVE
@JvmName("getADAMANT")
@Deprecated("Use Natures.ADAMANT, provided for backwards compatibility until Cobblemon 1.8.")
fun getADAMANT() = ADAMANT
@JvmName("getNAUGHTY")
@Deprecated("Use Natures.NAUGHTY, provided for backwards compatibility until Cobblemon 1.8.")
fun getNAUGHTY() = NAUGHTY
@JvmName("getBOLD")
@Deprecated("Use Natures.BOLD, provided for backwards compatibility until Cobblemon 1.8.")
fun getBOLD() = BOLD
@JvmName("getDOCILE")
@Deprecated("Use Natures.DOCILE, provided for backwards compatibility until Cobblemon 1.8.")
fun getDOCILE() = DOCILE
@JvmName("getRELAXED")
@Deprecated("Use Natures.RELAXED, provided for backwards compatibility until Cobblemon 1.8.")
fun getRELAXED() = RELAXED
@JvmName("getIMPISH")
@Deprecated("Use Natures.IMPISH, provided for backwards compatibility until Cobblemon 1.8.")
fun getIMPISH() = IMPISH
@JvmName("getLAX")
@Deprecated("Use Natures.LAX, provided for backwards compatibility until Cobblemon 1.8.")
fun getLAX() = LAX
@JvmName("getTIMID")
@Deprecated("Use Natures.TIMID, provided for backwards compatibility until Cobblemon 1.8.")
fun getTIMID() = TIMID
@JvmName("getHASTY")
@Deprecated("Use Natures.HASTY, provided for backwards compatibility until Cobblemon 1.8.")
fun getHASTY() = HASTY
@JvmName("getSERIOUS")
@Deprecated("Use Natures.SERIOUS, provided for backwards compatibility until Cobblemon 1.8.")
fun getSERIOUS() = SERIOUS
@JvmName("getJOLLY")
@Deprecated("Use Natures.JOLLY, provided for backwards compatibility until Cobblemon 1.8.")
fun getJOLLY() = JOLLY
@JvmName("getNAIVE")
@Deprecated("Use Natures.NAIVE, provided for backwards compatibility until Cobblemon 1.8.")
fun getNAIVE() = NAIVE
@JvmName("getMODEST")
@Deprecated("Use Natures.MODEST, provided for backwards compatibility until Cobblemon 1.8.")
fun getMODEST() = MODEST
@JvmName("getMILD")
@Deprecated("Use Natures.MILD, provided for backwards compatibility until Cobblemon 1.8.")
fun getMILD() = MILD
@JvmName("getQUIET")
@Deprecated("Use Natures.QUIET, provided for backwards compatibility until Cobblemon 1.8.")
fun getQUIET() = QUIET
@JvmName("getBASHFUL")
@Deprecated("Use Natures.BASHFUL, provided for backwards compatibility until Cobblemon 1.8.")
fun getBASHFUL() = BASHFUL
@JvmName("getRASH")
@Deprecated("Use Natures.RASH, provided for backwards compatibility until Cobblemon 1.8.")
fun getRASH() = RASH
@JvmName("getCALM")
@Deprecated("Use Natures.CALM, provided for backwards compatibility until Cobblemon 1.8.")
fun getCALM() = CALM
@JvmName("getGENTLE")
@Deprecated("Use Natures.GENTLE, provided for backwards compatibility until Cobblemon 1.8.")
fun getGENTLE() = GENTLE
@JvmName("getSASSY")
@Deprecated("Use Natures.SASSY, provided for backwards compatibility until Cobblemon 1.8.")
fun getSASSY() = SASSY
@JvmName("getCAREFUL")
@Deprecated("Use Natures.CAREFUL, provided for backwards compatibility until Cobblemon 1.8.")
fun getCAREFUL() = CAREFUL
@JvmName("getQUIRKY")
@Deprecated("Use Natures.QUIRKY, provided for backwards compatibility until Cobblemon 1.8.")
fun getQUIRKY() = QUIRKY
}
@@ -17,6 +17,7 @@ import com.cobblemon.mod.common.api.events.pokemon.ShinyChanceCalculationEvent
import com.cobblemon.mod.common.api.moves.Moves
import com.cobblemon.mod.common.api.pokeball.PokeBalls
import com.cobblemon.mod.common.api.pokemon.aspect.AspectProvider
import com.cobblemon.mod.common.api.pokemon.stats.Stat
import com.cobblemon.mod.common.api.pokemon.stats.Stats
import com.cobblemon.mod.common.api.pokemon.status.Statuses
import com.cobblemon.mod.common.api.properties.CustomPokemonProperty
@@ -31,10 +32,12 @@ import com.cobblemon.mod.common.pokemon.IVs
import com.cobblemon.mod.common.pokemon.OriginalTrainerType
import com.cobblemon.mod.common.pokemon.Pokemon
import com.cobblemon.mod.common.pokemon.RenderablePokemon
import com.cobblemon.mod.common.pokemon.stat.CobblemonStatProvider
import com.cobblemon.mod.common.pokemon.status.PersistentStatus
import com.cobblemon.mod.common.util.DataKeys
import com.cobblemon.mod.common.util.asIdentifierDefaultingNamespace
import com.cobblemon.mod.common.util.isDouble
import com.cobblemon.mod.common.util.isFloat
import com.cobblemon.mod.common.util.isUuid
import com.cobblemon.mod.common.util.server
import com.cobblemon.mod.common.util.simplify
@@ -146,6 +149,8 @@ open class PokemonProperties {
props.originalTrainer = parsePlayerProperty(keyPairs, listOf("originaltrainer", "ot"))
props.moves = parseString(keyPairs, listOf("moves"))?.split(",")
props.heldItem = parseString(keyPairs, listOf("helditem", "held_item"))
props.minPerfectIVs = parseIntProperty(keyPairs, listOf("min_perfect_ivs"))?.coerceIn(0, Stats.PERMANENT.size)
props.scaleModifier = parseFloatProperty(keyPairs, listOf("scale_modifier"))
val maybeIVs = IVs()
val maybeEVs = EVs()
@@ -195,6 +200,16 @@ open class PokemonProperties {
}
}
private fun parseFloatProperty(keyPairs: MutableList<Pair<String, String?>>, labels: Iterable<String>): Float? {
val matchingKeyPair = getMatchedKeyPair(keyPairs, labels) ?: return null
val value = matchingKeyPair.second
return if (value == null || !value.isFloat()) {
null
} else {
value.toFloat()
}
}
private fun parseIdentifierOfRegistry(keyPairs: MutableList<Pair<String, String?>>, validKeys: List<String>, valueFetcher: (ResourceLocation) -> String?): String? {
val matched = getMatchedKeyPair(keyPairs, validKeys) ?: return null
val value = matched.second?.lowercase() ?: return null
@@ -343,7 +358,9 @@ open class PokemonProperties {
var moves: List<String>? = null
var heldItem: String? = null
var cosmeticItem: String? = null
var scaleModifier: Float? = null
var minPerfectIVs: Int? = null
var ivs: IVs? = null
var evs: EVs? = null
var customProperties = mutableListOf<CustomPokemonProperty>()
@@ -413,6 +430,11 @@ open class PokemonProperties {
pokemon.hyperTrainIV(stat.key, stat.value)
}
}
minPerfectIVs?.let {
CobblemonStatProvider.ofType(Stat.Type.PERMANENT).shuffled().take(it).forEach { stat ->
pokemon.setIV(stat, IVs.MAX_VALUE)
}
}
evs?.let { evs ->
evs.forEach { stat ->
pokemon.setEV(stat.key, stat.value)
@@ -469,6 +491,7 @@ open class PokemonProperties {
if (stack.isEmpty) return@let
pokemon.swapHeldItem(stack, decrement = true, aiCanDrop = false)
}
scaleModifier?.let { pokemon.scaleModifier = it }
pokemon.updateAspects()
}
@@ -512,6 +535,7 @@ open class PokemonProperties {
nature?.takeIf { it != pokemon.nature.name.toString() }?.let { return false }
ability?.takeIf { it != pokemon.ability.name }?.let { return false }
status?.takeIf { it != pokemon.status?.status?.showdownName }?.let { return false }
minPerfectIVs?.takeIf { pokemon.ivs.count { stat -> stat.value == IVs.MAX_VALUE } < it }?.let { return false }
ivs?.forEach{ stat ->
if (stat.value != pokemon.ivs[stat.key]) { return false }
}
@@ -542,6 +566,7 @@ open class PokemonProperties {
return@takeIf false
}?.let { return false }
scaleModifier?.takeIf { it != pokemon.scaleModifier }?.let { return false }
return true
}
@@ -570,6 +595,7 @@ open class PokemonProperties {
nature?.takeIf { it != properties.nature }?.let { return false }
ability?.takeIf { it != properties.ability }?.let { return false }
status?.takeIf { it != properties.status }?.let { return false }
minPerfectIVs?.takeIf { it != properties.minPerfectIVs }?.let { return false }
ivs?.let{ ivs ->
ivs.forEach{ stat ->
//If the potential subset has IV and the main set does not then it cant be a subset
@@ -593,6 +619,7 @@ open class PokemonProperties {
originalTrainerType?.takeIf { it != properties.originalTrainerType }?.let{ return false }
moves?.takeIf { it.any { move -> properties.moves?.none { it == move } == true } }?.let { return false }
fullness?.takeIf { it != properties.fullness }?.let { return false }
scaleModifier?.takeIf { it != properties.scaleModifier }?.let { return false }
return true
}
@@ -646,6 +673,7 @@ open class PokemonProperties {
nature?.let { nbt.putString(DataKeys.POKEMON_NATURE, it) }
ability?.let { nbt.putString(DataKeys.POKEMON_ABILITY, it) }
status?.let { nbt.putString(DataKeys.POKEMON_STATUS_NAME, it) }
minPerfectIVs?.let { nbt.putInt(DataKeys.POKEMON_MIN_PERFECT_IVS, it) }
ivs?.let { nbt.put(DataKeys.POKEMON_IVS, IVs.CODEC.encodeStart(NbtOps.INSTANCE, it).result().get()) }
evs?.let { nbt.put(DataKeys.POKEMON_EVS, EVs.CODEC.encodeStart(NbtOps.INSTANCE, it).result().get()) }
type?.let { nbt.putString(DataKeys.ELEMENTAL_TYPE, it) }
@@ -657,6 +685,7 @@ open class PokemonProperties {
originalTrainer?.let { nbt.putString(DataKeys.POKEMON_ORIGINAL_TRAINER, it) }
moves?.let { nbt.putString(DataKeys.POKEMON_PROPERTIES_MOVES, it.joinToString(separator = ",")) }
heldItem?.let {nbt.putString(DataKeys.POKEMON_PROPERTIES_HELDITEM, it)}
scaleModifier?.let { nbt.putFloat(DataKeys.POKEMON_SCALE_MODIFIER, it) }
val custom = ListTag()
customProperties.map { StringTag.valueOf(it.asString()) }.forEach { custom.add(it) }
nbt.put(DataKeys.POKEMON_PROPERTIES_CUSTOM, custom)
@@ -678,6 +707,7 @@ open class PokemonProperties {
nature = if (tag.contains(DataKeys.POKEMON_NATURE)) tag.getString(DataKeys.POKEMON_NATURE) else null
ability = if (tag.contains(DataKeys.POKEMON_ABILITY)) tag.getString(DataKeys.POKEMON_ABILITY) else null
status = if (tag.contains(DataKeys.POKEMON_STATUS_NAME)) tag.getString(DataKeys.POKEMON_STATUS_NAME) else null
minPerfectIVs = if (tag.contains(DataKeys.POKEMON_MIN_PERFECT_IVS)) tag.getInt(DataKeys.POKEMON_MIN_PERFECT_IVS) else null
ivs = if (tag.contains(DataKeys.POKEMON_IVS)) IVs.CODEC.decode(NbtOps.INSTANCE, tag.getCompound(DataKeys.POKEMON_IVS)).result().getOrNull()?.first else null
evs = if (tag.contains(DataKeys.POKEMON_EVS)) EVs.CODEC.decode(NbtOps.INSTANCE, tag.getCompound(DataKeys.POKEMON_EVS)).result().getOrNull()?.first else null
type = if (tag.contains(DataKeys.ELEMENTAL_TYPE)) tag.getString(DataKeys.ELEMENTAL_TYPE) else null
@@ -689,6 +719,7 @@ open class PokemonProperties {
originalTrainer = if (tag.contains(DataKeys.POKEMON_ORIGINAL_TRAINER)) tag.getString(DataKeys.POKEMON_ORIGINAL_TRAINER) else null
moves = if (tag.contains(DataKeys.POKEMON_PROPERTIES_MOVES)) tag.getString(DataKeys.POKEMON_PROPERTIES_MOVES).split(",") else null
heldItem = if (tag.contains(DataKeys.POKEMON_PROPERTIES_HELDITEM)) tag.getString(DataKeys.POKEMON_PROPERTIES_HELDITEM) else null
scaleModifier = if (tag.contains(DataKeys.POKEMON_SCALE_MODIFIER)) tag.getFloat(DataKeys.POKEMON_SCALE_MODIFIER) else null
val custom = tag.getList(DataKeys.POKEMON_PROPERTIES_CUSTOM, Tag.TAG_STRING.toInt())
// This is kinda gross
custom.forEach { customProperties.addAll(parse(it.asString).customProperties) }
@@ -704,14 +735,14 @@ open class PokemonProperties {
shiny?.let { json.addProperty(DataKeys.POKEMON_SHINY, it) }
gender?.let { json.addProperty(DataKeys.POKEMON_GENDER, it.name) }
species?.let { json.addProperty(DataKeys.POKEMON_SPECIES_TEXT, it) }
//nickname?.let { json.addProperty(DataKeys.POKEMON_NICKNAME, Text.Serialization.toJsonString(it)) }
form?.let { json.addProperty(DataKeys.POKEMON_FORM_ID, it) }
friendship?.let { json.addProperty(DataKeys.POKEMON_FRIENDSHIP, it) }
fullness?.let {json.addProperty(DataKeys.POKEMON_FULLNESS, it)}
fullness?.let { json.addProperty(DataKeys.POKEMON_FULLNESS, it) }
pokeball?.let { json.addProperty(DataKeys.POKEMON_CAUGHT_BALL, it) }
nature?.let { json.addProperty(DataKeys.POKEMON_NATURE, it) }
ability?.let { json.addProperty(DataKeys.POKEMON_ABILITY, it) }
status?.let { json.addProperty(DataKeys.POKEMON_STATUS_NAME, it) }
minPerfectIVs?.let { json.addProperty(DataKeys.POKEMON_MIN_PERFECT_IVS, it) }
ivs?.let { json.add(DataKeys.POKEMON_IVS, IVs.CODEC.encodeStart(JsonOps.INSTANCE, it).result().get()) }
evs?.let { json.add(DataKeys.POKEMON_EVS, EVs.CODEC.encodeStart(JsonOps.INSTANCE, it).result().get()) }
type?.let { json.addProperty(DataKeys.ELEMENTAL_TYPE, it) }
@@ -723,6 +754,7 @@ open class PokemonProperties {
originalTrainer?.let { json.addProperty(DataKeys.POKEMON_ORIGINAL_TRAINER, it) }
moves?.let { json.addProperty(DataKeys.POKEMON_PROPERTIES_MOVES, it.joinToString(separator = ",")) }
heldItem?.let {json.addProperty(DataKeys.POKEMON_PROPERTIES_HELDITEM, it)}
scaleModifier?.let { json.addProperty(DataKeys.POKEMON_SCALE_MODIFIER, it) }
val custom = JsonArray()
customProperties.map { it.asString() }.forEach { custom.add(it) }
json.add(DataKeys.POKEMON_PROPERTIES_CUSTOM, custom)
@@ -737,7 +769,6 @@ open class PokemonProperties {
shiny = json.get(DataKeys.POKEMON_SHINY)?.asBoolean
gender = json.get(DataKeys.POKEMON_GENDER)?.asString?.let { Gender.valueOf(it) }
species = json.get(DataKeys.POKEMON_SPECIES_TEXT)?.asString
//nickname = json.get(DataKeys.POKEMON_NICKNAME)?.asString?.let { Text.Serialization.fromJson(it) }
form = json.get(DataKeys.POKEMON_FORM_ID)?.asString
friendship = json.get(DataKeys.POKEMON_FRIENDSHIP)?.asInt
fullness = json.get(DataKeys.POKEMON_FULLNESS)?.asInt
@@ -745,6 +776,7 @@ open class PokemonProperties {
nature = json.get(DataKeys.POKEMON_NATURE)?.asString
ability = json.get(DataKeys.POKEMON_ABILITY)?.asString
status = json.get(DataKeys.POKEMON_STATUS_NAME)?.asString
minPerfectIVs = json.get(DataKeys.POKEMON_MIN_PERFECT_IVS)?.asInt
ivs = json.getAsJsonObject(DataKeys.POKEMON_IVS)?.let { IVs.CODEC.decode(JsonOps.INSTANCE, it).result().getOrNull()?.first }
evs = json.getAsJsonObject(DataKeys.POKEMON_EVS)?.let { EVs.CODEC.decode(JsonOps.INSTANCE, it).result().getOrNull()?.first }
type = json.get(DataKeys.ELEMENTAL_TYPE)?.asString
@@ -756,6 +788,7 @@ open class PokemonProperties {
originalTrainer = json.get(DataKeys.POKEMON_ORIGINAL_TRAINER)?.asString
moves = json.get(DataKeys.POKEMON_PROPERTIES_MOVES)?.asString?.split(",")
heldItem = json.get(DataKeys.POKEMON_PROPERTIES_HELDITEM)?.asString
scaleModifier = json.get(DataKeys.POKEMON_SCALE_MODIFIER)?.asFloat
val custom = json.get(DataKeys.POKEMON_PROPERTIES_CUSTOM)?.asJsonArray
// This is still kinda gross
custom?.forEach { customProperties.addAll(parse(it.asString).customProperties) }
@@ -772,11 +805,12 @@ open class PokemonProperties {
shiny?.let { pieces.add("shiny=$it") }
gender?.let { pieces.add("gender=$it")}
friendship?.let { pieces.add("friendship=$it") }
fullness?.let {pieces.add("fullness=$it")}
fullness?.let { pieces.add("fullness=$it") }
pokeball?.let { pieces.add("pokeball=$it") }
nature?.let { pieces.add("nature=$it") }
ability?.let { pieces.add("ability=$it") }
status?.let { pieces.add("status=$it") }
minPerfectIVs?.let { pieces.add("min_perfect_ivs=$it") }
ivs?.forEach{ stat ->
pieces.add("${stat.key}_iv=${stat.value}")
}
@@ -793,6 +827,7 @@ open class PokemonProperties {
customProperties.forEach { pieces.add(it.asString()) }
moves?.let { pieces.add("moves=${it.joinToString(separator = ",")}") }
heldItem?.let {pieces.add("helditem=$it")}
scaleModifier?.let { pieces.add("scale_modifier=$it") }
return pieces.joinToString(separator)
}
@@ -142,8 +142,10 @@ object PokemonSpecies : JsonDataRegistry<Species> {
private val speciesByIdentifier = hashMapOf<ResourceLocation, Species>()
private val speciesByDex = HashBasedTable.create<String, Int, Species>()
@JvmStatic
val species: Collection<Species>
get() = this.speciesByIdentifier.values
@JvmStatic
val implemented: List<Species>
get() = this.species.filter { it.implemented }
@@ -169,6 +171,7 @@ object PokemonSpecies : JsonDataRegistry<Species> {
* @param name The path of the species asset.
* @return The [Species] if existing.
*/
@JvmStatic
fun getByName(name: String) = this.getByIdentifier(cobblemonResource(name))
/**
@@ -177,6 +180,7 @@ object PokemonSpecies : JsonDataRegistry<Species> {
* @param ndex The [Species.nationalPokedexNumber].
* @return The [Species] if existing.
*/
@JvmStatic
fun getByPokedexNumber(ndex: Int, namespace: String = Cobblemon.MODID) = this.speciesByDex.get(namespace, ndex)
/**
@@ -185,6 +189,7 @@ object PokemonSpecies : JsonDataRegistry<Species> {
* @param identifier The unique [Species.resourceIdentifier] of the [Species].
* @return The [Species] if existing.
*/
@JvmStatic
fun getByIdentifier(identifier: ResourceLocation) = this.speciesByIdentifier[identifier]
/**
@@ -192,6 +197,7 @@ object PokemonSpecies : JsonDataRegistry<Species> {
*
* @return The loaded species amount.
*/
@JvmStatic
fun count() = this.speciesByIdentifier.size
/**
@@ -199,6 +205,7 @@ object PokemonSpecies : JsonDataRegistry<Species> {
*
* @return The dex numbers map to species.
*/
@JvmStatic
fun getSpeciesInNamespace(namespace: String = Cobblemon.MODID): MutableMap<Int, Species> = speciesByDex.row(namespace)
/**
@@ -206,6 +213,7 @@ object PokemonSpecies : JsonDataRegistry<Species> {
*
* @return The list of loaded namespaces.
*/
@JvmStatic
fun getNamespaces() = speciesByDex.rowKeySet().toList()
/**
@@ -215,6 +223,7 @@ object PokemonSpecies : JsonDataRegistry<Species> {
*
* @return A randomly selected [Species].
*/
@JvmStatic
fun random(): Species = this.implemented.random()
override fun reload(data: Map<ResourceLocation, Species>) {
@@ -314,4 +323,4 @@ object PokemonSpecies : JsonDataRegistry<Species> {
}
return result
}
}
}
@@ -36,12 +36,16 @@ object ShoulderEffectRegistry {
PlatformEvents.SERVER_PLAYER_LOGIN.subscribe { this.refreshEffects(it.player) }
}
@JvmStatic
fun register(name: String, effect: Class<out ShoulderEffect>) = effect.also { effects[name] = it }
@JvmStatic
fun unregister(name: String) = effects.remove(name)
@JvmStatic
fun getName(clazz: Class<out ShoulderEffect>) = effects.firstNotNullOf { if (it.value == clazz) it.key else null }
@JvmStatic
fun get(name: String): Class<out ShoulderEffect>? = effects[name]
// It was removed by a source such as milk, reapply
@@ -62,10 +62,14 @@ object GlobalSpeciesFeatures : JsonDataRegistry<SpeciesFeatureProvider<*>> {
data.forEach(this::registerFromAssets)
}
@JvmStatic
fun getCodeFeature(name: String) = codeFeatures[name]
@JvmStatic
fun getResourceFeature(name: String) = resourceFeatures[name]
@JvmStatic
fun getFeature(name: String) = getCodeFeature(name) ?: getResourceFeature(name)
@JvmStatic
fun getFeatures() = (resourceFeatures.keys + codeFeatures.keys).mapNotNull(this::getFeature)
fun loadOnClient(entries: Collection<Map.Entry<String, SpeciesFeatureProvider<*>>>) {
@@ -83,7 +87,9 @@ object GlobalSpeciesFeatures : JsonDataRegistry<SpeciesFeatureProvider<*>> {
mapping[name] = provider
}
@JvmStatic
fun register(name: String, provider: SpeciesFeatureProvider<*>) = register(name, provider, isCoded = true)
@JvmStatic
fun <T : SpeciesFeature> register(name: String, providerLambda: () -> T) {
register(name, object : SpeciesFeatureProvider<T> {
override fun invoke(pokemon: Pokemon) = providerLambda()
@@ -93,6 +99,7 @@ object GlobalSpeciesFeatures : JsonDataRegistry<SpeciesFeatureProvider<*>> {
}
private fun registerFromAssets(identifier: ResourceLocation, provider: SpeciesFeatureProvider<*>) = register(identifier.path, provider, isCoded = false)
@JvmStatic
fun unregister(name: String) {
var coded = true
val value = getResourceFeature(name)?.also { coded = false } ?: getCodeFeature(name) ?: return
@@ -66,12 +66,16 @@ class IntSpeciesFeature(override var name: String) : SynchronizedSpeciesFeature,
override fun apply(pokemon: Pokemon) {
val featureProvider = SpeciesFeatures.getFeature(name) ?: return
if (featureProvider in SpeciesFeatures.getFeaturesFor(pokemon.species)) {
val existingFeature = pokemon.getFeature<IntSpeciesFeature>(name)
var existingFeature = pokemon.getFeature<IntSpeciesFeature>(name)
if (existingFeature != null) {
existingFeature.value = value
} else {
pokemon.features.add(IntSpeciesFeature(name, value))
existingFeature = IntSpeciesFeature(name, value)
pokemon.features.add(existingFeature)
}
pokemon.markFeatureDirty(existingFeature)
pokemon.updateAspects()
}
}
@@ -60,5 +60,6 @@ object SpeciesFeatureAssignments : JsonDataRegistry<SpeciesFeatureAssignment> {
this.assignments.putAll(data)
}
@JvmStatic
fun getFeatures(species: Species) = assignments[species.resourceIdentifier] ?: emptySet()
}
@@ -68,14 +68,19 @@ object SpeciesFeatures : JsonDataRegistry<SpeciesFeatureProvider<*>> {
data.forEach(this::registerFromAssets)
}
@JvmStatic
fun getCodeFeature(name: String) = codeFeatures[name]
@JvmStatic
fun getResourceFeature(name: String) = resourceFeatures[name]
@JvmStatic
fun getFeature(name: String) = getCodeFeature(name) ?: getResourceFeature(name) ?: GlobalSpeciesFeatures.getFeature(name)
fun loadOnClient(entries: Collection<Map.Entry<String, SpeciesFeatureProvider<*>>>) {
codeFeatures.putAll(entries.map { it.toPair() })
}
@JvmStatic
fun getFeatures() = (resourceFeatures.keys + codeFeatures.keys).mapNotNull(this::getFeature)
@JvmStatic
fun getFeaturesFor(species: Species): List<SpeciesFeatureProvider<*>> {
val mentionedFeatures = species.features.mapNotNull(this::getFeature)
val globalFeatures = GlobalSpeciesFeatures.getFeatures()
@@ -95,9 +100,11 @@ object SpeciesFeatures : JsonDataRegistry<SpeciesFeatureProvider<*>> {
mapping[name] = provider
}
@JvmStatic
fun register(name: String, provider: SpeciesFeatureProvider<*>) = register(name, provider, isCoded = true)
private fun registerFromAssets(identifier: ResourceLocation, provider: SpeciesFeatureProvider<*>) = register(identifier.path, provider, isCoded = false)
@JvmStatic
fun unregister(name: String) {
var coded = true
val value = getResourceFeature(name)?.also { coded = false } ?: getCodeFeature(name) ?: return
@@ -0,0 +1,17 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.pokemon.feature
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import com.cobblemon.mod.common.pokemon.Pokemon
import net.minecraft.server.level.ServerLevel
interface TickingSpeciesFeature {
fun onSecondPassed(world: ServerLevel, pokemon: Pokemon, entity: PokemonEntity?)
}
@@ -29,6 +29,7 @@ object HeldItemProvider {
* @param pokemon The [Pokemon] being queried.
* @return The [HeldItemManager] that can provide for the given [pokemon], if non match returns the [HeldItemManager.EMPTY].
*/
@JvmStatic
fun provide(pokemon: BattlePokemon): HeldItemManager = this.managers.firstOrNull { manager -> manager.showdownId(pokemon) != null } ?: HeldItemManager.EMPTY
/**
@@ -37,6 +38,7 @@ object HeldItemProvider {
* @param pokemon The [Pokemon] being queried.
* @return The showdownId string that [pokemon] is holding, otherwise null.
*/
@JvmStatic
fun provideShowdownId(pokemon: BattlePokemon) = this.managers.firstNotNullOfOrNull { manager -> manager.showdownId(pokemon) }
/**
@@ -45,6 +47,8 @@ object HeldItemProvider {
* @param manager The [HeldItemManager] being registered.
* @param priority The [Priority] to register it under.
*/
@JvmStatic
@JvmOverloads
fun register(manager: HeldItemManager, priority: Priority = Priority.NORMAL) {
this.managers.add(priority, manager)
}
@@ -56,6 +60,8 @@ object HeldItemProvider {
* @param priority The [Priority] to specifically remove the instance from, if null it will remove from all.
*/
@Suppress("unused")
@JvmStatic
@JvmOverloads
fun unregister(manager: HeldItemManager, priority: Priority? = null) {
if (priority != null) {
this.managers.remove(priority, manager)
@@ -69,6 +75,7 @@ object HeldItemProvider {
*
* @return The read-only copy of the registered [HeldItemManager]s.
*/
@JvmStatic
fun managers(): List<HeldItemManager> = this.managers.toList()
}
@@ -34,17 +34,24 @@ object Statuses {
private val volatileStatuses = mutableListOf<Status>()
private val allStatuses = mutableListOf<Status>()
@JvmField
val POISON = registerStatus(PoisonStatus())
@JvmField
val POISON_BADLY = registerStatus(PoisonBadlyStatus())
@JvmField
val PARALYSIS = registerStatus(ParalysisStatus())
@JvmField
val SLEEP = registerStatus(SleepStatus())
@JvmField
val FROZEN = registerStatus(FrozenStatus())
@JvmField
val BURN = registerStatus(BurnStatus())
@JvmField
val ATTRACT = registerStatus(AttractStatus())
@JvmField
val CONFUSE = registerStatus(ConfuseStatus())
@JvmStatic
fun <T: Status> registerStatus(status: T) : T {
if (status is PersistentStatus) {
persistentStatuses.add(status)
@@ -56,7 +63,10 @@ object Statuses {
return status
}
@JvmStatic
fun getStatus(name: ResourceLocation) = allStatuses.find { status -> status.name == name }
@JvmStatic
fun getStatus(showdownName: String) = allStatuses.find { it.showdownName == showdownName }
@JvmStatic
fun getPersistentStatuses() = persistentStatuses
}
@@ -17,6 +17,7 @@ import com.cobblemon.mod.common.api.reactive.pipes.StopAfterTransform
import com.cobblemon.mod.common.api.reactive.pipes.TakeFirstTransform
import java.lang.Thread.sleep
import java.util.concurrent.CompletableFuture
import java.util.function.Consumer
/**
* An object that emits values of the generic type. This can be subscribed to and unsubscribed from, as well as
@@ -30,6 +31,8 @@ import java.util.concurrent.CompletableFuture
*/
interface Observable<T> {
fun subscribe(priority: Priority = Priority.NORMAL, handler: (T) -> Unit): ObservableSubscription<T>
fun subscribe(handler: Consumer<T>): ObservableSubscription<T> = subscribe(Priority.NORMAL) { handler.accept(it) }
fun subscribe(priority: Priority, handler: Consumer<T>): ObservableSubscription<T> = subscribe(priority) { handler.accept(it) }
fun unsubscribe(subscription: ObservableSubscription<T>)
// This isn't pretty, ik
@@ -8,6 +8,9 @@
package com.cobblemon.mod.common.api.riding.behaviour
import com.bedrockk.molang.runtime.value.DoubleValue
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMoLangValue
import com.cobblemon.mod.common.api.molang.ObjectValue
import com.cobblemon.mod.common.api.riding.RidingStyle
import com.cobblemon.mod.common.api.riding.sound.RideSoundSettingsList
import com.cobblemon.mod.common.entity.PoseType
@@ -18,7 +21,6 @@ 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.abs
/**
* Represents the behaviour of a Pokemon when being ridden.
@@ -76,8 +78,6 @@ interface RidingBehaviour<Settings : RidingBehaviourSettings, State : RidingBeha
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
@@ -116,6 +116,18 @@ interface RidingBehaviour<Settings : RidingBehaviourSettings, State : RidingBeha
*/
fun mouseModifiesDriverRotation(settings: Settings, state: State, vehicle: PokemonEntity): Pair<Boolean, Boolean> = Pair(false, false)
/**
* Used in MoLang functions for querying states for animations or other magical MoLang effects.
*/
fun asMoLangValue(settings: Settings, state: State, vehicle: PokemonEntity): ObjectValue<RidingBehaviour<Settings, State>> {
val value = ObjectValue(
this
)
value.functions.put("ride_velocity") { state.rideVelocity.get().asMoLangValue() }
value.functions.put("stamina") { DoubleValue(state.stamina.get()) }
return value
}
/**
* Internal helpers to help behaviour specific calculations
*/
@@ -53,7 +53,6 @@ open class RidingBehaviourState {
rideVelocity.set(buffer.readVec3(), true)
stamina.set(buffer.readFloat(), true)
}
}
fun <T> ridingState(value: T, side: Side) = SidedRidingState(value, side)
@@ -39,13 +39,15 @@ object RidingBehaviours {
register(CompositeBehaviour.KEY, CompositeBehaviour())
}
@JvmStatic
fun register(key: ResourceLocation, behaviour: RidingBehaviour<out RidingBehaviourSettings, out RidingBehaviourState>) {
if (behaviours.contains(key)) error("Behaviour already registered to key $key")
behaviours[key] = behaviour as RidingBehaviour<RidingBehaviourSettings, RidingBehaviourState>
}
@JvmStatic
fun get(key: ResourceLocation): RidingBehaviour<RidingBehaviourSettings, RidingBehaviourState> {
if (!behaviours.contains(key)) error("Behaviour not registered to key $key")
return behaviours[key]!!
}
}
}
@@ -54,7 +54,7 @@ class RidingController(
// If transitioning to air then give an upward boost
if (newTransition == RidingStyle.AIR && context?.style != RidingStyle.AIR && context?.state != null) {
val currVel = context!!.state.rideVelocity.get()
context!!.state.rideVelocity.set(Vec3(currVel.x, max(0.4, currVel.y), currVel.z))
context!!.state.rideVelocity.set(Vec3(currVel.x, max(0.1, currVel.y), currVel.z))
}
val behaviourSettings = entity.pokemon.riding.behaviours?.get(newTransition)
if (newTransition != context?.style) {
@@ -118,8 +118,9 @@ class RidingController(
private fun canTransitionToLand(): Boolean {
val hasLandController = entity.pokemon.riding.behaviours?.get(RidingStyle.LAND) != null
if (hasLandController && (entity.isInLiquid || entity.isUnderWater)) return false
if (!hasLandController && (entity.isEyeInFluid(FluidTags.WATER) || entity.isEyeInFluid(FluidTags.LAVA))) return false
if (!hasLandController) return false
if ((entity.isUnderWater)) return false
if ((entity.isEyeInFluid(FluidTags.WATER) || entity.isEyeInFluid(FluidTags.LAVA))) return false
return entity.onGround()
}
@@ -10,9 +10,10 @@ package com.cobblemon.mod.common.api.riding.behaviour.types.air
import com.bedrockk.molang.Expression
import com.bedrockk.molang.runtime.MoLangMath.lerp
import com.cobblemon.mod.common.Cobblemon
import com.bedrockk.molang.runtime.value.DoubleValue
import com.cobblemon.mod.common.CobblemonRideSettings
import com.cobblemon.mod.common.OrientationControllable
import com.cobblemon.mod.common.api.molang.ObjectValue
import com.cobblemon.mod.common.api.orientation.OrientationController
import com.cobblemon.mod.common.api.riding.RidingStyle
import com.cobblemon.mod.common.api.riding.behaviour.*
@@ -33,7 +34,6 @@ 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 net.minecraft.world.phys.shapes.Shapes
import org.joml.Vector3f
import kotlin.math.*
@@ -55,7 +55,7 @@ class BirdBehaviour : RidingBehaviour<BirdSettings, BirdState> {
get() = CobblemonRideSettings.bird
override fun isActive(settings: BirdSettings, state: BirdState, vehicle: PokemonEntity): Boolean {
return !(vehicle.isInWater || vehicle.isUnderWater)
return !(vehicle.isUnderWater)
}
override fun pose(settings: BirdSettings, state: BirdState, vehicle: PokemonEntity): PoseType {
@@ -550,18 +550,6 @@ class BirdBehaviour : RidingBehaviour<BirdSettings, BirdState> {
return false
}
override fun useRidingAltPose(
settings: BirdSettings,
state: BirdState,
vehicle: PokemonEntity,
driver: Player
): ResourceLocation {
if (state.gliding.get()) {
return cobblemonResource("gliding")
}
return cobblemonResource("no_pose")
}
override fun inertia(settings: BirdSettings, state: BirdState, vehicle: PokemonEntity): Double {
return 0.5
}
@@ -591,7 +579,7 @@ class BirdBehaviour : RidingBehaviour<BirdSettings, BirdState> {
state: BirdState,
vehicle: PokemonEntity
): Boolean {
return true
return false
}
override fun damageOnCollision(
@@ -614,6 +602,17 @@ class BirdBehaviour : RidingBehaviour<BirdSettings, BirdState> {
}
override fun createDefaultState(settings: BirdSettings) = BirdState()
override fun asMoLangValue(
settings: BirdSettings,
state: BirdState,
vehicle: PokemonEntity
): ObjectValue<RidingBehaviour<BirdSettings, BirdState>> {
val value = super.asMoLangValue(settings, state, vehicle)
value.functions.put("gliding") { DoubleValue(state.gliding.get()) }
value.functions.put("last_glide") { DoubleValue(state.lastGlide.get()) }
return value
}
}
class BirdSettings : RidingBehaviourSettings {
@@ -9,7 +9,6 @@
package com.cobblemon.mod.common.api.riding.behaviour.types.air
import com.bedrockk.molang.Expression
import com.cobblemon.mod.common.Cobblemon
import com.cobblemon.mod.common.CobblemonRideSettings
import com.cobblemon.mod.common.OrientationControllable
import com.cobblemon.mod.common.api.riding.RidingStyle
@@ -24,7 +23,6 @@ import com.cobblemon.mod.common.entity.PoseType
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import com.cobblemon.mod.common.util.*
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
@@ -155,15 +153,6 @@ class GliderBehaviour : RidingBehaviour<GliderSettings, RidingBehaviourState> {
return false
}
override fun useRidingAltPose(
settings: GliderSettings,
state: RidingBehaviourState,
vehicle: PokemonEntity,
driver: Player
): ResourceLocation {
return cobblemonResource("no_pose")
}
override fun inertia(settings: GliderSettings, state: RidingBehaviourState, vehicle: PokemonEntity): Double {
return 0.5
}
@@ -33,7 +33,6 @@ import kotlin.math.abs
import kotlin.math.pow
import kotlin.math.sin
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
@@ -246,15 +245,6 @@ class HelicopterBehaviour : RidingBehaviour<HelicopterSettings, RidingBehaviourS
return true
}
override fun useRidingAltPose(
settings: HelicopterSettings,
state: RidingBehaviourState,
vehicle: PokemonEntity,
driver: Player
): ResourceLocation {
return cobblemonResource("no_pose")
}
override fun inertia(settings: HelicopterSettings, state: RidingBehaviourState, vehicle: PokemonEntity): Double {
return 0.1
}
@@ -9,7 +9,9 @@
package com.cobblemon.mod.common.api.riding.behaviour.types.air
import com.bedrockk.molang.Expression
import com.bedrockk.molang.runtime.value.DoubleValue
import com.cobblemon.mod.common.CobblemonRideSettings
import com.cobblemon.mod.common.api.molang.ObjectValue
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
@@ -23,7 +25,6 @@ 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.Mth
import net.minecraft.util.SmoothDouble
import net.minecraft.world.entity.LivingEntity
@@ -32,7 +33,6 @@ import net.minecraft.world.level.ClipContext
import net.minecraft.world.phys.HitResult
import net.minecraft.world.phys.Vec2
import net.minecraft.world.phys.Vec3
import net.minecraft.world.phys.shapes.Shapes
import org.joml.Matrix3f
import kotlin.math.*
@@ -59,18 +59,8 @@ class HoverBehaviour : RidingBehaviour<HoverSettings, HoverState> {
state: HoverState,
vehicle: PokemonEntity
): Boolean {
return Shapes.create(vehicle.boundingBox).blockPositionsAsListRounded().any {
//Need to check other fluids
if (vehicle.isInWater || vehicle.isUnderWater) {
return@any false
}
//This might not actually work, depending on what the yPos actually is. yPos of the middle of the entity? the feet?
if (it.y.toDouble() == (vehicle.position().y)) {
val blockState = vehicle.level().getBlockState(it.below())
return@any !blockState.isAir && blockState.fluidState.isEmpty
}
true
}
// Hover mounts should be able to go just about anywhere but underwater
return !vehicle.isUnderWater
}
override fun pose(
@@ -166,6 +156,7 @@ class HoverBehaviour : RidingBehaviour<HoverSettings, HoverState> {
driver: LivingEntity
): Vec2 {
val turnAmount = calcRotAmount(settings, state, vehicle, driver)
state.rideVelocity.set( state.rideVelocity.get().yRot(turnAmount.toRadians()))
return Vec2(driver.xRot, vehicle.yRot + turnAmount )
}
@@ -207,6 +198,7 @@ class HoverBehaviour : RidingBehaviour<HoverSettings, HoverState> {
input: Vec3
): Vec3 {
val retVel = calculateRideSpaceVel(settings, state, vehicle, driver)
state.rideVelocity.set(retVel)
return retVel
}
@@ -228,8 +220,8 @@ class HoverBehaviour : RidingBehaviour<HoverSettings, HoverState> {
}
// align the velocity vector to be in local vehicle space
val yawAligned = Matrix3f().rotateY(vehicle.yRot.toRadians())
newVelocity = (newVelocity.toVector3f().mul(yawAligned)).toVec3d()
// val yawAligned = Matrix3f().rotateY(vehicle.yRot.toRadians())
// newVelocity = (newVelocity.toVector3f().mul(yawAligned)).toVec3d()
// Vertical movement based on driver input.
val vertInput = when {
@@ -275,9 +267,6 @@ class HoverBehaviour : RidingBehaviour<HoverSettings, HoverState> {
// Check to see if this new velocity will exceed top speed and if it will then cap it
newVelocity = if (newVelocity.length() > topSpeed) newVelocity.normalize().scale(topSpeed) else newVelocity
val revertYawAligned = Matrix3f().rotateY(-vehicle.yRot.toRadians())
state.rideVelocity.set((newVelocity.toVector3f().mul(revertYawAligned)).toVec3d())
return newVelocity
}
@@ -361,15 +350,6 @@ class HoverBehaviour : RidingBehaviour<HoverSettings, HoverState> {
return false
}
override fun useRidingAltPose(
settings: HoverSettings,
state: HoverState,
vehicle: PokemonEntity,
driver: Player
): ResourceLocation {
return cobblemonResource("no_pose")
}
override fun inertia(
settings: HoverSettings,
state: HoverState,
@@ -415,7 +395,7 @@ class HoverBehaviour : RidingBehaviour<HoverSettings, HoverState> {
state: HoverState,
vehicle: PokemonEntity
): Boolean {
return false
return true
}
override fun getRideSounds(
@@ -427,6 +407,18 @@ class HoverBehaviour : RidingBehaviour<HoverSettings, HoverState> {
}
override fun createDefaultState(settings: HoverSettings) = HoverState()
override fun asMoLangValue(
settings: HoverSettings,
state: HoverState,
vehicle: PokemonEntity
): ObjectValue<RidingBehaviour<HoverSettings, HoverState>> {
val value = super.asMoLangValue(settings, state, vehicle)
value.functions.put("boosting") { DoubleValue(state.isBoosting.get()) }
value.functions.put("boost_ticks") { DoubleValue(state.boostTicks.get()) }
value.functions.put("too_high") { DoubleValue(state.tooHigh.get()) }
return value
}
}
class HoverSettings : RidingBehaviourSettings {
@@ -10,9 +10,10 @@ package com.cobblemon.mod.common.api.riding.behaviour.types.air
import com.bedrockk.molang.Expression
import com.bedrockk.molang.runtime.MoLangMath.lerp
import com.cobblemon.mod.common.Cobblemon
import com.bedrockk.molang.runtime.value.DoubleValue
import com.cobblemon.mod.common.CobblemonRideSettings
import com.cobblemon.mod.common.OrientationControllable
import com.cobblemon.mod.common.api.molang.ObjectValue
import com.cobblemon.mod.common.api.riding.RidingStyle
import com.cobblemon.mod.common.api.riding.behaviour.RidingBehaviour
import com.cobblemon.mod.common.api.riding.behaviour.RidingBehaviourSettings
@@ -40,7 +41,6 @@ import kotlin.math.min
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
@@ -72,7 +72,6 @@ class JetBehaviour : RidingBehaviour<JetSettings, JetState> {
if (vehicle.isInWater || vehicle.isUnderWater) {
return@any false
}
//This might not actually work, depending on what the yPos actually is. yPos of the middle of the entity? the feet?
if (it.y.toDouble() == (vehicle.position().y)) {
val blockState = vehicle.level().getBlockState(it.below())
return@any !(!blockState.isAir && blockState.fluidState.isEmpty)
@@ -168,8 +167,8 @@ class JetBehaviour : RidingBehaviour<JetSettings, JetState> {
calculateRideSpaceVel(settings, state, vehicle, driver)
// The downward force used to encourage players to stop flying upside down.
val maxDownwardForceTickCnt = 20.0
val extraDownwardForce = if(state.stamina.get() == 0.0f) -0.3 * (state.noStamTickCnt.get() / maxDownwardForceTickCnt).coerceIn(0.0, 1.0) else 0.0 // 6 blocks a second downward
val penaltyDeccel = vehicle.runtime.resolveDouble(settings.maxDownwardForceSeconds ?: globalJet.maxDownwardForceSeconds!!).toFloat() * 20.0f
val extraDownwardForce = if(state.stamina.get() == 0.0f) -0.3 * (state.noStamTickCnt.get() / penaltyDeccel).coerceIn(0.0f, 1.0f) else 0.0 // 6 blocks a second downward
// Convert the local velocity vector into a world vector
val localVelVec = Vector3f(
@@ -178,7 +177,10 @@ class JetBehaviour : RidingBehaviour<JetSettings, JetState> {
state.rideVelocity.get().z.toFloat() * -1.0f // Flip the z axis to make this left handed? orr.. right handed? idk, flip it though
)
var worldVelVec = localVelVec.mul(controller.orientation).toVec3d().yRot(vehicle.yRot.toRadians()) // Unrotate preemptively as this vector gets rotate later down the line in MC logic.
worldVelVec = worldVelVec.add(0.0, extraDownwardForce, 0.0) // Add the stamina depletion force to bring the ride down.
worldVelVec = Vec3(
worldVelVec.x,
worldVelVec.y * (1 - (state.noStamTickCnt.get() / penaltyDeccel).coerceIn(0.0f, 1.0f)), // Dampen the upwards movement depending on stamina depletion time
worldVelVec.z).add(0.0, extraDownwardForce, 0.0) // Add the stamina depletion force to bring the ride down.
return worldVelVec
}
@@ -198,6 +200,8 @@ class JetBehaviour : RidingBehaviour<JetSettings, JetState> {
val minSpeed = topSpeed * vehicle.runtime.resolveDouble(settings.minSpeedFactor ?: globalJet.minSpeedFactor!!)
val speed = state.rideVelocity.get().z
val boostMult = vehicle.runtime.resolveDouble(settings.jumpExpr ?: globalJet.jumpExpr!!)
val maxNoStamickCnt = vehicle.runtime.resolveDouble(settings.maxDownwardForceSeconds ?: globalJet.maxDownwardForceSeconds!!).toFloat() * 20.0f
val boostTopSpeed = topSpeed * boostMult
val boostAccel = accel * boostMult
@@ -205,11 +209,15 @@ class JetBehaviour : RidingBehaviour<JetSettings, JetState> {
//speed up and slow down based on input
if (state.stamina.get() == 0.0f) {
// Decelerate currently always a constant half of max acceleration.
// Increase penalty deccel when stamina has been depleted for a while.
val penaltyDeccel = deccel * (state.noStamTickCnt.get() / maxNoStamickCnt).coerceIn(0.0f, 1.0f)
val minPenaltySpeed = minSpeed
state.rideVelocity.set(
Vec3(
state.rideVelocity.get().x,
state.rideVelocity.get().y,
max(state.rideVelocity.get().z - (deccel * 1.3), 0.3 * 0.5)
max(state.rideVelocity.get().z - (penaltyDeccel), minPenaltySpeed)
)
)
}
@@ -321,7 +329,7 @@ class JetBehaviour : RidingBehaviour<JetSettings, JetState> {
// Have accumulated input begin decay when no input detected
if (abs(mouseX) == 0.0) {
// Have decay on roll be much stronger.
state.currMouseXForce.set(lerp(state.currMouseXForce.get(), 0.0, 0.08))
state.currMouseXForce.set(lerp(state.currMouseXForce.get(), 0.0, 0.02))
}
if (mouseY == 0.0) {
state.currMouseYForce.set(lerp(state.currMouseYForce.get(), 0.0, 0.02))
@@ -374,9 +382,9 @@ class JetBehaviour : RidingBehaviour<JetSettings, JetState> {
vehicle: PokemonEntity,
driver: Player
): Float {
val maxDownwardForceTickCnt = 20.0f
val penaltyDeccel = vehicle.runtime.resolveDouble(settings.maxDownwardForceSeconds ?: globalJet.maxDownwardForceSeconds!!).toFloat() * 20.0f
return when {
state.noStamTickCnt.get() != 0 -> 1f - 0.2f*(state.noStamTickCnt.get() / maxDownwardForceTickCnt).coerceIn(0.0f,1.0f)
state.noStamTickCnt.get() != 0 -> 1f - 0.2f*(state.noStamTickCnt.get() / penaltyDeccel).coerceIn(0.0f,1.0f)
state.boosting.get() -> 1.2f
else -> 1.0f
}
@@ -386,15 +394,6 @@ class JetBehaviour : RidingBehaviour<JetSettings, JetState> {
return true
}
override fun useRidingAltPose(
settings: JetSettings,
state: JetState,
vehicle: PokemonEntity,
driver: Player
): ResourceLocation {
return cobblemonResource("no_pose")
}
override fun inertia(settings: JetSettings, state: JetState, vehicle: PokemonEntity): Double {
return 1.0
}
@@ -446,6 +445,17 @@ class JetBehaviour : RidingBehaviour<JetSettings, JetState> {
val impactSpeed = impactVec.horizontalDistance().toFloat() * 10f
return vehicle.causeFallDamage(impactSpeed, 1f, vehicle.damageSources().flyIntoWall())
}
override fun asMoLangValue(
settings: JetSettings,
state: JetState,
vehicle: PokemonEntity
): ObjectValue<RidingBehaviour<JetSettings, JetState>> {
val value = super.asMoLangValue(settings, state, vehicle)
value.functions.put("boosting") { DoubleValue(state.boosting.get()) }
value.functions.put("can_speed_burst") { DoubleValue(state.canSpeedBurst.get()) }
return value
}
}
class JetSettings : RidingBehaviourSettings {
@@ -486,6 +496,9 @@ class JetSettings : RidingBehaviourSettings {
var staminaExpr: Expression? = null
private set
var maxDownwardForceSeconds: Expression? = null
private set
var rideSounds: RideSoundSettingsList = RideSoundSettingsList()
override fun encode(buffer: RegistryFriendlyByteBuf) {
@@ -501,6 +514,7 @@ class JetSettings : RidingBehaviourSettings {
buffer.writeNullableExpression(speedExpr)
buffer.writeNullableExpression(accelerationExpr)
buffer.writeNullableExpression(staminaExpr)
buffer.writeNullableExpression(maxDownwardForceSeconds)
}
override fun decode(buffer: RegistryFriendlyByteBuf) {
@@ -516,6 +530,7 @@ class JetSettings : RidingBehaviourSettings {
speedExpr = buffer.readNullableExpression()
accelerationExpr = buffer.readNullableExpression()
staminaExpr = buffer.readNullableExpression()
maxDownwardForceSeconds = buffer.readNullableExpression()
}
}
@@ -10,7 +10,9 @@ package com.cobblemon.mod.common.api.riding.behaviour.types.air
import com.bedrockk.molang.Expression
import com.bedrockk.molang.runtime.MoLangMath.lerp
import com.bedrockk.molang.runtime.value.DoubleValue
import com.cobblemon.mod.common.CobblemonRideSettings
import com.cobblemon.mod.common.api.molang.ObjectValue
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
@@ -24,14 +26,12 @@ 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.Mth
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 net.minecraft.world.phys.shapes.Shapes
import org.joml.Matrix3f
import kotlin.math.*
@@ -58,18 +58,7 @@ class RocketBehaviour : RidingBehaviour<RocketSettings, RocketState> {
state: RocketState,
vehicle: PokemonEntity
): Boolean {
return Shapes.create(vehicle.boundingBox).blockPositionsAsListRounded().any {
//Need to check other fluids
if (vehicle.isInWater || vehicle.isUnderWater) {
return@any false
}
//This might not actually work, depending on what the yPos actually is. yPos of the middle of the entity? the feet?
if (it.y.toDouble() == (vehicle.position().y)) {
val blockState = vehicle.level().getBlockState(it.below())
return@any !blockState.isAir && blockState.fluidState.isEmpty
}
true
}
return !((vehicle.isInWater || vehicle.isUnderWater) || vehicle.onGround())
}
override fun pose(
@@ -422,15 +411,6 @@ class RocketBehaviour : RidingBehaviour<RocketSettings, RocketState> {
return false
}
override fun useRidingAltPose(
settings: RocketSettings,
state: RocketState,
vehicle: PokemonEntity,
driver: Player
): ResourceLocation {
return cobblemonResource("no_pose")
}
override fun inertia(
settings: RocketSettings,
state: RocketState,
@@ -476,7 +456,7 @@ class RocketBehaviour : RidingBehaviour<RocketSettings, RocketState> {
state: RocketState,
vehicle: PokemonEntity
): Boolean {
return false
return true
}
@@ -500,6 +480,17 @@ class RocketBehaviour : RidingBehaviour<RocketSettings, RocketState> {
}
override fun createDefaultState(settings: RocketSettings) = RocketState()
override fun asMoLangValue(
settings: RocketSettings,
state: RocketState,
vehicle: PokemonEntity
): ObjectValue<RidingBehaviour<RocketSettings, RocketState>> {
val value = super.asMoLangValue(settings, state, vehicle)
value.functions.put("boosting") { DoubleValue(state.boosting.get()) }
value.functions.put("can_speed_burst") { DoubleValue(state.canSpeedBurst.get()) }
return value
}
}
class RocketSettings : RidingBehaviourSettings {
@@ -170,17 +170,6 @@ class CompositeBehaviour : RidingBehaviour<CompositeSettings, CompositeState> {
}
}
override fun useRidingAltPose(
settings: CompositeSettings,
state: CompositeState,
vehicle: PokemonEntity,
driver: Player
): ResourceLocation {
return chooseBehaviour(settings, state) { behaviour, behaviourSettings, behaviourState ->
behaviour.useRidingAltPose(behaviourSettings, behaviourState, vehicle, driver)
}
}
override fun useAngVelSmoothing(
settings: CompositeSettings,
state: CompositeState,
@@ -9,7 +9,9 @@
package com.cobblemon.mod.common.api.riding.behaviour.types.land
import com.bedrockk.molang.Expression
import com.bedrockk.molang.runtime.value.DoubleValue
import com.cobblemon.mod.common.CobblemonRideSettings
import com.cobblemon.mod.common.api.molang.ObjectValue
import com.cobblemon.mod.common.api.riding.RidingStyle
import com.cobblemon.mod.common.api.riding.behaviour.RidingBehaviour
import com.cobblemon.mod.common.api.riding.behaviour.RidingBehaviourSettings
@@ -41,7 +43,6 @@ import kotlin.math.sqrt
import net.minecraft.core.Direction
import net.minecraft.network.FriendlyByteBuf
import net.minecraft.network.RegistryFriendlyByteBuf
import net.minecraft.resources.ResourceLocation
import net.minecraft.util.Mth
import net.minecraft.util.SmoothDouble
import net.minecraft.world.entity.LivingEntity
@@ -471,19 +472,6 @@ class HorseBehaviour : RidingBehaviour<HorseSettings, HorseState> {
return false
}
override fun useRidingAltPose(
settings: HorseSettings,
state: HorseState,
vehicle: PokemonEntity,
driver: Player
): ResourceLocation {
when {
state.inAir.get() -> return cobblemonResource("in_air")
state.sprinting.get() -> return cobblemonResource("sprinting")
}
return cobblemonResource("no_pose")
}
override fun inertia(
settings: HorseSettings,
state: HorseState,
@@ -541,6 +529,19 @@ class HorseBehaviour : RidingBehaviour<HorseSettings, HorseState> {
}
override fun createDefaultState(settings: HorseSettings) = HorseState()
override fun asMoLangValue(
settings: HorseSettings,
state: HorseState,
vehicle: PokemonEntity
): ObjectValue<RidingBehaviour<HorseSettings, HorseState>> {
val canJump = vehicle.runtime.resolveBoolean(settings.canJump ?: globalHorse.canJump!!)
val value = super.asMoLangValue(settings, state, vehicle)
value.functions.put("sprinting") { DoubleValue(state.sprinting.get()) }
value.functions.put("walking") { DoubleValue(state.walking.get()) }
value.functions.put("in_air") { DoubleValue(state.inAir.get() || (state.rideVelocity.get().y >= 0.0 && (vehicle.controllingPassenger as? Player)?.jumping == true && canJump) || (state.rideVelocity.get().y > 0.0)) }
return value
}
}
class HorseSettings : RidingBehaviourSettings {
@@ -10,8 +10,10 @@ package com.cobblemon.mod.common.api.riding.behaviour.types.land
import com.bedrockk.molang.Expression
import com.bedrockk.molang.runtime.MoLangMath.lerp
import com.bedrockk.molang.runtime.value.DoubleValue
import com.cobblemon.mod.common.CobblemonRideSettings
import com.cobblemon.mod.common.OrientationControllable
import com.cobblemon.mod.common.api.molang.ObjectValue
import com.cobblemon.mod.common.api.riding.RidingStyle
import com.cobblemon.mod.common.api.riding.behaviour.RidingBehaviour
import com.cobblemon.mod.common.api.riding.behaviour.RidingBehaviourSettings
@@ -43,7 +45,6 @@ import kotlin.math.sign
import net.minecraft.core.Direction
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
@@ -394,18 +395,6 @@ class MinekartBehaviour : RidingBehaviour<MinekartSettings, MinekartState> {
return false
}
override fun useRidingAltPose(
settings: MinekartSettings,
state: MinekartState,
vehicle: PokemonEntity,
driver: Player
): ResourceLocation {
when {
state.drifting.get() -> return cobblemonResource("drifting")
}
return cobblemonResource("no_pose")
}
override fun inertia(settings: MinekartSettings, state: MinekartState, vehicle: PokemonEntity): Double {
return 1.0
}
@@ -455,6 +444,19 @@ class MinekartBehaviour : RidingBehaviour<MinekartSettings, MinekartState> {
}
override fun createDefaultState(settings: MinekartSettings) = MinekartState()
override fun asMoLangValue(
settings: MinekartSettings,
state: MinekartState,
vehicle: PokemonEntity
): ObjectValue<RidingBehaviour<MinekartSettings, MinekartState>> {
val value = super.asMoLangValue(settings, state, vehicle)
value.functions.put("drifiting") { DoubleValue(state.drifting.get()) }
value.functions.put("clockwise_drift") { DoubleValue(state.clockwiseDrift.get()) }
value.functions.put("boosting") { DoubleValue(state.boost.get()) }
value.functions.put("in_air") { DoubleValue(state.inAir.get()) }
return value
}
}
class MinekartSettings : RidingBehaviourSettings {
@@ -10,8 +10,10 @@ package com.cobblemon.mod.common.api.riding.behaviour.types.land
import com.bedrockk.molang.Expression
import com.bedrockk.molang.runtime.MoLangMath.lerp
import com.bedrockk.molang.runtime.value.DoubleValue
import com.cobblemon.mod.common.CobblemonRideSettings
import com.cobblemon.mod.common.OrientationControllable
import com.cobblemon.mod.common.api.molang.ObjectValue
import com.cobblemon.mod.common.api.riding.RidingStyle
import com.cobblemon.mod.common.api.riding.behaviour.RidingBehaviour
import com.cobblemon.mod.common.api.riding.behaviour.RidingBehaviourSettings
@@ -42,7 +44,6 @@ import kotlin.math.sign
import net.minecraft.core.Direction
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
@@ -359,19 +360,6 @@ class VehicleBehaviour : RidingBehaviour<VehicleSettings, VehicleState> {
return false
}
override fun useRidingAltPose(
settings: VehicleSettings,
state: VehicleState,
vehicle: PokemonEntity,
driver: Player
): ResourceLocation {
when {
state.poweredDrifting.get() -> return cobblemonResource("powered_drifting")
state.drifting.get() -> return cobblemonResource("drifting")
}
return cobblemonResource("no_pose")
}
override fun inertia(settings: VehicleSettings, state: VehicleState, vehicle: PokemonEntity): Double {
return 1.0
}
@@ -421,6 +409,17 @@ class VehicleBehaviour : RidingBehaviour<VehicleSettings, VehicleState> {
}
override fun createDefaultState(settings: VehicleSettings) = VehicleState()
override fun asMoLangValue(
settings: VehicleSettings,
state: VehicleState,
vehicle: PokemonEntity
): ObjectValue<RidingBehaviour<VehicleSettings, VehicleState>> {
val value = super.asMoLangValue(settings, state, vehicle)
value.functions.put("drifting") { DoubleValue(state.drifting.get()) }
value.functions.put("powered_drifting") { DoubleValue(state.poweredDrifting.get()) }
value.functions.put("in_air") { DoubleValue(state.inAir.get()) }
return value
}
}
class VehicleSettings : RidingBehaviourSettings {
@@ -9,8 +9,10 @@
package com.cobblemon.mod.common.api.riding.behaviour.types.liquid
import com.bedrockk.molang.Expression
import com.bedrockk.molang.runtime.value.DoubleValue
import com.cobblemon.mod.common.CobblemonRideSettings
import com.cobblemon.mod.common.OrientationControllable
import com.cobblemon.mod.common.api.molang.ObjectValue
import com.cobblemon.mod.common.api.riding.RidingStyle
import com.cobblemon.mod.common.api.riding.behaviour.RidingBehaviour
import com.cobblemon.mod.common.api.riding.behaviour.RidingBehaviourSettings
@@ -37,7 +39,6 @@ import kotlin.math.max
import kotlin.math.min
import net.minecraft.core.BlockPos
import net.minecraft.network.RegistryFriendlyByteBuf
import net.minecraft.resources.ResourceLocation
import net.minecraft.util.Mth
import net.minecraft.util.SmoothDouble
import net.minecraft.world.entity.LivingEntity
@@ -337,22 +338,6 @@ class BoatBehaviour : RidingBehaviour<BoatSettings, BoatState> {
return false
}
override fun useRidingAltPose(
settings: BoatSettings,
state: BoatState,
vehicle: PokemonEntity,
driver: Player
): ResourceLocation {
val isInWater = Shapes.create(vehicle.boundingBox).blockPositionsAsListRounded().any {
if (vehicle.isInWater || vehicle.isUnderWater) {
return@any true
}
val blockState = vehicle.level().getBlockState(it)
return@any !blockState.fluidState.isEmpty
}
return if (!isInWater) cobblemonResource("in_air") else cobblemonResource("no_pose")
}
override fun inertia(settings: BoatSettings, state: BoatState, vehicle: PokemonEntity): Double {
return 0.5
}
@@ -397,6 +382,25 @@ class BoatBehaviour : RidingBehaviour<BoatSettings, BoatState> {
override fun createDefaultState(settings: BoatSettings) = BoatState()
override fun asMoLangValue(
settings: BoatSettings,
state: BoatState,
vehicle: PokemonEntity
): ObjectValue<RidingBehaviour<BoatSettings, BoatState>> {
val value = super.asMoLangValue(settings, state, vehicle)
value.functions.put("sprinting") { DoubleValue(state.isVehicleSprinting.get()) }
value.functions.put("in_air") {
val isInWater = Shapes.create(vehicle.boundingBox).blockPositionsAsListRounded().any {
if (vehicle.isInWater || vehicle.isUnderWater) {
return@any true
}
val blockState = vehicle.level().getBlockState(it)
return@any !blockState.fluidState.isEmpty
}
DoubleValue(!isInWater)
}
return value
}
}
class BoatSettings : RidingBehaviourSettings {
@@ -492,5 +496,4 @@ class BoatState : RidingBehaviourState() {
if (previous !is BoatState) return false
return super.shouldSync(previous)
}
}
@@ -8,8 +8,10 @@
package com.cobblemon.mod.common.api.riding.behaviour.types.liquid
import com.bedrockk.molang.runtime.value.DoubleValue
import com.cobblemon.mod.common.CobblemonRideSettings
import com.cobblemon.mod.common.OrientationControllable
import com.cobblemon.mod.common.api.molang.ObjectValue
import com.cobblemon.mod.common.api.riding.RidingStyle
import com.cobblemon.mod.common.api.riding.behaviour.RidingBehaviour
import com.cobblemon.mod.common.api.riding.behaviour.RidingBehaviourSettings
@@ -25,10 +27,8 @@ import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import com.cobblemon.mod.common.util.blockPositionsAsListRounded
import com.cobblemon.mod.common.util.cobblemonResource
import com.cobblemon.mod.common.util.readRidingStats
import com.cobblemon.mod.common.util.writeNullable
import com.cobblemon.mod.common.util.writeRidingStats
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
@@ -190,15 +190,6 @@ class BurstBehaviour : RidingBehaviour<BurstSettings, BurstState> {
return false
}
override fun useRidingAltPose(
settings: BurstSettings,
state: BurstState,
vehicle: PokemonEntity,
driver: Player
): ResourceLocation {
return cobblemonResource("no_pose")
}
override fun inertia(settings: BurstSettings, state: BurstState, vehicle: PokemonEntity): Double {
return 0.5
}
@@ -240,6 +231,16 @@ class BurstBehaviour : RidingBehaviour<BurstSettings, BurstState> {
}
override fun createDefaultState(settings: BurstSettings) = BurstState()
override fun asMoLangValue(
settings: BurstSettings,
state: BurstState,
vehicle: PokemonEntity
): ObjectValue<RidingBehaviour<BurstSettings, BurstState>> {
val value = super.asMoLangValue(settings, state, vehicle)
value.functions.put("dashing") { DoubleValue(state.dashing.get()) }
return value
}
}
class BurstSettings : RidingBehaviourSettings {
@@ -10,9 +10,10 @@ package com.cobblemon.mod.common.api.riding.behaviour.types.liquid
import com.bedrockk.molang.Expression
import com.bedrockk.molang.runtime.MoLangMath.lerp
import com.cobblemon.mod.common.Cobblemon
import com.bedrockk.molang.runtime.value.DoubleValue
import com.cobblemon.mod.common.CobblemonRideSettings
import com.cobblemon.mod.common.OrientationControllable
import com.cobblemon.mod.common.api.molang.ObjectValue
import com.cobblemon.mod.common.api.orientation.OrientationController
import com.cobblemon.mod.common.api.riding.RidingStyle
import com.cobblemon.mod.common.api.riding.behaviour.RidingBehaviour
@@ -27,8 +28,8 @@ import com.cobblemon.mod.common.api.riding.sound.RideSoundSettingsList
import com.cobblemon.mod.common.api.riding.stats.RidingStat
import com.cobblemon.mod.common.entity.PoseType
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import com.cobblemon.mod.common.util.blockPositionsAsListRounded
import com.cobblemon.mod.common.util.cobblemonResource
import com.cobblemon.mod.common.util.math.geometry.toDegrees
import com.cobblemon.mod.common.util.math.geometry.toRadians
import com.cobblemon.mod.common.util.readNullableExpression
import com.cobblemon.mod.common.util.readRidingStats
@@ -41,13 +42,14 @@ import kotlin.math.*
import net.minecraft.client.Minecraft
import net.minecraft.network.FriendlyByteBuf
import net.minecraft.network.RegistryFriendlyByteBuf
import net.minecraft.resources.ResourceLocation
import net.minecraft.util.Mth
import net.minecraft.util.SmoothDouble
import net.minecraft.world.entity.LivingEntity
import net.minecraft.world.entity.player.Player
import net.minecraft.world.level.block.state.BlockState
import net.minecraft.world.phys.Vec2
import net.minecraft.world.phys.Vec3
import net.minecraft.world.phys.shapes.Shapes
import org.joml.Vector3f
class DolphinBehaviour : RidingBehaviour<DolphinSettings, DolphinState> {
@@ -67,7 +69,20 @@ class DolphinBehaviour : RidingBehaviour<DolphinSettings, DolphinState> {
.with(PoseOption(PoseType.SWIM) { _, state, entity -> abs(state.rideVelocity.get().length()) > 0.05 })
override fun isActive(settings: DolphinSettings, state: DolphinState, vehicle: PokemonEntity): Boolean {
return vehicle.isInWater || !vehicle.onGround()
// If its in water then the dolphin should definitely be active
if (vehicle.isInWater || vehicle.isUnderWater) {
return true
}
val blockPosBelow = vehicle.blockPosition().below()
val blockState = vehicle.level().getBlockState(blockPosBelow)
// Check if the block below is solid AND not a fluid
val isOnSolidGround = !blockState.isAir && blockState.fluidState.isEmpty
// The dolphin is only INACTIVE if it is on solid ground.
// Therefore, it is ACTIVE if it is NOT on solid ground
return !isOnSolidGround
}
override fun pose(settings: DolphinSettings, state: DolphinState, vehicle: PokemonEntity): PoseType {
@@ -388,8 +403,8 @@ class DolphinBehaviour : RidingBehaviour<DolphinSettings, DolphinState> {
val hoverSpeed = 0.2
val pitchDamping = abs(cos(controller.pitch.toRadians())).pow(2) // Helper value used when wanting to discard the influence of another value at steep pitches
// Yaw locally when at or below hoverSpeed but not when pitched up or rolled over
val globalYaw = xInput * (1 - sqrt(RidingBehaviour.scaleToRange(currSpeed, 0.0, hoverSpeed))).coerceIn(0.0, 1.0)
// Yaw locally when at or below topSpeed but not when pitched up or rolled over
val globalYaw = xInput * (1 - sqrt(RidingBehaviour.scaleToRange(currSpeed, 0.0, topSpeed))).coerceIn(0.0, 1.0)
controller.rotateYaw(pitchDamping*globalYaw.toFloat())
controller.rotateRoll((1-pitchDamping)*globalYaw.toFloat())
@@ -476,15 +491,6 @@ class DolphinBehaviour : RidingBehaviour<DolphinSettings, DolphinState> {
return false
}
override fun useRidingAltPose(
settings: DolphinSettings,
state: DolphinState,
vehicle: PokemonEntity,
driver: Player
): ResourceLocation {
return cobblemonResource("no_pose")
}
override fun inertia(settings: DolphinSettings, state: DolphinState, vehicle: PokemonEntity): Double {
return if (!vehicle.isInWater && !vehicle.isUnderWater) 1.0 else 0.1
}
@@ -527,6 +533,16 @@ class DolphinBehaviour : RidingBehaviour<DolphinSettings, DolphinState> {
override fun createDefaultState(settings: DolphinSettings) = DolphinState()
override fun asMoLangValue(
settings: DolphinSettings,
state: DolphinState,
vehicle: PokemonEntity
): ObjectValue<RidingBehaviour<DolphinSettings, DolphinState>> {
val value = super.asMoLangValue(settings, state, vehicle)
value.functions.put("boosting") { DoubleValue(state.boosting.get()) }
value.functions.put("has_breached") { DoubleValue(state.hasBreached.get()) }
return value
}
}
class DolphinSettings : RidingBehaviourSettings {
@@ -10,8 +10,10 @@ package com.cobblemon.mod.common.api.riding.behaviour.types.liquid
import com.bedrockk.molang.Expression
import com.bedrockk.molang.runtime.MoLangMath.lerp
import com.bedrockk.molang.runtime.value.DoubleValue
import com.cobblemon.mod.common.CobblemonRideSettings
import com.cobblemon.mod.common.OrientationControllable
import com.cobblemon.mod.common.api.molang.ObjectValue
import com.cobblemon.mod.common.api.orientation.OrientationController
import com.cobblemon.mod.common.api.riding.RidingStyle
import com.cobblemon.mod.common.api.riding.behaviour.*
@@ -33,7 +35,6 @@ import com.cobblemon.mod.common.util.writeRidingStats
import net.minecraft.core.BlockPos
import net.minecraft.network.FriendlyByteBuf
import net.minecraft.network.RegistryFriendlyByteBuf
import net.minecraft.resources.ResourceLocation
import net.minecraft.tags.FluidTags
import net.minecraft.util.SmoothDouble
import net.minecraft.world.entity.LivingEntity
@@ -492,15 +493,6 @@ class SubmarineBehaviour : RidingBehaviour<SubmarineSettings, SubmarineState> {
return false
}
override fun useRidingAltPose(
settings: SubmarineSettings,
state: SubmarineState,
vehicle: PokemonEntity,
driver: Player
): ResourceLocation {
return cobblemonResource("no_pose")
}
override fun inertia(settings: SubmarineSettings, state: SubmarineState, vehicle: PokemonEntity): Double {
return if (!vehicle.isUnderWater) 1.0 else 0.1
}
@@ -547,6 +539,15 @@ class SubmarineBehaviour : RidingBehaviour<SubmarineSettings, SubmarineState> {
override fun createDefaultState(settings: SubmarineSettings) = SubmarineState()
override fun asMoLangValue(
settings: SubmarineSettings,
state: SubmarineState,
vehicle: PokemonEntity
): ObjectValue<RidingBehaviour<SubmarineSettings, SubmarineState>> {
val value = super.asMoLangValue(settings, state, vehicle)
value.functions.put("on_surface") { DoubleValue(state.onSurface.get()) }
return value
}
}
class SubmarineSettings : RidingBehaviourSettings {
@@ -64,6 +64,7 @@ object CobblemonScripts : DataRegistry {
player.sendPacket(ScriptRegistrySyncPacket(clientScripts.entries))
}
@JvmStatic
fun run(identifier: ResourceLocation, runtime: MoLangRuntime): MoValue? {
return scripts[identifier]?.resolve(runtime, runtime.contextOrEmpty)
}
@@ -46,6 +46,8 @@ class FishingSpawnCause(
) : SpawnCause(spawner, entity) {
companion object {
const val FISHED_ASPECT = "fished"
const val DROPS_REROLL_ASPECT = "drops_reroll"
fun shinyReroll(pokemonEntity: PokemonEntity, effect: SpawnBait.Effect) {
if (pokemonEntity.pokemon.shiny) return
@@ -60,6 +62,10 @@ class FishingSpawnCause(
}
}
fun saveDropsReroll(pokemonEntity: PokemonEntity, effect: SpawnBait.Effect) {
pokemonEntity.pokemon.forcedAspects += DROPS_REROLL_ASPECT
}
fun alterNatureAttempt(pokemonEntity: PokemonEntity, effect: SpawnBait.Effect) {
val baitStat = effect.subcategory?.let { it1 -> Stats.getStat(it1.path).identifier } ?: run {
LOGGER.warn("One of your nature baits is missing a subcategory and failed to effect a fished Pokemon")
@@ -71,7 +71,7 @@ open class FlatSelector : SpawningSelector<FlatSelector.SpawnablePositionSelecti
override fun removeSpawnDetails(shouldRemove: (SpawnDetail) -> Boolean) {
val toRemove = spawnToSpawnablePosition.entries.filter { shouldRemove(it.key) }
toRemove.forEach { spawnToSpawnablePosition.remove(it.key) }
percentSum -= toRemove.sumOf { it.key.percentage.toDouble() }.toFloat()
percentSum -= toRemove.sumOf { it.key.percentage.toDouble().takeIf { it > 0 } ?: 0.0 }.toFloat()
}
override fun removeSpawnablePositions(shouldRemove: (SpawnDetail, SpawnablePosition) -> Boolean) {
@@ -83,7 +83,7 @@ open class FlatSelector : SpawningSelector<FlatSelector.SpawnablePositionSelecti
toRemove.forEach { spawnToSpawnablePosition.remove(it.key) }
percentSum -= toRemove.sumOf { it.key.percentage.toDouble() }.toFloat()
percentSum -= toRemove.sumOf { it.key.percentage.toDouble().takeIf { it > 0 } ?: 0.0 }.toFloat()
}
}
@@ -72,7 +72,7 @@ open class FlatSpawnablePositionWeightedSelector : SpawningSelector<FlatSpawnabl
fun removeSpawnDetails(shouldRemove: (SpawnDetail) -> Boolean) {
val toRemove = spawnToSpawnablePosition.entries.filter { shouldRemove(it.key) }
toRemove.forEach { spawnToSpawnablePosition.remove(it.key) }
percentSum -= toRemove.sumOf { it.key.percentage.toDouble() }.toFloat()
percentSum -= toRemove.sumOf { it.key.percentage.toDouble().takeIf { it > 0 } ?: 0.0 }.toFloat()
}
fun removeSpawnablePositions(shouldRemove: (SpawnDetail, SpawnablePosition) -> Boolean) {
@@ -84,7 +84,7 @@ open class FlatSpawnablePositionWeightedSelector : SpawningSelector<FlatSpawnabl
toRemove.forEach { spawnToSpawnablePosition.remove(it.key) }
percentSum -= toRemove.sumOf { it.key.percentage.toDouble() }.toFloat()
percentSum -= toRemove.sumOf { it.key.percentage.toDouble().takeIf { it > 0 } ?: 0.0 }.toFloat()
}
}
@@ -165,6 +165,7 @@ open class FlatSpawnablePositionWeightedSelector : SpawningSelector<FlatSpawnabl
This means you don't understand how this option works.
""".trimIndent()
)
return null
}
@@ -0,0 +1,56 @@
/*
* 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.stats
import net.minecraft.resources.ResourceLocation
object CobblemonStats {
val stats = mutableMapOf<String, ResourceLocation>()
var CAPTURED: ResourceLocation = ResourceLocation.fromNamespaceAndPath("cobblemon", "captured") //makeCustomStat("captured", StatFormatter.DEFAULT)
val SHINIES_CAPTURED: ResourceLocation = ResourceLocation.fromNamespaceAndPath("cobblemon", "shinies_captured") //makeCustomStat("shinies_captured", StatFormatter.DEFAULT)
val RELEASED: ResourceLocation = ResourceLocation.fromNamespaceAndPath("cobblemon", "released") //makeCustomStat("released", StatFormatter.DEFAULT)
val EVOLVED: ResourceLocation = ResourceLocation.fromNamespaceAndPath("cobblemon", "evolved") //makeCustomStat("evolved", StatFormatter.DEFAULT)
val LEVEL_UP: ResourceLocation = ResourceLocation.fromNamespaceAndPath("cobblemon", "level_up") //makeCustomStat("level_up", StatFormatter.DEFAULT)
val BATTLES_WON: ResourceLocation = ResourceLocation.fromNamespaceAndPath("cobblemon", "battles_won") //makeCustomStat("battles_won", StatFormatter.DEFAULT)
val BATTLES_LOST: ResourceLocation = ResourceLocation.fromNamespaceAndPath("cobblemon", "battles_lost") //makeCustomStat("battles_lost", StatFormatter.DEFAULT)
val BATTLES_FLED: ResourceLocation = ResourceLocation.fromNamespaceAndPath("cobblemon", "battles_fled") //makeCustomStat("battles_fled", StatFormatter.DEFAULT)
val BATTLES_TOTAL: ResourceLocation = ResourceLocation.fromNamespaceAndPath("cobblemon", "battles_total") //makeCustomStat("battles_total", StatFormatter.DEFAULT)
val DEX_ENTRIES: ResourceLocation = ResourceLocation.fromNamespaceAndPath("cobblemon", "dex_entries") //makeCustomStat("dex_entries", StatFormatter.DEFAULT)
val EGGS_COLLECTED: ResourceLocation = ResourceLocation.fromNamespaceAndPath("cobblemon", "eggs_collected") //makeCustomStat("eggs_collected", StatFormatter.DEFAULT)
val EGGS_HATCHED: ResourceLocation = ResourceLocation.fromNamespaceAndPath("cobblemon", "eggs_hatched") //makeCustomStat("eggs_hatched", StatFormatter.DEFAULT)
val TRADED: ResourceLocation = ResourceLocation.fromNamespaceAndPath("cobblemon", "traded") //makeCustomStat("traded", StatFormatter.DEFAULT)
val FOSSILS_REVIVED: ResourceLocation = ResourceLocation.fromNamespaceAndPath("cobblemon", "fossils_revived") //makeCustomStat("fossils_revived", StatFormatter.DEFAULT)
val TIMES_RIDDEN: ResourceLocation = ResourceLocation.fromNamespaceAndPath("cobblemon", "times_ridden")
val ROD_CASTS: ResourceLocation = ResourceLocation.fromNamespaceAndPath("cobblemon", "rod_casts")
val REEL_INS: ResourceLocation = ResourceLocation.fromNamespaceAndPath("cobblemon", "reel_ins")
val POKEMON_INTERACTED_WITH: ResourceLocation = ResourceLocation.fromNamespaceAndPath("cobblemon", "pokemon_interacted_with") //makeCustomStat("pokemon_interacted_with", StatFormatter.DEFAULT)
//TODO block, stats (interact, gimmi), riding (styles?)
fun registerStats() {
stats["captured"] = CAPTURED
stats["shinies_captured"] = SHINIES_CAPTURED
stats["released"] = RELEASED
stats["evolved"] = EVOLVED
stats["level_up"] = LEVEL_UP
stats["battles_won"] = BATTLES_WON
stats["battles_lost"] = BATTLES_LOST
stats["battles_fled"] = BATTLES_FLED
stats["battles_total"] = BATTLES_TOTAL
stats["dex_entries"] = DEX_ENTRIES
stats["eggs_collected"] = EGGS_COLLECTED
stats["eggs_hatched"] = EGGS_HATCHED
stats["traded"] = TRADED
stats["fossils_revived"] = FOSSILS_REVIVED
stats["times_ridden"] = TIMES_RIDDEN
stats["rod_casts"] = ROD_CASTS
stats["reel_ins"] = REEL_INS
stats["pokemon_interacted_with"] = POKEMON_INTERACTED_WITH
}
}
@@ -10,5 +10,4 @@ package com.cobblemon.mod.common.api.storage.party
import com.cobblemon.mod.common.entity.npc.NPCEntity
class NPCPartyStore(val npc: NPCEntity) : PartyStore(npc.uuid) {
}
class NPCPartyStore(val npc: NPCEntity) : PartyStore(npc.uuid)
@@ -87,6 +87,8 @@ open class PartyStore(override val uuid: UUID) : PokemonStore<PartyPosition>() {
/** The amount of party slots that are occupied by a [Pokemon]. */
fun occupied() = slots.filterNotNull().count()
fun isEmpty() = occupied() == 0
override fun sendTo(player: ServerPlayer) {
player.sendPacket(InitializePartyPacket(false, uuid, slots.size))
slots.forEachIndexed { index, pokemon ->
@@ -280,5 +282,4 @@ open class PartyStore(override val uuid: UUID) : PokemonStore<PartyPosition>() {
remove(it)
}
}
}
}
@@ -14,6 +14,7 @@ import com.cobblemon.mod.common.api.events.CobblemonEvents
import com.cobblemon.mod.common.api.events.pokemon.PokemonGainedEvent
import com.cobblemon.mod.common.api.pokemon.evolution.Evolution
import com.cobblemon.mod.common.api.pokemon.evolution.PassiveEvolution
import com.cobblemon.mod.common.api.pokemon.feature.TickingSpeciesFeature
import com.cobblemon.mod.common.api.storage.pc.PCStore
import com.cobblemon.mod.common.battles.BattleRegistry
import com.cobblemon.mod.common.pokemon.OriginalTrainerType
@@ -21,7 +22,6 @@ import com.cobblemon.mod.common.pokemon.Pokemon
import com.cobblemon.mod.common.pokemon.activestate.ShoulderedState
import com.cobblemon.mod.common.pokemon.evolution.variants.LevelUpEvolution
import com.cobblemon.mod.common.util.*
import net.minecraft.nbt.CompoundTag
import net.minecraft.server.level.ServerPlayer
import net.minecraft.network.chat.Component
import java.util.*
@@ -162,6 +162,8 @@ open class PlayerPartyStore(
pokemon.tickInteractionCooldown()
}
pokemon.features.filterIsInstance<TickingSpeciesFeature>().forEach { it.onSecondPassed(player.serverLevel(), pokemon, null) }
if (pokemon.entity?.passengers?.isNotEmpty() != true) {
pokemon.rideStamina += 0.1F // Recover all stamina in 10 seconds, as long as no one's on it
}
@@ -36,6 +36,15 @@ data class GeneralPlayerData(
player.sendPacket(SetClientPlayerDataPacket(PlayerInstancedDataStoreTypes.GENERAL, this.toClientData()))
}
override fun initialize() {
// For any existing players, ensure they have all default key items
Cobblemon.config.defaultKeyItems.forEach {
if (!keyItems.contains(it)) {
keyItems.add(it)
}
}
}
override fun toClientData(): ClientInstancedPlayerData {
return ClientGeneralPlayerData(
false,
@@ -48,5 +57,4 @@ data class GeneralPlayerData(
)
}
}
}
@@ -34,7 +34,7 @@ class PlayerDataJsonBackend: JsonBackedPlayerDataStoreBackend<GeneralPlayerData>
starterLocked = !Cobblemon.starterConfig.allowStarterOnJoin,
starterSelected = false,
starterUUID = null,
keyItems = mutableSetOf(),
keyItems = Cobblemon.config.defaultKeyItems,
extraData = mutableMapOf(),
battleTheme = CobblemonSounds.PVP_BATTLE.location
)}
@@ -35,7 +35,7 @@ class PlayerDataMongoBackend(mongoClient: MongoClient, databaseName: String, col
starterLocked = !Cobblemon.starterConfig.allowStarterOnJoin,
starterSelected = false,
starterUUID = null,
keyItems = mutableSetOf(),
keyItems = Cobblemon.config.defaultKeyItems,
extraData = mutableMapOf(),
battleTheme = CobblemonSounds.PVP_BATTLE.location
)}
@@ -18,6 +18,7 @@ object ElementalTypes {
private val allTypes = mutableListOf<ElementalType>()
@JvmField
val NORMAL = register(
name = "Normal",
displayName = Component.translatable("cobblemon.type.normal"),
@@ -25,6 +26,7 @@ object ElementalTypes {
textureXMultiplier = 0
)
@JvmField
val FIRE = register(
name = "Fire",
displayName = Component.translatable("cobblemon.type.fire"),
@@ -32,6 +34,7 @@ object ElementalTypes {
textureXMultiplier = 1
)
@JvmField
val WATER = register(
name = "Water",
displayName = Component.translatable("cobblemon.type.water"),
@@ -39,6 +42,7 @@ object ElementalTypes {
textureXMultiplier = 2
)
@JvmField
val GRASS = register(
name = "Grass",
displayName = Component.translatable("cobblemon.type.grass"),
@@ -46,6 +50,7 @@ object ElementalTypes {
textureXMultiplier = 3
)
@JvmField
val ELECTRIC = register(
name = "Electric",
displayName = Component.translatable("cobblemon.type.electric"),
@@ -53,6 +58,7 @@ object ElementalTypes {
textureXMultiplier = 4
)
@JvmField
val ICE = register(
name = "Ice",
displayName = Component.translatable("cobblemon.type.ice"),
@@ -60,6 +66,7 @@ object ElementalTypes {
textureXMultiplier = 5
)
@JvmField
val FIGHTING = register(
name = "Fighting",
displayName = Component.translatable("cobblemon.type.fighting"),
@@ -67,6 +74,7 @@ object ElementalTypes {
textureXMultiplier = 6
)
@JvmField
val POISON = register(
name = "Poison",
displayName = Component.translatable("cobblemon.type.poison"),
@@ -74,6 +82,7 @@ object ElementalTypes {
textureXMultiplier = 7
)
@JvmField
val GROUND = register(
name = "Ground",
displayName = Component.translatable("cobblemon.type.ground"),
@@ -81,6 +90,7 @@ object ElementalTypes {
textureXMultiplier = 8
)
@JvmField
val FLYING = register(
name = "Flying",
displayName = Component.translatable("cobblemon.type.flying"),
@@ -88,6 +98,7 @@ object ElementalTypes {
textureXMultiplier = 9
)
@JvmField
val PSYCHIC = register(
name = "Psychic",
displayName = Component.translatable("cobblemon.type.psychic"),
@@ -95,6 +106,7 @@ object ElementalTypes {
textureXMultiplier = 10
)
@JvmField
val BUG = register(
name = "Bug",
displayName = Component.translatable("cobblemon.type.bug"),
@@ -102,6 +114,7 @@ object ElementalTypes {
textureXMultiplier = 11
)
@JvmField
val ROCK = register(
name = "Rock",
displayName = Component.translatable("cobblemon.type.rock"),
@@ -109,6 +122,7 @@ object ElementalTypes {
textureXMultiplier = 12
)
@JvmField
val GHOST = register(
name = "Ghost",
displayName = Component.translatable("cobblemon.type.ghost"),
@@ -116,6 +130,7 @@ object ElementalTypes {
textureXMultiplier = 13
)
@JvmField
val DRAGON = register(
name = "Dragon",
displayName = Component.translatable("cobblemon.type.dragon"),
@@ -123,6 +138,7 @@ object ElementalTypes {
textureXMultiplier = 14
)
@JvmField
val DARK = register(
name = "Dark",
displayName = Component.translatable("cobblemon.type.dark"),
@@ -130,6 +146,7 @@ object ElementalTypes {
textureXMultiplier = 15
)
@JvmField
val STEEL = register(
name = "Steel",
displayName = Component.translatable("cobblemon.type.steel"),
@@ -137,6 +154,7 @@ object ElementalTypes {
textureXMultiplier = 16
)
@JvmField
val FAIRY = register(
name = "Fairy",
displayName = Component.translatable("cobblemon.type.fairy"),
@@ -144,6 +162,7 @@ object ElementalTypes {
textureXMultiplier = 17
)
@JvmStatic
fun register(name: String, displayName: MutableComponent, hue: Int, textureXMultiplier: Int): ElementalType {
return ElementalType(
name = name,
@@ -155,20 +174,103 @@ object ElementalTypes {
}
}
@JvmStatic
fun register(elementalType: ElementalType): ElementalType {
allTypes.add(elementalType)
return elementalType
}
@JvmStatic
fun get(name: String): ElementalType? {
return allTypes.firstOrNull { type -> type.name.equals(name, ignoreCase = true) }
}
@JvmStatic
fun getOrException(name: String): ElementalType {
return allTypes.first { type -> type.name.equals(name, ignoreCase = true) }
}
@JvmStatic
fun count() = allTypes.size
@JvmStatic
fun all() = this.allTypes.toList()
}
@JvmStatic
fun getRandomType(): ElementalType = this.allTypes.random()
/**
* Backwards compatibility getters
*/
@JvmName("getNORMAL")
@Deprecated("Use ElementalTypes.NORMAL, provided for backwards compatibility until Cobblemon 1.8.")
fun getNORMAL() = NORMAL
@JvmName("getFIRE")
@Deprecated("Use ElementalTypes.FIRE, provided for backwards compatibility until Cobblemon 1.8.")
fun getFIRE() = FIRE
@JvmName("getWATER")
@Deprecated("Use ElementalTypes.WATER, provided for backwards compatibility until Cobblemon 1.8.")
fun getWATER() = WATER
@JvmName("getGRASS")
@Deprecated("Use ElementalTypes.GRASS, provided for backwards compatibility until Cobblemon 1.8.")
fun getGRASS() = GRASS
@JvmName("getELECTRIC")
@Deprecated("Use ElementalTypes.ELECTRIC, provided for backwards compatibility until Cobblemon 1.8.")
fun getELECTRIC() = ELECTRIC
@JvmName("getICE")
@Deprecated("Use ElementalTypes.ICE, provided for backwards compatibility until Cobblemon 1.8.")
fun getICE() = ICE
@JvmName("getFIGHTING")
@Deprecated("Use ElementalTypes.FIGHTING, provided for backwards compatibility until Cobblemon 1.8.")
fun getFIGHTING() = FIGHTING
@JvmName("getPOISON")
@Deprecated("Use ElementalTypes.POISON, provided for backwards compatibility until Cobblemon 1.8.")
fun getPOISON() = POISON
@JvmName("getGROUND")
@Deprecated("Use ElementalTypes.GROUND, provided for backwards compatibility until Cobblemon 1.8.")
fun getGROUND() = GROUND
@JvmName("getFLYING")
@Deprecated("Use ElementalTypes.FLYING, provided for backwards compatibility until Cobblemon 1.8.")
fun getFLYING() = FLYING
@JvmName("getPSYCHIC")
@Deprecated("Use ElementalTypes.PSYCHIC, provided for backwards compatibility until Cobblemon 1.8.")
fun getPSYCHIC() = PSYCHIC
@JvmName("getBUG")
@Deprecated("Use ElementalTypes.BUG, provided for backwards compatibility until Cobblemon 1.8.")
fun getBUG() = BUG
@JvmName("getROCK")
@Deprecated("Use ElementalTypes.ROCK, provided for backwards compatibility until Cobblemon 1.8.")
fun getROCK() = ROCK
@JvmName("getGHOST")
@Deprecated("Use ElementalTypes.GHOST, provided for backwards compatibility until Cobblemon 1.8.")
fun getGHOST() = GHOST
@JvmName("getDRAGON")
@Deprecated("Use ElementalTypes.DRAGON, provided for backwards compatibility until Cobblemon 1.8.")
fun getDRAGON() = DRAGON
@JvmName("getDARK")
@Deprecated("Use ElementalTypes.DARK, provided for backwards compatibility until Cobblemon 1.8.")
fun getDARK() = DARK
@JvmName("getSTEEL")
@Deprecated("Use ElementalTypes.STEEL, provided for backwards compatibility until Cobblemon 1.8.")
fun getSTEEL() = STEEL
@JvmName("getFAIRY")
@Deprecated("Use ElementalTypes.FAIRY, provided for backwards compatibility until Cobblemon 1.8.")
fun getFAIRY() = FAIRY
}
Loaded 100 of 2602 files, more files were not shown because too many files have changed in this diff. Show more