Compare commits

..
Author SHA1 Message Date
Paul 765e9f2cc3 snapshot = false 2023-12-23 11:39:57 +10:00
Paul ffda34742c Edge case protection with nickname migration 2023-12-23 11:01:03 +10:00
Paul c2385edbe7 more more changelog [skip-ci] 2023-12-23 11:00:00 +10:00
Paul 961ad0f4bd more changelog [skip-ci] 2023-12-23 10:45:07 +10:00
Paul 8851594347 Changelog polishing and removing stacks of unused item files 2023-12-23 10:44:32 +10:00
Paul 3c1ad2bea6 Add pokeball vivillon variant back into advancement 2023-12-23 09:10:17 +10:00
Hiroku e1960792d7 Merge branch 'bush_pathing' into 'main'
Berry bush avoidance

See merge request cable-mc/cobblemon!824
2023-12-22 22:50:24 +00:00
gr3ger 23b9f933c7 Updated changelog. 2023-12-22 23:37:27 +01:00
Paul 9662699bcb Fix mongo adapter constructor issue 2023-12-23 08:29:54 +10:00
Hiroku 32b2d2023b Merge branch 'nickname-migrate' into 'main'
Adds json nickname migrate + bug fix for non player entity backed battle actors.

See merge request cable-mc/cobblemon!821
2023-12-22 22:24:03 +00:00
Hiroku c64612859c Merge branch '732_spelling' into 'main'
Fix wrong name on animation/model folders

Closes #732

See merge request cable-mc/cobblemon!822
2023-12-22 22:17:12 +00:00
gr3ger 6c97c4c238 Removed extra call to getBlockState() and made function return on match instead of going through all if statements. 2023-12-22 23:11:58 +01:00
gr3ger 6535d43964 PoC bush avoidance 2023-12-22 18:16:21 +01:00
gr3ger 234d1dad44 Closes #732
Tested spawning entities after changes, nothing seems out of the ordinary.
2023-12-22 10:12:47 +01:00
Deltric da247e9902 Adds json nickname migrate + bug fix for non player entity backed battle actors. 2023-12-22 01:47:19 -06:00
Paul 0655d63dc5 Removed a couple of recipe advancements that are for items not ingame 2023-12-22 12:06:23 +10:00
Paul 81ba5ef615 Removed errant "light powder" item 2023-12-22 10:53:59 +10:00
Paul 8354c3838a Merge remote-tracking branch 'origin/main' 2023-12-22 10:10:12 +10:00
Paul 80db305aba Updated heaps of langs from crowdin 2023-12-22 10:10:00 +10:00
Hiroku 60e0314f29 Merge branch 'Spawn_Level_Scaling' into 'main'
Level scaling tweak

See merge request cable-mc/cobblemon!820
2023-12-19 22:14:21 +00:00
Nick 5f868630e0 Merge branch 'neo-bounties' into 'main'
:)

See merge request cable-mc/cobblemon!818
2023-12-19 20:46:10 +00:00
MoeBoy76 b93adae945 Merge branch 'main' of https://gitlab.com/cable-mc/cobblemon into Spawn_Level_Scaling
# Conflicts:
#	CHANGELOG.md
2023-12-19 12:49:57 +11:00
MoeBoy76 9f1ed344d8 Changelog 2023-12-19 12:46:48 +11:00
MoeBoy76 2c256eefde Correct logic and cleanup unused test code 2023-12-19 12:27:41 +11:00
Neovitalism b075fce83f :)
#725 - Adds a boolean property to PokemonEntity to make it not count towards the spawn cap.
#728 - Makes PokemonEntity respect minecraft's silent flag.
2023-12-18 15:10:19 -06:00
Paul f2ed332c4c Fixed minor error in lang 2023-12-19 05:51:00 +10:00
Paul e8f083d8bf Merge remote-tracking branch 'origin/main' 2023-12-19 05:50:38 +10:00
Hiroku 1684a341a1 Merge branch 'Swim_Behavior_Fix' into 'main'
Fixed Swim Behaviors for some Pokemon

See merge request cable-mc/cobblemon!817
2023-12-18 19:40:34 +00:00
Hiroku b4e1bf794d Merge branch 'Pokemon_Weight_Watchers' into 'main'
Changed calculations of Pokemon's weight and height before it is sent to Showdown so that battle damage for weight-based moves are accurate

See merge request cable-mc/cobblemon!816
2023-12-18 19:40:22 +00:00
jeffw773 c85ad7d60c - Changelog 2023-12-18 11:28:53 -08:00
jeffw773 e61e92a5d4 - Changelog 2023-12-18 11:27:08 -08:00
jeffw773 a245e9661c - final tweaks for MR 2023-12-18 11:01:35 -08:00
jeffw773 059152b34c - removed unused test code 2023-12-18 10:58:59 -08:00
jeffw773 0d35157fcf - removed unused test code 2023-12-18 10:42:43 -08:00
jeffw773 302388d0a6 - Added Swim behaviors to Samurott line, Clodsire, Wimpod, Golisopod, Quaxwell, Quaquaval, 2023-12-18 10:30:07 -08:00
jeffw773 ab957f82e1 - Altered some code for how Pokemon's height and weight is calculated for weight-based moves during battles as it had issues and was doing more damage than it should have been 2023-12-17 20:18:41 -08:00
jeffw773 fef82ae6bf - Altered some code for how Pokemon's height and weight is calculated for weight-based moves during battles as it had issues and was doing more damage than it should have been 2023-12-17 20:16:06 -08:00
jeffw773 8b979c1944 - Altered some code for how Pokemon's height and weight is calculated for weight-based moves during battles as it had issues and was doing more damage than it should have been 2023-12-17 19:52:32 -08:00
Paul 4bbbaacacf Merge remote-tracking branch 'origin/main' 2023-12-18 08:34:34 +10:00
jeffw773 eda8e15509 Merge remote-tracking branch 'origin/main' 2023-12-17 10:03:21 -08:00
Nick d53a71c188 Merge branch '1.4.1-fixes' into 'main'
1.4.1 fixes

See merge request cable-mc/cobblemon!814
2023-12-17 01:16:44 +00:00
HirokuandNick d2f02b0d06 1.4.1 fixes 2023-12-17 01:16:44 +00:00
Paul 5c0bb194b6 Fixed Tyrogue fainting into the floor 2023-12-17 10:50:08 +10:00
Paul e41562f5ad Fixed status apply fail messages for when they're already afflicted by that status 2023-12-17 10:49:59 +10:00
Paul 69ea1ac3bf Fixed things like Keen Eye not having translation stuff 2023-12-17 10:29:19 +10:00
Paul 7c15f0f924 Fixed confusing poison heal messages 2023-12-17 09:40:32 +10:00
Paul 6165e5e871 Corrected mistaken changelog entry 2023-12-17 09:19:41 +10:00
Paul dd8f59e0d0 Removed pink bow recipe as not needed anymore 2023-12-17 09:11:56 +10:00
Paul 87611795e9 Fixed battle messages getting out of sync after spectating, unspectating, re-spectating 2023-12-17 09:11:18 +10:00
Paul d2fe9b1132 Fixed Life Orb not having a proper item name 2023-12-17 08:57:26 +10:00
Hiroku e95759a710 Merge branch 'whatsy/bugfixes' into 'main'
Various bugfixes for 1.4.1

Closes #722 and #724

See merge request cable-mc/cobblemon!805
2023-12-16 21:50:39 +00:00
Hiroku 7284f8d35d Merge branch 'can-moe-scrape' into 'main'
Teal Mask species data

See merge request cable-mc/cobblemon!806
2023-12-16 21:24:07 +00:00
Hiroku 334dd1206e Merge branch 'share-the-explove' into 'main'
Balanced EXP Share Recipe

Closes #727

See merge request cable-mc/cobblemon!811
2023-12-16 21:23:32 +00:00
Hiroku e7caab0ae0 Merge branch 'Waldleufer/spawnCSVScriptPolishing' into 'main'
minor spawn CSV Script improvements and pokemon.json fix

See merge request cable-mc/cobblemon!812
2023-12-16 21:22:58 +00:00
Waldleufer 47f02f6e50 Restored Script default settings 2023-12-16 11:42:31 +01:00
Waldleufer 3367b0c39c dissolved bug in script
that would occur if the filled out Multiplier column for one pokemon was followed by an empty field
2023-12-16 11:40:47 +01:00
Waldleufer 0e43d7730c verified omanyte, omastar kabuto and kabutops json 2023-12-16 11:07:06 +01:00
Waldleufer b5604686f2 fix: Updated all minecraft:nether_quartz to minecraft:quartz 2023-12-16 11:05:00 +01:00
Waldleufer e030dbfbf5 refactor: Made the script report more readable. 2023-12-16 11:03:56 +01:00
Lily 96647a9398 fix conflict in changelog 2023-12-15 19:09:58 +00:00
dhi_holo 9e2c0ab0db Balanced EXP Share Recipe
Closes #727
2023-12-14 06:48:43 +10:00
Lily 1bc953f3f3 lang update 2023-12-12 14:40:06 +00:00
jeffw773 d089eab60f - Start of a tweak to how spawns work in terms of scaling the level of Pokémon based off of player party highest level 2023-12-11 17:19:19 -08:00
Hiroku d18cab39a9 Merge branch 'kkeenanwong-main-patch-46161' into 'main'
Update garganacl.json quartz item ID

See merge request cable-mc/cobblemon!808
2023-12-11 03:21:09 +00:00
Keenan Wong 4492666f5a Update garganacl.json quartz item ID 2023-12-11 03:04:33 +00:00
Hiroku 6a0985958b Merge branch 'reknot' into 'main'
Knot Flip

See merge request cable-mc/cobblemon!807
2023-12-10 23:37:43 +00:00
dhi_holo 308c5e6d32 Knot Flip
Destiny Knot recipe has been vertically flipped, to closer match the sprite.
2023-12-11 09:15:40 +10:00
MoeBoy76 bd83cc143b redo broken é 2023-12-09 23:43:12 +11:00
MoeBoy76 c9e6cb1022 fix line separator 2023-12-09 23:40:43 +11:00
MoeBoy76 74c75b7faa Applin evo data 2023-12-09 23:31:52 +11:00
MoeBoy76 45819a17f6 Teal Mask new data 2023-12-09 22:36:32 +11:00
Lily e3f84248b8 Added StructureLikeCondition.kt and a new StructureRequirement for evolutions. Closes #722 2023-12-05 19:35:30 -05:00
Lily 0ff518194f Fix grammar errors on certain pokeballs. made small fixes to Vivillon evolutions. Closes #724 2023-12-05 18:42:58 -05:00
Lily 634a1ad6fc Fixed Inkay evolution, fixed conflicting biome requirements for ocean, river, sun, and tundra vivillion variants. Closes #724 2023-12-05 16:58:39 +00:00
Lily 41217ebdcc Remove poke ball variant from the Vivillionaire advancement 2023-12-05 16:42:05 +00:00
Hiroku a021ec1337 Merge branch 'sound' into 'main'
Fixed missing cries again

See merge request cable-mc/cobblemon!803
2023-12-04 20:30:00 +00:00
Sterrezo b03f95b7da Fixed missing cries again
Scatterbug and Spewpa lost their cries somewhere so I re-added them. No changelog because this happened during development, so it's as it was in 1.4
2023-12-04 17:55:26 +01:00
Paul d8cee44661 Changelog [skip-ci] 2023-12-02 14:56:45 +10:00
Hiroku 5dd2287441 Merge branch 'fastutil-crash' into 'main'
Fixed fastutil crash

See merge request cable-mc/cobblemon!802
2023-12-02 04:39:25 +00:00
Paul 1eb6af14c2 Changelog 2023-12-02 10:53:18 +10:00
Paul 61b73972d4 Merge branch '1.4.0a'
# Conflicts:
#	CHANGELOG.md
2023-12-02 10:39:31 +10:00
Hiroku f8bcf8c291 Merge branch 'rendercontext-additions' into 'main'
Add species and aspects to RenderContext

See merge request cable-mc/cobblemon!799
2023-12-02 00:28:20 +00:00
Waterpicker 543d408e63 Merge remote-tracking branch 'cable-mc/main' into rendercontext-additions 2023-12-01 00:46:35 -06:00
Apion 2cdc781e93 Merge branch 'battles-unlanguished' into 'main'
Added langs and update interpreter

See merge request cable-mc/cobblemon!801
2023-12-01 05:45:42 +00:00
Segfault Guy 8dc0a7f72d Interpreter trimmings and fixes. 2023-12-01 00:18:50 -05:00
Paul 8b5231d6f0 Alternative way to fix dupe issue to not crash (huge) 2023-12-01 12:07:00 +10:00
Hiroku 665c4cc26c Merge branch 'particle-command' into 'main'
Added /bedrockparticle command

See merge request cable-mc/cobblemon!798
2023-11-30 22:50:25 +00:00
apion 7c860d8f91 Fix some of seg's review threads 2023-11-30 12:39:09 -05:00
apion 006e86f3c3 Fix my review threads 2023-11-30 11:37:52 -05:00
MoeBoy76 91dec859e8 Merge branch 'main' of https://gitlab.com/cable-mc/cobblemon into battles-unlanguished
# Conflicts:
#	CHANGELOG.md
2023-11-30 11:55:53 +11:00
Apion 85f08c9d28 Merge branch 'regionalise' into 'main'
Regionalise

See merge request cable-mc/cobblemon!800
2023-11-30 00:51:21 +00:00
MoeBoy76 d465f465c8 Merge branch 'main' of https://gitlab.com/cable-mc/cobblemon into battles-unlanguished
# Conflicts:
#	CHANGELOG.md
2023-11-30 11:43:02 +11:00
MoeBoy76 a87bd35fd6 changelog time 2023-11-30 11:38:39 +11:00
MoeBoy76 0c32da0ce1 added species feature for all regional forms that were missing it 2023-11-30 08:51:54 +11:00
Waterpicker 2bdb110c92 Remove some debug code I missed! 2023-11-29 14:04:20 -06:00
Waterpicker d21f3747fc Add species and aspects to RenderContext 2023-11-29 13:56:53 -06:00
jeffw773 fb303fcd97 - Started basic functionality of Battle menu that can be controlled by WASD or keybinded keys. Still more todo on this, but wanted to make a branch for it now 2023-11-29 11:35:50 -08:00
jeffw773 31b185b96c - Added -endability and -transform handlers 2023-11-28 00:06:52 -08:00
jeffw773 034a51b904 Merge remote-tracking branch 'origin/battles-unlanguished' into battles-unlanguished 2023-11-27 22:12:01 -08:00
jeffw773 9e1c491d9c - Moe said it was okay 2023-11-27 22:11:42 -08:00
jmmcp f695a99705 Added -swapboost langs for Guard Swap, Power Swap, and Heart Swap, as well as -start lang for Tar Shot. 2023-11-28 00:31:13 -05:00
jmmcp a8567f9190 Added check for optional effects in handleStartInstruction to allow for proper handling of moves like Reflect Type. 2023-11-27 23:39:27 -05:00
jmmcp 7d455b2dac Merge remote-tracking branch 'origin/battles-unlanguished' into battles-unlanguished
# Conflicts:
#	common/src/main/resources/assets/cobblemon/lang/en_us.json
2023-11-27 23:10:57 -05:00
jmmcp 1dffbd1b37 Added -start langs for embargo and general typeadd moves. 2023-11-27 23:10:10 -05:00
jeffw773 332e25fa76 Merge remote-tracking branch 'origin/battles-unlanguished' into battles-unlanguished 2023-11-27 20:07:53 -08:00
jeffw773 f080fb5639 - Added Substitute Start Language 2023-11-27 20:07:34 -08:00
jmmcp 769a1862e4 Added -copyboost lang, new copyboost instruction handler, new copy method to ContextManager, silent optional argument check to -clearnegativeboost instruction handler, and tweaked -enditem instruction handler in CobblemonHeldItemManager to allow for cases with null source (example: Fling). 2023-11-27 22:25:54 -05:00
jmmcp 127c5e7a8b Merge branch 'main' into battles-unlanguished 2023-11-27 19:11:22 -05:00
Paul d1a71373c0 Added /bedrockparticle command 2023-11-27 13:26:26 +10:00
Hiroku 77def6de43 Merge branch 'mooshtank_fix_and_shuckle_nerf' into 'main'
Shuckle Berry Nerf + Brown Mooshtank Sus Stew Fix

See merge request cable-mc/cobblemon!792
2023-11-27 01:42:01 +00:00
jmmcp 973c6bb05f Merge remote-tracking branch 'origin/battles-unlanguished' into battles-unlanguished 2023-11-26 19:39:26 -05:00
jmmcp 5b83e49669 Added -start lang for type changing moves Camouflage, Conversion, and Conversion2, as well as -sidestart and -sideend langs for Lucky Chant and Mist. 2023-11-26 19:38:59 -05:00
Hiroku e01bc2eeab Merge branch 'nickname_invalid_format' into '1.4.0'
Resolves a bug in the format in which the nickname is saved in JSON.

See merge request cable-mc/cobblemon!797
2023-11-26 23:19:50 +00:00
Pedro Souza f6f3070b8e changelog 2023-11-26 20:18:37 -03:00
Pedro Souza 0f2301e668 Resolved nickname invalid format bug 2023-11-26 12:24:54 -03:00
jeffw773 80ce5bab58 - Added battle language for powertrick and powershift 2023-11-26 01:25:15 -08:00
Hiroku 8fb678b0f8 Merge branch 'battle_music_enhancements' into 'main'
Add new battle music features

Closes #587

See merge request cable-mc/cobblemon!790
2023-11-26 08:17:45 +00:00
jeffw773 c0a77aca23 - Added battle language for Stockpile 2023-11-26 00:02:37 -08:00
jmmcp e4c0eab8e2 Added -fieldactivate langs for Fairy Lock and Teatime, as well as a new handler for -invertboost instructions. 2023-11-26 00:02:04 -05:00
Hiroku b9ff46e1b2 Merge branch 'sirrfuchs-main-patch-53627' into 'main'
Added canFly true to Yveltal

See merge request cable-mc/cobblemon!796
2023-11-25 21:22:45 +00:00
sirrfuchs 45a998d3d7 Added canFly true to Yveltal 2023-11-25 16:27:57 +00:00
Hiroku a108d85531 Merge branch 'root-burn' into 'main'
Remedy Alternate Cooking

See merge request cable-mc/cobblemon!795
2023-11-25 07:22:27 +00:00
dhi_holo 0fae45f811 Remedy Alternate Cooking
Smokers and Campfires work now
2023-11-25 10:13:19 +10:00
Hiroku 88717d598d Merge branch 'Waldleufer/speciesJsonFixes' into 'main'
small species json fixes

See merge request cable-mc/cobblemon!794
2023-11-24 22:14:28 +00:00
WaldleuferandHiroku 33123b4a33 small species json fixes 2023-11-24 22:14:27 +00:00
Hiroku 74e0915ec8 Merge branch 'SmarterDrops' into 'main'
Corrected some drops, added missing drops to a bunch of base forms and forms.

See merge request cable-mc/cobblemon!789
2023-11-24 00:00:28 +00:00
WaldleuferandHiroku 39cd5e9726 Corrected some drops, added missing drops to a bunch of base forms and forms. 2023-11-24 00:00:28 +00:00
jeffw773 876be2afcf - Brown Mooshtanks give Suspicious Stews like vanilla brown mooshrooms do (plus Pep Up Flower)
- Nerfed Infinite Berry Juice Shuckle
2023-11-22 19:07:39 -08:00
jeffw773 d693f452bc - Fixed Mooshtanks not giving mushroom stew in creative
- Nerfed Shuckle infinite Berry Juice
2023-11-22 15:49:54 -08:00
jmmcp a1e94b8200 Added -activate langs for eerie spell and crafty shield. 2023-11-22 01:04:11 -05:00
Segfault Guy 8b4552a532 Unique wild encounter themes. 2023-11-19 22:33:26 -05:00
Segfault Guy 41673ba90f Battle music for spectators. 2023-11-19 22:33:26 -05:00
Segfault Guy 18f9942dc6 BattleStartedEvent rework and battle music override support. 2023-11-19 22:33:23 -05:00
Segfault Guy 875fe46d21 Player specific battle themes. 2023-11-19 22:32:42 -05:00
Segfault Guy 66c6f9bdd1 BattleMusicHandler upgrades and bug fixes. 2023-11-19 22:32:04 -05:00
Hiroku b72af84c8c Merge branch 'tooltip-fix' into 'main'
Tooltip fix

See merge request cable-mc/cobblemon!788
2023-11-20 00:32:18 +00:00
miasmus a5ee270b8b account for tooltips with only 1 element 2023-11-19 19:00:05 -05:00
miasmus c08ef4247d doing it this way cause the other way was bad 2023-11-19 18:24:47 -05:00
jmmcp 9424bafabb Merge remote-tracking branch 'origin/battles-unlanguished' into battles-unlanguished 2023-11-19 18:21:02 -05:00
jmmcp a96ecfcdf2 Added -fail instructions for Burn Up and Double Shock, as well as lang for healing moves and weight based moves against Dynamaxed mons failing 2023-11-19 18:20:07 -05:00
Hiroku b1d11e8c22 Merge branch 'HOLDY2' into 'main'
Fixed some minor errors in the newly added dropps

See merge request cable-mc/cobblemon!787
2023-11-19 22:05:02 +00:00
WaldleuferandHiroku c1fb1379a9 Fixed some minor errors in the newly added dropps 2023-11-19 22:05:02 +00:00
Hiroku 5a220e0ef0 Merge branch 'implement_pokemon' into 'main'
Implemented Drifloon line and minor asset updates.

See merge request cable-mc/cobblemon!786
2023-11-19 22:01:03 +00:00
Hiroku b379fc62b1 Merge branch 'Waldleufer/cry_checker_script' into 'main'
cry audio checker script

See merge request cable-mc/cobblemon!785
2023-11-19 21:55:53 +00:00
WaldleuferandHiroku d442e4e956 cry audio checker script 2023-11-19 21:55:53 +00:00
Tyzillion bb22c22db9 added "implemented": true to the species.json for the new Pokemon implemented. 2023-11-19 10:33:58 -05:00
JazzMcNade 09bc174401 Added code to display enditem.incinerate's message when it occurs. 2023-11-19 04:26:13 -06:00
Tyzillion e109a1d59f Implemented Drifloon line, Updated Dodrio textures, updated aegislash_shiny texture, Updated models for Geodude line. Added emissives for Noctowl. 2023-11-18 22:12:23 -05:00
jmmcp 3b97a0c847 Added -activate langs for Skill Swap and Wide Guard, -enditem langs for Corrosive Gas and Bug Bite, -fail lang for Aura Wheel, and allow for effectID to pass through as null in handle fail instruction for fails that don't have an effect, such as Baton Pass and Bide. 2023-11-18 16:02:58 -05:00
JazzMcNade 87e8fcd7f7 Added -end lang for Healblock and Skydrop. Added -fail for Skydrop 2023-11-17 22:47:41 -06:00
Hiroku b34f8a045d Merge branch 'null-safety-time' into 'main'
Fix to NullPointerException in PokemonOnShoulderHandler

Closes #677

See merge request cable-mc/cobblemon!783
2023-11-18 04:26:38 +00:00
JPAKx4 4f79b9f8a7 Fix to https://gitlab.com/cable-mc/cobblemon/-/issues/677 2023-11-17 21:30:49 -06:00
JazzMcNade d1b651a876 Added -activate langs for Grudge, Speedswap and Switcheroo. 2023-11-17 21:13:55 -06:00
Hiroku b30a67651e Merge branch 'VillagerCropInteractionFix' into 'main'
Fix for villagers not being able to pick and plant mint seeds, vivichoke seeds...

Closes #647

See merge request cable-mc/cobblemon!760
2023-11-18 01:43:10 +00:00
JazzMcNade a1398e9495 Fixed capitalization. 2023-11-17 19:22:42 -06:00
jmmcp ca319764f0 Added -activate langs for Ingrain, Mist, Poltergeist, Powder, Quash, Quick Guard, Safeguard, and Sketch. 2023-11-17 19:00:12 -05:00
Hiroku ac03c68f41 Merge branch 'defaultIssueTemplate' into 'main'
Added a default Issue Template

See merge request cable-mc/cobblemon!769
2023-11-17 22:16:35 +00:00
Nick 0eb4b43b49 Merge branch 'updated-showdown' into 'main'
Updated Showdown version to latest master from Smogon

Closes #542

See merge request cable-mc/cobblemon!764
2023-11-17 21:18:05 +00:00
HirokuandNick b49376dba5 Updated Showdown version to latest master from Smogon 2023-11-17 21:18:03 +00:00
Nick 81f6e7b786 Merge branch 'shuckle_milk' into 'main'
Added ability for Shuckles to be milked for Berry Juice

See merge request cable-mc/cobblemon!770
2023-11-17 21:17:28 +00:00
Plastered_CrabandNick 574ee1ae4a Added ability for Shuckles to be milked for Berry Juice 2023-11-17 21:17:27 +00:00
Nick 07a83f54a2 Merge branch 'HOLDY-lite' into 'main'
It's holding time

See merge request cable-mc/cobblemon!777
2023-11-17 19:41:59 +00:00
JordanandNick 6f3b530d7b It's holding time 2023-11-17 19:41:59 +00:00
Nick 4b86dc1e58 Merge branch 'ability-optional-arguments' into 'main'
Implement method to properly handle showdown ability instructions with optional arguments.

Closes #499

See merge request cable-mc/cobblemon!778
2023-11-17 19:30:45 +00:00
JMMCPandNick bb141aee50 Implement method to properly handle showdown ability instructions with optional arguments. 2023-11-17 19:30:45 +00:00
Nick acb473c01f Merge branch 'Waldleufer/fixUndergroundSpawningAlgorithm' into 'main'
Underground Spawning Algorithm Improvements

See merge request cable-mc/cobblemon!737
2023-11-17 18:37:02 +00:00
WaldleuferandNick a8dc3f40a4 Underground Spawning Algorithm Improvements 2023-11-17 18:37:02 +00:00
Nick b55f11628d Merge branch 'Waldleufer/spawnSpreadsheetToCodeAutomation' into 'main'
Validated and corrected all Spawnfiles

See merge request cable-mc/cobblemon!755
2023-11-17 18:27:17 +00:00
WaldleuferandNick 150c03d4f5 Validated and corrected all Spawnfiles 2023-11-17 18:27:17 +00:00
Nick 1c092588f4 Merge branch 'HealingWishUnfaintPostBattleFix' into 'main'
HealingWishUnfaintPostBattleFix

See merge request cable-mc/cobblemon!779
2023-11-17 18:19:11 +00:00
JazzMcNade 683473c34c - Added activate.electricterrain 2023-11-17 02:43:36 -06:00
jeffw773 c7dee1bd53 - Added some more -start flags 2023-11-16 23:00:03 -08:00
jeffw773 d83a1086d3 - Added start.futuresight 2023-11-16 22:17:35 -08:00
Hiroku b34ca3d42b Merge branch 'HealthBarUpdateOnDamageFix' into 'main'
Fix for health bars not updating when a pokemon takes damage from commit 132a43c5

See merge request cable-mc/cobblemon!775
2023-11-17 05:04:34 +00:00
MoeBoy76 3a1389d719 start of missing battle messages 2023-11-17 10:18:44 +11:00
Hiroku e608dc84ae Merge branch 'mongodb-timestamp' into 'main'
Added timestamp to MongoDB store to signify when the save was created.

See merge request cable-mc/cobblemon!781
2023-11-16 14:49:52 +00:00
navneetset c987a5ba19 Added timestamp to MongoDB store to signify when the save was created. 2023-11-16 14:08:18 +01:00
Hiroku d65090ce10 Merge branch 'main' into 'main'
Issue #699 - Fixed typo in Coba Berry tooltip.

See merge request cable-mc/cobblemon!780
2023-11-16 11:09:45 +00:00
Michael 206ec25a99 Issue #699 - Fixed typo in Coba Berry tooltip. 2023-11-16 03:22:47 -05:00
JazzMcNade ccd376c055 Refactoring 2023-11-14 22:19:40 -06:00
JazzMcNade 6214fb1b97 The handleDamageInstruction inner dispatch is now placed at the head of the queue to make sure it stays ahead of the handleFaintInstruction dispatch. 2023-11-13 01:13:27 -06:00
JazzMcNade a65cee3e24 Fix for health bars not updating when a pokemon takes damage from commit 132a43c5 2023-11-13 00:51:50 -06:00
Hiroku 9999a04692 Merge branch 'status-complete' into 'main'
added tab completion for Statuses

See merge request cable-mc/cobblemon!774
2023-11-13 06:29:19 +00:00
MoeBoy76 6901f3e43d added tab completion for Statuses 2023-11-13 17:07:22 +11:00
Waldleufer 1a0135c1fd Added a feature request issue template. 2023-11-12 10:25:44 +01:00
Waldleufer 23dab6546f Added requested changes 2023-11-12 10:25:16 +01:00
Hiroku 3b94b6660c Merge branch 'new_battle_fix' into 'main'
New 100+ Battle languages fixed

See merge request cable-mc/cobblemon!771
2023-11-12 08:55:05 +00:00
jeffw773 dc46c96ecf Fixed merge conflicts 2023-11-12 00:33:00 -08:00
Hiroku 55861a249e Merge branch 'augh-u-rite' into 'main'
More Augurite Usage

Closes #687

See merge request cable-mc/cobblemon!754
2023-11-12 03:28:42 +00:00
Hiroku f00a569d9d Merge branch 'main' into 'augh-u-rite'
# Conflicts:
#   CHANGELOG.md
2023-11-12 02:40:29 +00:00
Hiroku aaa5484752 Update CHANGELOG.md [skip-ci] 2023-11-12 01:38:44 +00:00
Hiroku c6e82ebfb9 Merge branch 'fix-405-recall-visual-bug' into 'main'
Fix visual Pokemon recall bug

Closes #415 and #405

See merge request cable-mc/cobblemon!750
2023-11-12 01:37:19 +00:00
Hiroku 365844ae2e Merge branch 'battle_text_fail_block' into 'main'
Added -fail and -block handlers to ShowdownInterpreter as well as added around...

See merge request cable-mc/cobblemon!753
2023-11-12 01:33:22 +00:00
Hiroku c18c1f39fb Merge branch 'main' into 'battle_text_fail_block'
# Conflicts:
#   CHANGELOG.md
2023-11-12 01:09:42 +00:00
Hiroku 1fd2aa06ae Merge branch 'EXP-Item-Pokemon-Select' into 'main'
Exp Candies - Party Pokemon Select

Closes #692

See merge request cable-mc/cobblemon!757
2023-11-11 22:55:31 +00:00
Hiroku 931852bd36 Merge branch 'alolanRatataFix' into 'main'
Fixed alolan Rattata animations

Closes #695

See merge request cable-mc/cobblemon!768
2023-11-11 19:48:25 +00:00
WaldleuferandHiroku 272f429f59 Fixed alolan Rattata animations 2023-11-11 19:48:24 +00:00
Waldleufer b4787b8db8 Added a default Issue Template 2023-11-11 19:44:02 +01:00
Hiroku 6a5c6d2b17 Merge branch 'licious/190' into 'main'
Conditional held item consumption

Closes #190

See merge request cable-mc/cobblemon!767
2023-11-11 12:37:16 +00:00
Hiroku 618453caaa Update CHANGELOG.md 2023-11-11 11:53:18 +00:00
Hiroku e1d048ec9d Merge branch 'main' into 'licious/190'
# Conflicts:
#   CHANGELOG.md
2023-11-11 11:52:37 +00:00
Hiroku 26ebd23d14 Merge branch 'sound' into 'main'
Added cries to the Beldum line, tweaked Pikachu and Raichu cries

See merge request cable-mc/cobblemon!766
2023-11-11 01:07:05 +00:00
Paul b446415200 Fixed minor position error in new pokeball animations 2023-11-11 09:45:47 +10:00
jeffw773 ed8fe19dc1 Fixed redundancies, added shared langs for a few moves, and fixed red formatting for fail lang. 2023-11-10 15:30:11 -08:00
Hiroku cdcc071ce0 Merge branch 'main' into 'VillagerCropInteractionFix'
# Conflicts:
#   CHANGELOG.md
2023-11-10 22:51:44 +00:00
dhi_holo e674b042d0 Nerfed Obsidian
reduced crafting to output 1 because it makes more sense
2023-11-11 08:49:21 +10:00
dhi_holo 53abb58ae6 Merge branch 'main' into augh-u-rite 2023-11-11 08:47:01 +10:00
Sterrezo 17fed9662c Merge branch 'main' into sound 2023-11-10 21:38:28 +01:00
Sterrezo 74dd2a6c0d Added cries to the Beldum line, tweaked Pikachu and Raichu cries 2023-11-10 21:38:11 +01:00
Stephen White 7505ce15e3 Merge remote-tracking branch 'upstream/main' into fix-405-recall-visual-bug 2023-11-10 12:27:43 -04:00
Charzard4261 30ba97ea69 Merge remote-tracking branch 'origin/EXP-Item-Pokemon-Select' into EXP-Item-Pokemon-Select 2023-11-10 14:15:20 +00:00
Charzard4261 5fee2df9f7 Added a missing POKEMON_INTERACT trigger in PokemonSelectingItem, when successfully using an Item on a Pokemon out of battle. 2023-11-10 14:14:53 +00:00
Charzard4261 238c7474b3 Merge branch 'main' into 'EXP-Item-Pokemon-Select'
# Conflicts:
#   CHANGELOG.md
2023-11-10 11:14:39 +00:00
Hiroku 5da5c72b4f Merge branch 'main' into 'main'
Restored Fabric BrewingStandBlockEntityMixin for brewing stand/sidehopper interaction

See merge request cable-mc/cobblemon!746
2023-11-10 05:55:58 +00:00
Hiroku 0604b45b9d Merge branch 'spectate' into 'main'
Added ability to spectate pokemon battles

See merge request cable-mc/cobblemon!747
2023-11-10 05:28:50 +00:00
ApionandHiroku 132a43c5c7 Added ability to spectate pokemon battles 2023-11-10 05:28:50 +00:00
Hiroku b1e8f9cfb6 Merge branch 'fortune_evo_ores' into 'main'
Fortune evo ores

Closes #686

See merge request cable-mc/cobblemon!765
2023-11-10 04:21:57 +00:00
Lily a166a38c4b Update CHANGELOG.md 2023-11-09 22:59:52 -05:00
Lily 57fa6a58d5 Add Fortune compatibility to evo stone ores. Closes #686 2023-11-09 22:58:39 -05:00
Charzard4261 95006ae327 Merge branch 'main' into 'EXP-Item-Pokemon-Select'
# Conflicts:
#   CHANGELOG.md
2023-11-10 00:08:03 +00:00
Hiroku ad6fc97eef Merge branch 'implement_pokemon' into 'main'
One new Pokémon line, Animation, Textures, and Models updated. Pokémon Sleep? Naw just sleepy Pokemon.

See merge request cable-mc/cobblemon!763
2023-11-10 00:03:21 +00:00
Tyzillion fc39baaa30 Fixed Exeggcute faint, Added emissive to Hoothoot. 2023-11-09 18:40:59 -05:00
Tyzillion 887ff8ccdb Merge remote-tracking branch 'origin/implement_pokemon' into implement_pokemon 2023-11-09 18:29:47 -05:00
Paul 4d6117f5bf Merge remote-tracking branch 'origin/implement_pokemon' into implement_pokemon 2023-11-10 09:13:44 +10:00
Paul 3dc26639a5 Fixed Trevenant sleep animation 2023-11-10 09:13:28 +10:00
Tyzillion 252f9d5dbd Merge branch 'main' of https://gitlab.com/cable-mc/cobblemon into implement_pokemon
# Conflicts:
#	CHANGELOG.md
2023-11-09 16:46:47 -05:00
Charzard4261 599b8c5eec Merge branch 'main' into 'EXP-Item-Pokemon-Select'
# Conflicts:
#   CHANGELOG.md
2023-11-09 18:55:55 +00:00
Nick 974f839d61 Merge branch 'more_composting' into 'main'
Update composting functionality for Heal Powder and mutated Herbs

Closes #681

See merge request cable-mc/cobblemon!759
2023-11-09 18:50:44 +00:00
Nick b4ea13ab20 Merge branch 'milk_the_mooshtank' into 'main'
Allow Mooshtanks to be milked for mushroom stew. Closes #684

Closes #684

See merge request cable-mc/cobblemon!758
2023-11-09 18:49:33 +00:00
Nick 06afb04050 Merge branch 'missing_messages' into 'main'
Added a bunch of missing texts. Fixes #582, #588

Closes #588 and #582

See merge request cable-mc/cobblemon!752
2023-11-09 18:48:25 +00:00
Lily 92c3d9464b Merge branch 'main' into milk_the_mooshtank
# Conflicts:
#	CHANGELOG.md
2023-11-09 13:04:53 -05:00
Lily 03ed8f3edd Update CHANGELOG.md 2023-11-09 13:03:23 -05:00
Hiroku b475b02fff Merge branch 'Bee-Related-Changes' into 'main'
Bee Related Changes

See merge request cable-mc/cobblemon!762
2023-11-08 20:10:18 +00:00
Charzard4261 8c462f1567 Gave the Pep-Up Flower item the "minecraft:flowers" tag, to allow Bees to be fed using them. 2023-11-08 16:23:16 +00:00
JazzMcNade 1c25ae69a5 Fix for villagers not being able to pick and plant mint seeds, vivichoke seeds and revival herbs. Closes #647 2023-11-08 03:05:03 -06:00
Lily e668735dd8 Update composting functionality for Heal Powder and mutated Herbs. Closes #681 2023-11-07 21:15:22 -05:00
Lily f0e65fe4de Allow Mooshtanks to be milked for mushroom stew. Closes #684 2023-11-07 20:41:19 -05:00
Charzard4261 084a7bfb3c CandyItem now uses PokemonSelectingItem, and does not consume when in Creative. 2023-11-08 00:46:51 +00:00
Tyzillion 3c11a673dc Update models for Hitmontop. Updated animations for Zubat, Golbat, Scatterbug, Spewpa. Added Shoulder animations for Zubat. 2023-11-07 07:23:36 -05:00
dhi_holo deb2cff477 A Use?
Augurite now can make axes and obsidian, closes #687
2023-11-07 12:16:30 +10:00
jeffw773 79d89852d4 Added -fail and -block handlers to ShowdownInterpreter as well as added around 17 battle texts related to them 2023-11-06 15:51:09 -08:00
Tyzillion 8d38144551 Merge branch 'main' of https://gitlab.com/cable-mc/cobblemon into implement_pokemon 2023-11-06 14:08:39 -05:00
Stephen White a21a172be3 Fix visual Pokemon recall bug 2023-11-06 10:32:05 -04:00
JazzMcNade b44e5c797e Made sure mixin logic is applied for all potion slots in brewing stands. 2023-11-05 17:12:15 -06:00
JazzMcNade ae9337c84a Mixin compatibility changes. 2023-11-05 16:33:44 -06:00
JazzMcNade 5db2c4c955 Restored BrewingStandBlockEntityMixin for brewing stand/hopper interaction 2023-11-05 03:59:54 -06:00
Hiroku 8af1225c90 Merge branch 'npc-revival' into 'main'
Prevent NPCs from freezing battles upon using Revival Blessing.

See merge request cable-mc/cobblemon!745
2023-11-05 05:14:51 +00:00
jmmcp 4b181d75c8 Added a check to avoid NPCs freezing battles upon using Revival Blessing. 2023-11-05 00:51:38 -04:00
Hiroku 9e28dce3d7 Merge branch 'revival-blessing-fix' into 'main'
Fixes the move Revival Blessing

Closes #660

See merge request cable-mc/cobblemon!744
2023-11-05 02:29:27 +00:00
jmmcp 39f084bd56 Can't forget the changelog. 2023-11-04 21:46:29 -04:00
jmmcp c82bba7872 Add checks throughout the switch process to allow the Revival Blessing forceSwitch command to validate. 2023-11-04 21:42:03 -04:00
Hiroku 3f557d9ae6 Merge branch 'return_bottles' into 'main'
Return bottles

Closes #674 and #673

See merge request cable-mc/cobblemon!742
2023-11-04 04:35:26 +00:00
Tyzillion c15976a936 Merge branch 'main' of https://gitlab.com/cable-mc/cobblemon into implement_pokemon
# Conflicts:
#	CHANGELOG.md
2023-11-03 21:38:04 -04:00
Hiroku c8652b519a Merge branch 'vivillon_wings' into 'main'
Implement new Vivillon patterns

Closes #600 and #676

See merge request cable-mc/cobblemon!743
2023-11-04 00:51:32 +00:00
Lily 67c828dd0c missed one 2023-11-03 19:49:30 -04:00
Lily 10a1bc6bc6 Merge remote-tracking branch 'origin/return_bottles' into return_bottles 2023-11-03 19:42:35 -04:00
Lily e4db065a85 change friendshop drop through json and not the item class 2023-11-03 19:42:09 -04:00
Hiroku 171cd45e32 Merge branch 'main' into 'return_bottles'
# Conflicts:
#   CHANGELOG.md
2023-11-03 23:27:57 +00:00
Lily d638315fb1 Rename "Patterned Wings" to "Vivillonaire". Closes #676 2023-11-03 19:27:38 -04:00
Hiroku 980fa6a13d Merge branch 'healing_percent_fix' into 'main'
Fix issue involving health display after healing

Closes #663

See merge request cable-mc/cobblemon!740
2023-11-03 23:27:37 +00:00
Hiroku 267faf9397 Merge branch 'get-nerfed' into 'main'
Harder Healing Machine, Nerds

Closes #672

See merge request cable-mc/cobblemon!741
2023-11-03 23:25:56 +00:00
Lily 7549d77ad7 Update CHANGELOG.md 2023-11-03 19:24:59 -04:00
Lily 0f6929dd5e implement new vivillon wing patterns. Closes #600 2023-11-03 19:23:18 -04:00
Licious 79597a81fe Implemented conditional held item consumption. 2023-11-03 11:44:42 +00:00
dhi_holo e54e822c3a Harder Healing Machine, Nerds
Closes #672
2023-11-03 15:12:30 +10:00
Lily 5e60bb525c Changes to healing items. Closes #673, #674 2023-11-02 23:47:12 -04:00
Tyzillion c49cb45892 Fixed sleeping animations not playing for many Pokmeon. Implemented Litwick line, Update model, texture, and animations for Zubat line. Fixed Ceruledge back spike texture error. Updated Dusknoir, Ratatta, and Exegguter animation. Fixed Volbeat t-pose when flying. Fixed Wimpod asymmetric eyebrows. Fixed Voltorb texture. Fixed shiny Pidgeotto texture. 2023-11-02 22:22:16 -04:00
Tyzillion e0a896377e Merge branch 'main' of https://gitlab.com/cable-mc/cobblemon into implement_pokemon 2023-11-02 22:19:43 -04:00
Lily b96638226c Fixes #663 2023-11-02 22:19:36 -04:00
Lily 7c025582e0 Added a bunch of missing texts. Fixes #582, #588 2023-11-02 19:59:52 -04:00
Hiroku 623dfbb78b Merge branch 'licious/potion-fixes' into 'main'
Rework potion stuff & fixes

Closes #667 and #460

See merge request cable-mc/cobblemon!739
2023-11-02 23:28:37 +00:00
Licious 942bf8247e Consistent names aren't my specialty okay? 2023-11-02 22:44:26 +00:00
Licious d6a991e81e Fix various potion related issues. 2023-11-02 22:43:33 +00:00
Tyzillion 5d5de4f2f3 Merge branch 'main' of https://gitlab.com/cable-mc/cobblemon into implement_pokemon
# Conflicts:
#	CHANGELOG.md
2023-11-02 15:38:50 -04:00
Hiroku 7e952295a5 Merge branch 'licious/a-sign-of-boats-to-come' into 'main'
Implement Apricorn boats & signs

See merge request cable-mc/cobblemon!725
2023-11-02 08:14:26 +00:00
Hiroku d299cad9db Merge branch 'main' into 'licious/a-sign-of-boats-to-come'
# Conflicts:
#   CHANGELOG.md
2023-11-01 20:35:35 +00:00
Nick 261408d542 Merge branch 'licious/606' into 'main'
Progress related evolution requirement fixes

Closes #606

See merge request cable-mc/cobblemon!738
2023-11-01 19:01:24 +00:00
Nick cde163c1d1 Merge branch 'licious/597' into 'main'
Fix loot injection on Forge

Closes #597

See merge request cable-mc/cobblemon!736
2023-11-01 16:52:54 +00:00
Licious dbc478fc89 Fix battle critical hits evolution, fixed DamageTakenEvolutionProgress & DefeatEvolutionProgress not being registered. 2023-11-01 14:49:03 +00:00
Licious dde6c1dc97 *Apricorn 2023-10-31 23:47:46 +00:00
Licious 41d7740374 Merge branch 'main' into licious/a-sign-of-boats-to-come
# Conflicts:
#	CHANGELOG.md
#	common/src/main/kotlin/com/cobblemon/mod/common/CobblemonItems.kt
#	common/src/main/resources/mixins.cobblemon-common.json
2023-10-31 23:44:21 +00:00
Licious 29f0c6f7bc Rework LootInjector functionality, fix Forge. 2023-10-31 23:38:17 +00:00
Licious d128d3e025 Merge branch 'blame-json' into 'main'
Advancements Fixed

See merge request cable-mc/cobblemon!735
2023-10-31 09:50:59 +00:00
Licious 422bd5a0de Merge branch 'licious/596' into 'main'
Add the Fairy Feather.

Closes #596

See merge request cable-mc/cobblemon!734
2023-10-31 09:50:28 +00:00
Licious 65271dc1b1 Merge branch 'licious/595' into 'main'
Add the Cleanse Tag item

Closes #595

See merge request cable-mc/cobblemon!733
2023-10-31 09:50:07 +00:00
dhi_holo 8a604fdefe Only Canon
Removed Cobblemon Vivillon patterns from advancement for time being, so this can be merged
2023-10-31 12:15:26 +10:00
dhi_holo a525df98cd Merge branch 'main' into blame-json 2023-10-31 12:14:19 +10:00
Licious 6a5c52ca0e Add the Fairy Feather. 2023-10-30 11:40:47 +00:00
Licious 57509b6bba Fix typo. 2023-10-30 11:21:27 +00:00
Licious 0a4b7fe5c8 Added the cleanse tag. 2023-10-30 11:21:19 +00:00
Hiroku 45f72e0e9e Merge branch 'spawner-fixes' into 'main'
Two spawner fixes

See merge request cable-mc/cobblemon!732
2023-10-30 07:30:06 +00:00
Deltric 029e152d95 Updated changelog for spawning fixes. 2023-10-30 02:00:22 -05:00
Deltric 08d6fa00eb Two spawner fixes 2023-10-30 01:47:36 -05:00
Hiroku 35bb803fb0 Merge branch 'battle-lang-fix' into 'main'
Battle lang fix

Closes #617 and #637

See merge request cable-mc/cobblemon!731
2023-10-29 23:48:38 +00:00
Plastered_Crab ec028c89e4 Update CHANGELOG.md 2023-10-29 18:47:27 +00:00
Plastered_Crab 1de8a40bae Added case for Disable to ShowdownInterpreter.kt 2023-10-29 18:45:24 +00:00
Plastered_Crab 8c682356bb Added extra battle text for various moves en_us.json 2023-10-29 18:42:33 +00:00
Nick e817675abc Merge branch 'licious/354' into 'main'
Make pasture blocks connect to all wall-like blocks

Closes #354

See merge request cable-mc/cobblemon!730
2023-10-29 17:20:17 +00:00
Licious 49ebd740b6 Change up pasture block bottom voxelshape to be able to connect to blocks like walls. Remove unnecessary FenceBlockMixin due to changes. 2023-10-29 16:42:37 +00:00
Licious a96b550618 Merge branch 'advancement-fixes-and-additions' into 'main'
Advancement Evolution crash fix

Closes #608

See merge request cable-mc/cobblemon!729
2023-10-29 10:59:51 +00:00
MoeBoy76 b1431b1be1 Update file CHANGELOG.md 2023-10-29 09:47:03 +00:00
MoeBoy76 19400a71f2 added evolution ID 2023-10-29 20:37:56 +11:00
MoeBoy76 87661224da be more verbose with error message and use fancy Kotlin thingy 2023-10-29 19:45:37 +11:00
MoeBoy76 92dc6fefe0 Merge branch 'main' of https://gitlab.com/cable-mc/cobblemon into advancement-fixes-and-additions
# Conflicts:
#	CHANGELOG.md
2023-10-29 19:19:35 +11:00
dhi_holo f7adaa6100 Moving recipes to correct root (4/4) 2023-10-29 01:16:51 +00:00
dhi_holo 7381ef6a02 Moving recipes to correct root (3/4) 2023-10-29 01:16:36 +00:00
dhi_holo a54acc48e7 Moving recipes to correct root (2/4) 2023-10-29 01:16:14 +00:00
dhi_holo 5478db4e32 Moving recipes to correct root (1/4) 2023-10-29 01:15:59 +00:00
Hiroku c99b1503cb Merge branch 'spawning-json-fix' into 'main'
Fixed json spawning files

Closes #650

See merge request cable-mc/cobblemon!723
2023-10-28 23:21:58 +00:00
JPAKx4 8ede54739b Added a tool to check for mistakes in spawning jsons. also fixed the json problems that were reported. 2023-10-28 18:01:18 -05:00
JPAKx4 921f3796c1 Drop is an intended property. 2023-10-28 17:57:32 -05:00
Hiroku 225d170ee3 Merge branch 'licious/620' into 'main'
Add EvolutionTestedEvent

Closes #620

See merge request cable-mc/cobblemon!728
2023-10-28 21:39:53 +00:00
MoeBoy76 5e3479eb8f added catch for bad evolution data crashing the AdvancementHandler and print warning for the evolution that has bad data. 2023-10-29 07:59:50 +11:00
Licious 13379eb8d0 Add EvolutionTestedEvent. 2023-10-28 21:09:43 +01:00
Nick 47f05d0b37 Merge branch 'licious/612' into 'main'
Fixed the SpawnEvent not respecting usage of Cancelable#cancel

Closes #612

See merge request cable-mc/cobblemon!727
2023-10-28 19:30:36 +00:00
Nick 5f6bfa03aa Merge branch 'licious/stat-fix' into 'main'
Fix some more stuff in PokemonStats

See merge request cable-mc/cobblemon!726
2023-10-28 19:08:53 +00:00
Licious 83ac0388d6 Fixed the SpawnEvent not respecting usage of Cancelable#cancel 2023-10-28 19:38:11 +01:00
Licious 454c2b368a Fix coercion for present stat 2023-10-28 19:26:36 +01:00
Licious 4395514376 Fix some more stuff in PokemonStats 2023-10-28 19:25:05 +01:00
Licious 5f55cbb5d3 Implement Apricorn boats & signs, pending texture approval. Fix a few missing item tags in CobblemonItemTags. Added support for injecting into specific points of ItemGroups. 2023-10-28 15:20:08 +01:00
Hiroku a8f7141c14 Merge branch 'main' into 'main'
Update `SpawnAction#run` to `open`

See merge request cable-mc/cobblemon!724
2023-10-28 04:46:23 +00:00
corgi in tights eba32fbf60 Update SpawnAction#run to open 2023-10-28 04:30:58 +00:00
JPAKx4 57a3ad9c9b Added a tool to check for mistakes in spawning jsons. also fixed the json problems that were reported. 2023-10-27 21:36:57 -05:00
JPAKx4 40c2c843a2 Merge remote-tracking branch 'origin/main' 2023-10-27 20:27:39 -05:00
Hiroku b20db43afa Merge branch 'curseMessageFix' into 'main'
Fixed cursed battle message

Closes #632

See merge request cable-mc/cobblemon!722
2023-10-27 22:07:49 +00:00
WaldleuferPlastered_Crab <jeffw773@gmail.com><name@example.com>Hiroku
e81c025152 Fixed cursed battle message
Closes #632

Co-authored-by: Plastered_Crab <jeffw773@gmail.com><name@example.com>
Co-authored-by: Hiroku <paul_l_preston@hotmail.com>
2023-10-27 23:09:30 +02:00
Hiroku 39a9c60a84 Merge branch 'Extra-Brewing-Stand-Hopper-Items' into 'main'
More Brewing Stand Insertables

See merge request cable-mc/cobblemon!717
2023-10-27 20:18:11 +00:00
Hiroku dd3787896b Merge branch 'passengerDefaultPose' into 'main'
Default pose for Passenger Pokemon = PosteType.STAND

Closes #636

See merge request cable-mc/cobblemon!720
2023-10-27 20:17:16 +00:00
Hiroku 80ddbaf50c Merge branch 'main' into 'passengerDefaultPose'
# Conflicts:
#   CHANGELOG.md
2023-10-27 20:16:52 +00:00
Hiroku 62c9654f97 Merge branch 'fix-iv-loading' into 'main'
Query all stats on data read, even if they don't exist. Fixes #625

Closes #625

See merge request cable-mc/cobblemon!721
2023-10-27 20:16:02 +00:00
NickandHiroku 98b5d69d01 Query all stats on data read, even if they don't exist. Fixes #625 2023-10-27 20:16:02 +00:00
Waldleufer 87f0811c2b Default pose for Passenger Pokemon = PosteType.STAND
Added the fix to the changelog
2023-10-27 17:58:36 +02:00
tyzillion dfa104d8cf Updated Pokeball animations and model tweaks.
- Added cries to Raticate, Onix, Unfezant, Bergmite, Avalugg, Boltund, Revavroom.
- Turtwig can now be put on shoulder.
- Added animations for Hitmontop, Tyrogue, and Mightyena.
- Tweaked animations for Bewear, Exeggutor, and Alolan Exeggutor.
- Sized Kantonian Exeggutor down. Still big but not TOO BIG.
2023-10-26 15:07:39 -04:00
tyzillion 6ff53c0be3 Merge branch 'main' of https://gitlab.com/cable-mc/cobblemon into implement_pokemon 2023-10-26 15:04:49 -04:00
Waldleufer ec58079b4f Default pose for Passenger Pokemon = PosteType.STAND 2023-10-26 15:51:15 +02:00
Charzard4261 7c3cf3f498 Simplified the check to just check against the BrewingRecipes.brewableItems list. 2023-10-26 11:01:38 +01:00
Hiroku a7c0a911e3 Merge branch 'pokemon-drop-credit' into 'main'
Credits the player who defeated the pokemon in battle for drops.

See merge request cable-mc/cobblemon!718
2023-10-26 09:54:10 +00:00
Hiroku fee8634661 Merge branch 'ai-actor-tweak' into 'main'
Move choice request to its own method that can be overridden.

See merge request cable-mc/cobblemon!719
2023-10-26 09:53:29 +00:00
Hiroku 68a517332f Merge branch 'clefairy-moon-phase' into 'main'
Fixed Clefairy moon phase issue

See merge request cable-mc/cobblemon!716
2023-10-26 09:52:58 +00:00
dhi_holo 088159bab2 Advancements Fixed
Repairs harvest_apricorn_seed and catch_all_vivillon advancements (can't be merged until confirmation on whether the Vivillon forms are ready for 1.4.1 or not)
2023-10-26 16:02:23 +10:00
tyzillion 6682049be1 Merge branch 'main' of https://gitlab.com/cable-mc/cobblemon into implement_pokemon 2023-10-25 20:17:49 -04:00
tyzillion fa2bbdbb10 Merge remote-tracking branch 'origin/implement_pokemon' into implement_pokemon 2023-10-25 20:17:02 -04:00
Deltric b78bdd727f Move choice request to its own method that can be overridden. 2023-10-25 18:19:09 -05:00
Deltric 610e197236 Credits the player who defeated the pokemon in battle for drops. 2023-10-25 17:43:49 -05:00
Charzard4261 27ee34573d Added PP Restoring and Status Healing items to the BrewingStandBlockEntityMixin isValid check for Hopper Insertion. 2023-10-25 23:07:17 +01:00
Plastered_Crab e4bd024567 Added: "Fixed Moonphases for Clefairy line" 2023-10-25 17:40:06 +00:00
Plastered_Crab e41d94b5dc Update 0173_cleffa.json 2023-10-25 17:38:36 +00:00
Plastered_Crab 00ae3841db Update 0036_clefable.json 2023-10-25 17:37:44 +00:00
Plastered_Crab b0a54a408f Update 0035_clefairy.json 2023-10-25 17:37:10 +00:00
Hiroku a34735891a Merge branch 'sound' into 'main'
Sound stuff

See merge request cable-mc/cobblemon!715
2023-10-25 10:05:20 +00:00
Sterrezo 17552017f9 Update CHANGELOG.md 2023-10-25 11:31:17 +02:00
Sterrezo d90cd5b9a8 Merge branch 'main' into sound 2023-10-25 11:30:13 +02:00
Sterrezo 33fe1a7c32 Made sounds.json easier to look at 2023-10-25 11:27:13 +02:00
Hiroku 17096f3bb7 Merge branch 'cooking-with-berries' into 'main'
Two Tags

Closes #598

See merge request cable-mc/cobblemon!703
2023-10-25 07:36:18 +00:00
Hiroku 81f733e89f Merge branch 'main' into 'cooking-with-berries'
# Conflicts:
#   CHANGELOG.md
2023-10-25 07:08:43 +00:00
Hiroku fac7419225 Merge branch 'Licenses-are-fun' into 'main'
Fixing Licenses

See merge request cable-mc/cobblemon!714
2023-10-25 06:56:30 +00:00
JPAKx4 69d174b6a6 Merge remote-tracking branch 'origin/main' 2023-10-24 19:07:22 -05:00
Hiroku d66f534b95 Merge branch 'roggenrola_drop_fix' into 'main'
fixing drops for roggenrola

See merge request cable-mc/cobblemon!713
2023-10-24 20:14:24 +00:00
Waldleufer 6f342045f4 Fixing Licenses for Jordan
I'm not mad, just disappointed.
2023-10-24 22:01:56 +02:00
Waldleufer 726aeac836 fixing drops for roggenrola
and some auto reformatting that happens when the .py script runs.
2023-10-24 21:22:05 +02:00
JPAKx4 f01c5a5ceb Merge remote-tracking branch 'origin/main'
# Conflicts:
#	CHANGELOG.md
2023-10-23 19:31:52 -05:00
Licious 5876d83147 Merge branch 'chansey_drop_fix' into 'main'
fix drops for chansey/blissey

Closes #628

See merge request cable-mc/cobblemon!712
2023-10-23 19:01:20 +00:00
Lily ae1a55fa98 fix drops for chansey/blissey 2023-10-23 18:14:14 +00:00
Hiroku 417fefa911 Merge branch 'Brewing-Stand-Hopper-Interaction' into 'main'
Allow Hoppers to insert Medicinal Brew / Poke Potions into Brewing Stands

See merge request cable-mc/cobblemon!698
2023-10-23 05:11:12 +00:00
Hiroku e30cc3dce8 Merge branch 'main' into 'Brewing-Stand-Hopper-Interaction'
# Conflicts:
#   CHANGELOG.md
2023-10-23 03:59:30 +00:00
Hiroku 63f721bc9b Merge branch 'main' into 'main'
Created a system to add blocks to the flammable registry in FireBlock and...

Closes #553

See merge request cable-mc/cobblemon!711
2023-10-23 00:33:04 +00:00
JordanandHiroku 27248fd17d Created a system to add blocks to the flammable registry in FireBlock and... 2023-10-23 00:33:04 +00:00
JPAKx4 c198aee827 Moved the array into the init method and adjusted wording to be better. 2023-10-22 19:22:16 -05:00
JPAKx4 a8c6d58499 Merge remote-tracking branch 'origin/main' 2023-10-22 19:20:57 -05:00
Hiroku 9e748cc9cf Merge branch 'mintedNatureQOLChanges' into 'main'
Italicized Nature and Hovertext for Minted Natures in Info, PC and Trade Screen.

Closes #480

See merge request cable-mc/cobblemon!702
2023-10-22 23:32:00 +00:00
Waldleufer 5890918e04 Added MPL Header 2023-10-22 21:49:49 +02:00
Waldleufer c0567ac11f The nature of Cobblemon will now indicate minted Nature. 2023-10-22 21:38:18 +02:00
Waldleufer 5036e334dc Compostability 2023-10-22 21:23:01 +02:00
Waldleufer 9f798cddf5 Display MintedNature Italicized and with Tooltip showing the Mint used. 2023-10-22 21:09:48 +02:00
Waldleufer eb2828e0a4 Moved Minted Nature reformatting to its own file. 2023-10-22 21:09:48 +02:00
Waldleufer 53f127fc23 added onHover for Text 2023-10-22 21:09:48 +02:00
Waldleufer c463bb6e06 Compostable integration 2023-10-22 21:09:17 +02:00
Waldleufer 4e9d45d38c MutableText.onHover() now is actually drawn if text is being hovered
#480
2023-10-22 21:08:15 +02:00
Waldleufer 4e2f7d3bc5 InfoWidget refactored into multiple smaller widgets.
#480
2023-10-22 21:08:15 +02:00
Waldleufer 8975b099ad InfoWidget reworked.
#480
2023-10-22 21:08:09 +02:00
Waldleufer 308380706a Implemented Hovertext and italicized Nature for Minted Natures in Info and Trade Screen.
I am sure there is a better way to do that though.

#480
2023-10-22 21:01:31 +02:00
Waldleufer ef80924526 Display MintedNature Italicized and with Tooltip showing the Mint used. 2023-10-22 20:58:43 +02:00
Waldleufer fadf57046d Moved Minted Nature reformatting to its own file. 2023-10-22 20:44:17 +02:00
JPAKx4 13cedaaf73 Refactored the flammable blocks system, it's now in one centralized place and has comments to make things clearer. The values are all based on the vanilla counterparts. 2023-10-22 10:08:27 -05:00
Waldleufer 0a0806716b added onHover for Text 2023-10-22 15:18:35 +02:00
Waldleufer af59cb5e58 Using Map for better performance 2023-10-22 15:16:22 +02:00
Charzard4261 c0f8e37206 Merge branch 'main' into 'Brewing-Stand-Hopper-Interaction'
# Conflicts:
#   CHANGELOG.md
2023-10-22 13:14:34 +00:00
Waldleufer e64aaf66ab MutableText.onHover() now is actually drawn if text is being hovered
#480
2023-10-22 14:49:58 +02:00
Waldleufer a946dfea1f InfoWidget refactored into multiple smaller widgets.
#480
2023-10-22 14:49:25 +02:00
dhi_holo f2c459cc06 Pain, Suffering Even
Moved the tags to only be in their respective modloaders, that took way too long to figure out, updated the Forge version to what Farmer's Delight uses because of failed testing, and added this to the changelog
2023-10-22 15:39:19 +10:00
Jordan 6f12f53e85 Update CHANGELOG to include branch changes 2023-10-22 04:14:11 +00:00
JPAKx4 073ee8e283 Merge https://gitlab.com/superpizzaman10/cobblemon-compost-fix 2023-10-21 22:44:25 -05:00
JPAKx4 d3a5ad8efa Created a system to add blocks to the flammable registry in FireBlock and added apricorn wood to it. 2023-10-21 22:43:19 -05:00
Jordan 62a2dcc606 Merge branch cobblemon:main into main 2023-10-22 03:37:25 +00:00
dhi_holo a7f71eb437 Merge branch 'main' into cooking-with-berries 2023-10-22 13:03:28 +10:00
JPAKx4 b65dab7f30 Merge remote-tracking branch 'origin/main' 2023-10-21 20:15:53 -05:00
Hiroku ac76878002 Merge branch 'main' into 'main'
Simplified composting as well as made mint, apricorn, and berries more consistent.

See merge request cable-mc/cobblemon!710
2023-10-22 01:13:46 +00:00
JordanandHiroku fe219e52e6 Simplified composting as well as made mint, apricorn, and berries more consistent. 2023-10-22 01:13:45 +00:00
Jordan bfd28ec9b0 Update CHANGELOG.md 2023-10-22 01:05:18 +00:00
JPAKx4 1063441b0e Merge https://gitlab.com/superpizzaman10/cobblemon-compost-fix into tempBranch 2023-10-21 18:39:29 -05:00
JPAKx4 4e89f45253 Simplified composting as well as made mint, apricorn, and berries more consistent. 2023-10-21 16:00:18 -05:00
Sterrezo 2798f73397 Fixed a couple missing cries
Fixed typo in farfetchd_galar.animation.json, added a cry provider to QuaxwellModel.kt, added a placeholder cry for Raticate, added missing sound keyframes to Onix, Unfezant, Bergmite, Avalugg, Boltund, Revavroom
2023-10-21 20:13:25 +02:00
dhi_holo 56aa5ae8d8 Merge branch 'main' into cooking-with-berries 2023-10-21 12:53:21 +10:00
Hiroku 156a7a70eb Merge branch 'battle-potion-fix' into 'main'
Fix Potions, Super Potions, and Hyper Potions not working during Battle

See merge request cable-mc/cobblemon!708
2023-10-21 02:21:09 +00:00
Hiroku 3b13b9f246 Merge branch 'PlasteredCrab-main-patch-56636' into 'main'
Update CHANGELOG.md to include Potion use during battle issue

See merge request cable-mc/cobblemon!709
2023-10-21 02:21:03 +00:00
Plastered_Crab 0a8d920285 Update CHANGELOG.md to include Potion use during battle issue 2023-10-21 02:15:28 +00:00
Plastered_Crab f5418a8088 Update PotionItem.kt to fix Potions, Super Potions, and Hyper Potions not working during Battle 2023-10-21 02:07:00 +00:00
Hiroku cae097bf2c Merge branch 'berry-juice-bowl' into 'main'
Fixed Berry Juice so bowl is given back to player

See merge request cable-mc/cobblemon!706
2023-10-21 01:56:36 +00:00
Hiroku f760003c3a Merge branch 'PlasteredCrab-main-patch-58336' into 'main'
Update CHANGELOG.md to include Berry Juice changes

See merge request cable-mc/cobblemon!707
2023-10-21 01:56:17 +00:00
Plastered_Crab 38f70c5960 Update CHANGELOG.md to include Berry Juice changes 2023-10-21 01:55:00 +00:00
Plastered_Crab 81b00d7f85 Fixed Berry Juice so that when it is used in and outside of Battle when in Survival Mode a wooden bowl is given back to the player 2023-10-21 01:47:43 +00:00
Paul 948ceeaa8d Merge remote-tracking branch 'origin/main' 2023-10-21 10:14:25 +10:00
Paul 1eda446897 Fixed bad PC loading from JSON and NBT store adapters due to 392b6993 2023-10-21 10:14:15 +10:00
Charzard4261 49d03c0336 Merge branch 'main' into 'Brewing-Stand-Hopper-Interaction'
# Conflicts:
#   CHANGELOG.md
2023-10-20 21:57:53 +00:00
Licious c5d254cca7 Merge branch 'Berries-On-Modded-Farmland' into 'main'
Allow Berries on Modded Farmland

See merge request cable-mc/cobblemon!705
2023-10-20 20:29:52 +00:00
Waldleufer 4f7fda1e96 InfoWidget reworked.
#480
2023-10-20 20:22:01 +02:00
Charzard4261 d3e10cb570 Merge remote-tracking branch 'origin/Berries-On-Modded-Farmland' into Berries-On-Modded-Farmland 2023-10-20 19:12:34 +01:00
Charzard4261 51d7d2cb04 Added Forge and Fabric (unofficial but according to their standards) farmlands tag to facilitate better compatibility, as advised by Licious. 2023-10-20 19:12:19 +01:00
Charzard4261 ac53d2da95 Merge branch 'main' into 'Berries-On-Modded-Farmland'
# Conflicts:
#   CHANGELOG.md
2023-10-20 16:43:45 +00:00
Charzard4261 17e41f5f0b Updated CHANGELOG.md 2023-10-20 17:30:29 +01:00
Charzard4261 4bd70698ce Added a "below.block is FarmlandBlock" check for Berry blocks to allow them to be placed on other blocks that extend from it. 2023-10-20 17:25:57 +01:00
Sterrezo 23b750d5e9 Added a sound for giving Pokemon items and taking items from them 2023-10-20 17:46:43 +02:00
Charzard4261 ab2b67c426 Merge branch 'main' into 'Brewing-Stand-Hopper-Interaction'
# Conflicts:
#   CHANGELOG.md
2023-10-20 12:17:00 +00:00
Hiroku d68c912ca6 Merge branch 'Dispenser-Shear-Apricorn-Fix' into 'main'
Fixed Dispensers being unable to shear grown Apricorns

See merge request cable-mc/cobblemon!701
2023-10-20 09:32:17 +00:00
Hiroku c391d1a5e0 Merge branch 'main' into 'Dispenser-Shear-Apricorn-Fix'
# Conflicts:
#   CHANGELOG.md
2023-10-20 07:42:04 +00:00
Nick 0af39118eb Merge branch 'multi-party-fix' into 'main'
Allows PlayerPartyStore's to have their own unique storage id, separate from the player uuid.

See merge request cable-mc/cobblemon!704
2023-10-20 07:21:03 +00:00
Deltric 392b69937f Allows PlayerPartyStore's to have their own unique storage id, separate from the player uuid. 2023-10-20 01:53:32 -05:00
Hiroku e32af733f1 Merge branch 'more-mod-compat' into 'main'
Fix compatibility with the Forge version of Carry On, add compatibility for Adorn.

See merge request cable-mc/cobblemon!697
2023-10-20 06:41:13 +00:00
dhi_holo e1509c9dab Two Tags
Adds Cobblemon Berries to the Forge and Fabric general tags for berries (which aren't core to their APIs), allowing for Farmer's Delight compatibility, unsure if anything else actually uses it but eh, doesn't hurt to have this set up
2023-10-20 12:30:14 +10:00
Waldleufer 1cb6baee59 Implemented Hovertext and italicized Nature for Minted Natures in Info and Trade Screen.
I am sure there is a better way to do that though.

#480
2023-10-20 00:09:19 +02:00
Sterrezo 9403cb6296 Merge branch 'main' into sound 2023-10-19 23:59:55 +02:00
Sterrezo fd157fae4f Lowered the volume of all cries 2023-10-19 23:59:08 +02:00
Charzard4261 9ca472ccaf Fixed Dispensers being unable to shear grown Apricorns. 2023-10-19 11:48:27 +01:00
Charzard4261 13b7e0d418 Update CHANGELOG.md 2023-10-19 10:20:07 +00:00
Charzard4261 a6ddc1e4ae Add missing MAX_POTION check. 2023-10-19 00:30:10 +01:00
Charzard4261 a5b1b87ec5 Add a new Mixin for BrewingStandBlockEntity that allows for Hopper interaction with Cobblemon POTIONs and MEDICINAL_BREW. 2023-10-18 22:24:59 +01:00
Licious b3255045fa Fix compatibility with the Forge version of Carry On, add compatibility for Adorn. 2023-10-18 22:17:35 +01:00
Hiroku 90f3acebac Merge branch 'main' into 'main'
Check chunks are loaded before running AreaSpawner

See merge request cable-mc/cobblemon!692
2023-10-18 20:00:56 +00:00
Nick 0da91fb255 Merge branch 'Miltank-Milk-Revert-Fix' into 'main'
Fix Miltank Bucket Reversion

See merge request cable-mc/cobblemon!696
2023-10-18 18:22:23 +00:00
Charzard4261 ba3b26ac74 Fix desync that was causing milk buckets occasionally reverting to regular buckets by removing the ServerClientPlayer check in PokemonEntity.interactMob for Shearing and Milking, and modifying it slightly to be the same calls as CowEntity (minus the SFX). 2023-10-18 17:49:47 +01:00
Xander Forrest 966761776d Merge branch cobblemon:main into main 2023-10-18 10:20:29 +00:00
Nick 24f07c58a0 Merge branch 'fabric-roots-spreading-fix' into 'main'
Fix Fabric big root spreading.

See merge request cable-mc/cobblemon!695
2023-10-17 23:06:24 +00:00
Xander Forrest a8b5f649a8 Merge branch cobblemon:main into main 2023-10-17 21:49:58 +00:00
Xander Forrest 295c73ae69 Don't create chunk in SpawningProspector 2023-10-17 22:47:38 +01:00
Xander Forrest 899bdb38ac Removes ServerChunkManagerMixin.java
Update chunk logic in AreaSpawner.constrainArea to reflect this
Updated Prospector to not use SCCM when getting chunks
2023-10-17 21:40:47 +01:00
Nick f30e5bda1e Merge branch 'improve-mongo-db-store-override' into 'main'
Improve the ability to reuse and override the MongoDBStoreAdapter.

See merge request cable-mc/cobblemon!694
2023-10-17 19:50:18 +00:00
Licious 76c870b472 Fix Fabric big root spreading. 2023-10-17 20:40:43 +01:00
Nick 963448e173 Merge branch 'composter-registration-changes' into 'main'
Update Composter block valid item registration

See merge request cable-mc/cobblemon!693
2023-10-17 19:30:03 +00:00
Licious 48d2fc6e2e Improve the ability to reuse and override the MongoDBStoreAdapter. 2023-10-17 20:08:49 +01:00
Licious 5868d39431 Rework Composter item registration to be platform implementation specific. 2023-10-17 19:53:48 +01:00
Xander Forrest c47b3a21db Move isBoxLoaded to WorldExtensions.kt 2023-10-17 10:41:47 +01:00
Xander Forrest 0d12fb1f1c When running AreaSpawner, check area box's chunks are all loaded before attempting to get all entities in the area 2023-10-17 10:18:05 +01:00
Hiroku 78c7188a11 Merge branch 'update_version' into 'main'
update version

See merge request cable-mc/cobblemon!691
2023-10-16 03:49:53 +00:00
Hiroku ff5f63a998 Merge branch 'main' into 'update_version'
# Conflicts:
#   gradle.properties
2023-10-16 03:49:34 +00:00
Lily b9a8a9be11 update version 2023-10-15 22:24:29 -04:00
Paul 2046482252 Turn snapshot back on, 1.4 looks good 2023-10-14 17:46:43 +10:00
Hiroku 6a737999a9 Merge branch 'sendingOutShoulderedCobblemon' into 'main'
Dismounting Shouldered Cobblemon

Closes #473

See merge request cable-mc/cobblemon!680
2023-10-14 07:04:34 +00:00
WaldleuferandHiroku 89d37e583b Dismounting Shouldered Cobblemon 2023-10-14 07:04:33 +00:00
Paul e077a5d453 Not snapshot 2023-10-14 10:32:40 +10:00
Paul e7208ed396 Changelog polish 2 [skip-ci] 2023-10-14 10:31:27 +10:00
Paul 27f8bbf029 Changelog polish 2023-10-14 10:29:36 +10:00
Hiroku 2f97a69b8c Merge branch 'implement_pokemon' into 'main'
LAST MERGE REQUEST FOR ME TONIGHT? LAST MINUTE?

See merge request cable-mc/cobblemon!690
2023-10-13 23:44:13 +00:00
tyzillion 79d67389ba Merge remote-tracking branch 'origin/implement_pokemon' into implement_pokemon 2023-10-13 19:36:11 -04:00
tyzillion 61f2150f2e Fixed Exeggcute looping faint. Fixed Baltoy texture zfighting. Fixed Wishiwashi framing. 2023-10-13 19:36:00 -04:00
tyzillion 5d63c8fe06 Merge branch 'main' of https://gitlab.com/cable-mc/cobblemon into implement_pokemon 2023-10-13 19:35:16 -04:00
Hiroku 0d109a64fd Merge branch 'scriptedDropsCSVtoJson' into 'main'
Automating the manual Drop Json editing

See merge request cable-mc/cobblemon!686
2023-10-13 23:34:54 +00:00
Hiroku 5daef700e7 Merge branch 'gimmick_data_fix' into 'main'
Remove gmax factor from natural spawns.

See merge request cable-mc/cobblemon!689
2023-10-13 23:15:18 +00:00
Paul 21bd1550f0 Fixed exeggcute and pikachu evolutions to kanto forms not undoing alolan flag 2023-10-14 09:13:28 +10:00
Segfault Guy 0d4f63ba01 Remove gmax factor from natural spawns. 2023-10-13 19:12:22 -04:00
Paul 946cff21fb Merge remote-tracking branch 'origin/main' into implement_pokemon 2023-10-14 08:43:40 +10:00
Paul 8a2291cd6e Fixed form order for exeggcute and pikachu 2023-10-14 08:43:33 +10:00
Hiroku 304ac0e07a Merge branch '1.4-fixes' into 'main'
Fixed underscores not really working as species names, fixed recalls not working (that was close)

See merge request cable-mc/cobblemon!688
2023-10-13 22:27:46 +00:00
tyzillion 3cac1138fb 😂😂😂 ˙sǝxᴉɟ uoᴉʇnloʌǝ ǝʇnuᴉɯ ʇsɐl 2023-10-13 18:05:33 -04:00
Paul b19a11f8ab Merge remote-tracking branch 'origin/main' into 1.4-fixes 2023-10-14 07:41:25 +10:00
Hiroku cad64ae24b Merge branch 'shedninja-evolution-fixes' into 'main'
Shedinja fixes

Closes #561

See merge request cable-mc/cobblemon!687
2023-10-13 21:40:23 +00:00
Paul 9036909968 Fixed underscores not really working as species names, fixed recalls not working (that was close) 2023-10-14 07:40:08 +10:00
MoeBoy76 53b98e8008 order of operations 2023-10-14 08:31:34 +11:00
MoeBoy76 574fd92827 added trigger to Shedinja evolution code and made Creative not care about Pokeballs 2023-10-14 08:06:31 +11:00
Waldleufer e6d7513c20 Merge branch 'main' into 'scriptedDropsCSVtoJson'
# Conflicts:
#   common/src/main/resources/data/cobblemon/species/generation1/golem.json
#   common/src/main/resources/data/cobblemon/species/generation1/graveler.json
#   common/src/main/resources/data/cobblemon/species/generation5/boldore.json
#   common/src/main/resources/data/cobblemon/species/generation5/gigalith.json
2023-10-13 20:47:11 +00:00
Waldleufer e36252318a Removed dangling Import. 2023-10-13 22:37:58 +02:00
Waldleufer 5d5dbb9e79 Fruits of the labor. 100% Datasheet and code consistency. 2023-10-13 22:28:04 +02:00
Hiroku 4036592c9a Merge branch 'go-to-sleep-flywheel' into 'main'
Remove flywheel, for now

See merge request cable-mc/cobblemon!684
2023-10-13 20:27:23 +00:00
Waldleufer c0ddbad4f5 Pulling fresh data from spreadsheet
Also added a printout for Troublesome IDs. (missing in the natural language to IDs map)
2023-10-13 22:19:50 +02:00
Paul fa1f485cd2 Merge remote-tracking branch 'origin/main' into go-to-sleep-flywheel
# Conflicts:
#	common/src/main/kotlin/com/cobblemon/mod/common/client/render/block/BerryEntityInstance.kt
2023-10-14 06:18:35 +10:00
Waldleufer b5aeb0e5f7 Removed debug logs. 2023-10-13 22:18:13 +02:00
Paul 9c2680783a Reapply a fix from main for when flywheel is turned back on 2023-10-14 06:09:33 +10:00
Hiroku b7ed72241b Merge branch 'berry_bugfixes' into 'main'
No longer just berry bugfixes

Closes #568

See merge request cable-mc/cobblemon!685
2023-10-13 20:07:54 +00:00
Hiroku 689f9eabc0 Merge branch 'lang-updates' into 'main'
Updated heaps of lang

See merge request cable-mc/cobblemon!670
2023-10-13 20:07:02 +00:00
Hiroku 4fd24be1d3 Merge branch '1.4-fixes' into 'main'
1.4 fixes

Closes #564, #569, #578, #573, and #576

See merge request cable-mc/cobblemon!683
2023-10-13 20:06:57 +00:00
Paul 7579203527 Merge remote-tracking branch 'origin/main' into berry_bugfixes
# Conflicts:
#	common/src/main/resources/data/cobblemon/species/generation5/boldore.json
#	common/src/main/resources/data/cobblemon/species/generation5/gigalith.json
#	common/src/main/resources/data/cobblemon/species/generation5/roggenrola.json
2023-10-14 06:04:24 +10:00
Martin Wagner 9e3dd9373c Use correct indent (2). 2023-10-13 21:44:18 +02:00
Martin Wagner c9b9ac7d07 If the spreadsheet does not contain drop data, then remove any drops. 2023-10-13 21:26:53 +02:00
Martin Wagner dddae893cd Polishing of csv to json skript 2023-10-13 19:42:17 +02:00
Lily 86508801d3 Update destiny_knot.json 2023-10-13 17:24:48 +00:00
Lily de44411ad2 added everstone drop to geodude and roggenrola lines 2023-10-13 17:17:26 +00:00
Waldleufer e59aa01345 Logging some info for testing 2023-10-13 17:46:36 +02:00
Waldleufer 3f3e8b5747 Parsing Drops from spreadsheet 2023-10-13 15:36:45 +02:00
Waldleufer bb769fa165 get list of all files we need to change. 2023-10-13 14:15:14 +02:00
Waldleufer 163218c0a8 Creation of a python script to automate drop configuration 2023-10-13 14:07:16 +02:00
Paul e61eadb834 Will this make the license thing shut up no.2 2023-10-13 20:21:19 +10:00
Paul 29c8bbe9e9 Will this make the license thing shut up 2023-10-13 18:27:38 +10:00
Paul 7c42390515 Keep the license bit in here mate that's alright 2023-10-13 18:06:33 +10:00
Paul ff84ca69cd Updated pt_br and zh_cn 2023-10-13 15:33:22 +10:00
Paul dda3c4e981 Merge branch 'main' into lang-updates 2023-10-13 15:28:30 +10:00
Paul 1570bbf42b Remove flywheel, for now 2023-10-13 14:59:23 +10:00
Paul 41cfe79b0e Updated mutations for Haban, Sitrus, Hopo. Closes #576 2023-10-13 09:28:57 +10:00
Paul dc4e3dc39c Added 'biomeAnticondition' to BiomeRequirement, closes #573 2023-10-13 09:18:31 +10:00
Paul d100537d41 Changed hide overlay default keybind from P to O, closes #578 2023-10-13 09:06:10 +10:00
Paul fe218399e2 Fixed possible stack overflow removing owned pokemon from the world, closes #569 2023-10-13 09:05:31 +10:00
Paul 8f4a4a7e45 Fixed flower models not showing, closes #564 2023-10-13 08:58:38 +10:00
Lily de04379297 fixed broken advancement for getting an apricorn sprout 2023-10-10 20:23:56 -04:00
Lily 10bf9d1abd berries will now drop when broken. Closes #568 2023-10-10 19:49:22 -04:00
Paul 54cd0ba700 Updated ru_ru 2023-10-08 07:58:01 +10:00
Paul 46b4bfa7ea Updated pt_pt 2023-10-07 20:59:04 +10:00
Paul f5a308e579 Updated heaps of lang 2023-10-07 13:21:28 +10:00
2172 changed files with 66716 additions and 20852 deletions
+30
View File
@@ -0,0 +1,30 @@
<!-- 1. START HERE: (Before filling all this out, please quickly go to the list of all issues: (https://gitlab.com/cable-mc/cobblemon/-/issues/?sort=created_date&state=all) and do a quick search to see if your issue has already been reported. If it has, please add a comment to the existing issue instead of creating a new one.)-->
<!-- 2. If the issue was not already reported, please fill out the following template. -->
<!-- 3. If you do not know something, don't worry! Just fill out as much as you can to make sure the issue can get fixed asap. -->
## Summary
(Please summarize the bug encountered concisely)
## Steps to reproduce
(How one can reproduce the issue - this is very important)
## What is the current bug behavior?
(What actually happens)
## What is the expected correct behavior?
(What you should see instead)
## Cobblemon Version and Mod Loader
(Are you using Forge or Fabric? And what version of Cobblemon are you using?)
## Mods used besides Cobblemon
(Did you have any other mods installed besides Cobblemon? If so, please list them here)
## Relevant logs, screenshots and/or videos
(Paste any relevant logs - use code blocks (```) at the start and end to format console output, logs, and code, as
it's very hard to read otherwise. Or just put a link here)
## Additional Information
(If you can, link to the line of code that might be responsible for the problem, or any other info that might be useful)
/label ~bug
@@ -0,0 +1,31 @@
<!-- 1. START HERE: (Before filling all this out, please quickly go to the list of all issues: (https://gitlab.com/cable-mc/cobblemon/-/issues/?sort=created_date&state=all) and do a quick search to see if your feature was already requested. If it is, please add a comment to the existing issue instead of creating a new one.)-->
<!-- 2. If the feature request was not already reported, please fill out the following template. -->
<!-- 3. If you do not know something, don't worry! Just fill out as much as you can. -->
<!-- 4. The more info you provide here, the greater the chance of it being considered by the Design team. -->
## Summary
(Please summarize your feature request concisely)
## What are the projected benefits of this feature?
- (List)
- (benefits)
- (here)
## What could speak against this feature?
- (List)
- (possible)
- (cons)
## Why do you think the benefits outweigh the cons?
(Explain why you think the benefits outweigh the cons)
## Mods involved besides Cobblemon
(Does your suggestion require any other mods besides Cobblemon? If so, please list them here)
## Sketches, screenshots and/or videos
(Feel free to add any sketches, screenshots or videos that might help the Design team understand your suggestion)
## Additional Information
(Is there anything else you would like to add?)
/label ~feature ~suggestion ~needs-design
+210 -78
View File
@@ -1,37 +1,165 @@
# Changelog
## [1.?.?]()
## [1.4.1 (December 23rd, 2023)](#1-4-1)
### Additions
- Added battle spectating. Press R on a player in a battle and you can spectate and bully them for their tactics.
- Added the Litwick and Drifloon lines.
- Cobblemon now has compatibility with [Adorn](https://modrinth.com/mod/adorn), allowing you to craft Apricorn wood furniture.
- Berries can now be used in recipes from [Farmer's Delight](https://modrinth.com/mod/farmers-delight) and [Farmer's Delight (Fabric)](https://modrinth.com/mod/farmers-delight-fabric), as well as any other mods using the same berry tags.
- Boats, signs and hanging signs are now craftable with Apricorn wood.
- Added the Fairy Feather, Iron Ball, Cleanse Tag, Flame Orb, Life Orb, Smoke Ball, and Toxic Orb held items.
- Added the Inferno, Void, and Forsaken patterns for Vivillon. These can be obtained by evolving a Spewpa in the Nether, End, or Deep Dark respectively.
- Bees can now be fed using Pep-Up Flowers.
- Mooshtank can now be milked with a bowl for Mushroom Stew.
- Updated Showdown version to use generation 9 battle data.
- Added cries to Beldum, Metang and Metagross.
- Added a /bedrockparticle command to run Snowstorm-format particle effects.
- Added data for Dipplin, Fezandipiti, Munkidori, Ogerpon, Okidogi, Poltchageist and Sinistcha.
### Changes
- Using Potions, Status Heals, Ethers, and Antidotes will now return a glass bottle
- Using a Remedy, Fine Remedy, or Superb Remedy will no longer lower friendship with a Pokémon.
- The Healing Machine now has a [much more difficult recipe](https://wiki.cobblemon.com/index.php/Healing_Machine), placing it later game.
- Made the EXP. Share recipe cheaper.
- Turtwig can now be put on your shoulder.
- Updated Zubat line model, texture, and animations.
- Updated Geodude line models and textures.
- Added animations for Hitmontop, Tyrogue, and Mightyena.
- Tweaked animations for Dusknoir, Ratatta, Bewear, Exeggutor, and Alolan Exeggutor.
- Sized Kantonian Exeggutor down. Still big, but not TOO big.
- Tweaked cries for Pikachu, Raichu and Alolan Raichu.
- Fixed Swimming behaviors for Wimpod line, Oshawott line, Quaxly line, and Clodsire
- Changed the way level scaling works in spawning. By default, anything with a spawn range of up to 5 either side of the party highest level and everything else will spawn per its specified ranges.
- The nature of Pokémon will now be displayed italicized when a mint has been applied. Hovering over the nature will display the mint that was applied.
- Slightly lowered the volume of all cries.
- Giving Pokémon items now plays a sound
- Updated the Poké Ball model and animations.
- Pasture blocks will now also connect their bottom left and right sides to walls, iron bars, glass panes, and any other modded block that follows the same connection rules.
- The config option `consumeHeldItems` has been removed, please see the Datapack & Resourcepack Creators section for instructions on the updated method.
- Heal Powder can now be composted with a 75% chance of adding a layer
- Mental, Power, White, and Mirror Herbs can now be composted with a 100% chance of adding a layer.
- Added glowing eyes to Hoothoot and Noctowl.
- Mining Evolution Stone Ores with a Fortune pickaxe will now increase the amount of items received.
- Black Augurite can now be used to craft stone axes and obsidian.
- Using Experience Candies brings up the Party Pokémon Select screen when not targeting a Pokémon.
- Added tab completion for statuses to commands.
- Remedies can now be cooked in a Smoker and on a Campfire.
- Vertically flipped the Destiny Knot recipe.
### Fixes
- Fixed Raticate, Onix, Unfezant, Bergmite, Avalugg, Boltund and Revavroom cries not playing.
- Fixed Alolan Ratticate animations causing a crash.
- Fixed Quaxwell not doing its cry.
- Fixed Shroomish not using its idle.
- Fixed how Weight and Height is calculated for Pokémon, fixing the damage from moves like Low Kick.
- Fixed a staggering number of battle messages.
- Fixed various stone related blocks not being valid for Big Roots to spread onto on the Fabric version.
- Updated the registration of compostable items to improve compatibility with Fabric forks such as Quilt. Please note this does not mean we officially support Quilt, this change was only done since it was possible by correcting the registration to use the new intended way in the Fabric API.
- Fixed Dispensers being unable to shear grown Apricorns.
- Fixed Bowl not being given back to player after using Berry Juice
- Fixed missing text for attempting to catch an uncatchable Pokémon
- Fixed Moonphases for Clefairy line
- Fixed issue where Potions, Super Potions, and Hyper Potions did not work during battle
- Fixed the compatibility patch with the Forge version of [Carry On](https://modrinth.com/mod/carry-on) due to a bug on the mod, the Fabric version was unchanged and is still compatible.
- Added the ability to place Berries on modded Farmland blocks.
- Shouldered Pokémon now hop off when selected in team and R is pressed. This also is in effect in battles leading to shouldered Pokémon jumping of the shoulder of the trainer when it is their turn.
- Made more items compostable and changed the process for making items compostable.
- Added the ability for Hoppers to fill Brewing Stands with Medicinal Brews and Potions.
- Apricorn blocks are now flammable. Probably should have started that way, but we got there.
- The default pose for Pokémon being passengers is now "standing".
- Fixed issue where some IVs were changing every time a player logged back in.
- Fixed advancement crash from bad datapack evolution data.
- Fixed global influences being applied to TickingSpawners twice.
- Reverted the default SpawningSelector back to FlatContextWeightedSelector. This fixes multiple weight related issues, including weights with SpawningInfluences.
- Apricorn Planting advancement should work again.
- Advancement "Vivillonaire" should now allow High Plains and Icy Snow Vivillon to register.
- Fixed the last battle critical hits evolution requirement not working.
- Fixed the damage taken evolution requirement not saving progress.
- Fixed the defeated Pokémon evolution requirement not saving progress.
- Fixed potion brewing recipes not showing up JEI and similar mods on the Forge version.
- Fixed an exploit that could convert a single piece of Blaze Powder into an extra Medicinal Brew on the Forge version.
- Fixed an issue where health percentages would show incorrectly after healing
- Fixed the move Revival Blessing not allowing you to select from fainted party members.
- Fixed villagers not being able to pick up and plant mint seeds, vivichoke seeds, and revival herbs.
- Fixed Exeggcute faint.
- Fixed various spawn configuration issues across the board.
- Fixed a possible visual duplication of sent out Pokémon.
- Fixed battle text for Trace, Receiver, and Power of Alchemy.
- Fixed tooltips being appended too late in items.
- Fixed battles ending background music when battle music is not present.
- Fixed battles ending background music, instead of pausing, when battle music is played.
- Fixed a bunch of regionals to actually be obtainable, namely the unmodelled ones
- Fixed battle text for moves that were missing.
- Fixed a formatting error that affected Pokémon nicknames when the storage type is JSON.
- Fixed a crash that could occur on some servers relating to chunk loading and teleporting.
- Fixed an issue with Inkay's evolution requirement.
- Fixed conflicting evolution requirements that would cause the Ocean, River, Sun, and Tundra variants of Vivillon to be unobtainable through evolution.
- Fixed the Modern variant of Vivillon not being obtainable through evolution.
- Fixed Pokémon pathing through berry bushes, harming themselves in the process.
### Developer
- Various breaking changes have been made to ElementalTypes, Moves and other registries, Cobblemon has migrated to make use of proper Minecraft registries.
- DamageCategory is now an Enum.
- Gender has been moved to an API package.
- Fixed the `SpawnEvent` not respecting usage of `Cancelable#cancel`.
- Added the `EvolutionTestedEvent`, this allows listening and overriding the final result of evolution requirement tests.
- Added utility script that can be used to generate all Spawn JSONS for all pokemon from the spawning spreadsheet in 1 click ([cobblemon_spawn_csv_to_json.py](utilityscripts%2Fcobblemon_spawn_csv_to_json.py)).
- The `HeldItemManager` has a new method `shouldConsumeItem`, this will return false by default to prevent breaking changes, see the documentation and update your implementations as needed.
- Added and implemented minSkyLight and maxSkyLight as config options for SpawnConditions
- Player specific battle themes can now be assigned to `PlayerData#battleTheme`.
- Changed design of `BattleStartedPreEvent`. Will now expose the `PokemonBattle`.
### Datapack & Resourcepack Creators
- Pokémon types can now be created via datapacks. Data path is ``your_mod_namespace/cobblemon/elemental_types/path_to_your_file``.
- Custom moves are now possible via datapacks, these require JavaScript/TypeScript programming knowledge. Data path is ``your_mod_namespace/cobblemon/moves/path_to_your_file``.
- Pokémon species data path has been changed to ``your_mod_namespace/cobblemon/species/path_to_your_file``.
- Added 3 new item tags: `cobblemon:held/consumed_in_npc_battle`, `cobblemon:held/consumed_in_pvp_battle` & `cobblemon:held/consumed_in_wild_battle` these will determine which items get consumed in the implied battle types by Cobblemon, keep in mind the controller for this behaviour can be overriden by 3rd party.
- Unique wild encounter themes can now be associated with a specific species (or form) by assigning a SoundEvent identifier to the `battleTheme` field in the species' data configuration.
- Added a `structure` evolution condition, used to check if a Pokémon is in a given structure.
## [1.4.0](#1-4-0)
### Localization
- Updated translations for:
- French and Canadian French
- Simplified and Traditional Chinese
- Spanish and Mexican Spanish
- Pirate English
- German
- Thai
- Portuguese and Brazilian Portuguese
- Polish
- Italian
- Dutch
- Ukrainian
- Russian
Thank you so much to all of our community translators that bring the mod to the rest of the world!
## [1.4.0 - The Friends and Farms Update (October 13th, 2023)](#1-4-0)
### Additions
- Added nicknaming.
- Added mints, found on mountains.
- Added revival herbs, with pep-up flowers if fully grown, growing in lush caves.
- Added medicinal leeks, growing on the surface of rivers and ponds. It is a potion ingredient!
- Added big roots, generating from cave ceiling dirt and sometimes spreading into energy roots.
- Added trading between players. Press R while looking at another player, you'll figure it out.
- Added pasture blocks, used to let your PC Pokémon roam around your base.
- Added 69 berry trees. Some are found in village farms, some from planting different berries close to each other.
- Added pasture blocks, used to let your PC Pokémon roam around an area.
- Added nicknaming from the summary menu of a Pokémon (click their name).
- Added trading between players. Press R while looking at another player and you'll figure the rest out.
- Added mints for changing Pokémon stats. These are most commonly found at high altitudes.
- Added [Revival Herbs](https://wiki.cobblemon.com/index.php/Revival_Herb), with pep-up flowers when fully grown, growing in lush caves.
- Added [Medicinal Leeks](https://wiki.cobblemon.com/index.php/Medicinal_Leek), growing on the surface of rivers and ponds. It is a potion ingredient and can be cooked as food!.
- Added [Big Roots](https://wiki.cobblemon.com/index.php/Big_Root), generating from cave ceiling dirt which sometimes spread as energy roots.
- Added [69 Berry Trees](https://wiki.cobblemon.com/index.php/Berry_Tree) and [Berries](https://wiki.cobblemon.com/index.php/Berry). Some are found in village farms, some from planting different berries close to each other.
- Added mulches: Mulch Base, Growth Mulch, Surprise Mulch, Coarse Mulch, Humid Mulch, Rich Mulch, Loamy Mulch, Peat Mulch, and Sandy Mulch
- Added [Vivichokes](https://wiki.cobblemon.com/index.php/Vivichoke), obtainable from wandering villager trades and some loot chests.
- Added medicine brewing using medicinal leeks and berries in brewing stands.
- Added Pokémon cries when in battles and being sent out.
- Added support for scale in animations.
- Added support for jump keyframes (i.e. pre and post keyframes)
- Added AI for Nosepass to point towards world spawn when idle.
- Added structure spawn conditions
- Added recipes for Berry Juice, Heal Powder, Remedy, Fine Remedy, Superb Remedy, Revive, Max Revive, HP Up, Protein, Iron, Calcium, Zinc, Carbos, PP Up, PP Max, Pasture, Medicinal Leek to Magenta Dye, Roasted Leek, Leek and Potato Stew, Braised Vivichoke, Vivichoke Dip, Mulch Base, Growth Mulch, Surprise Mulch, Coarse Mulch, Humid Mulch, Rich Mulch, Loamy Mulch, Peat Mulch, Sandy Mulch, X Attack, X Defense, X Special Attack, X Special Defense, X Speed, X Accuracy, Dire Hit, Guard Spec, Power Anklet, Power Band, Power Belt, Power Bracelet, Power Lens, Power Weight, Bright Powder, Destiny Knot
- Added a shoulder mount for Mimikyu
- Added Advancement trigger for defeating Pokémon and collecting varieties of Pokémon.
- Added sleep animations to Arcanine, Jigglypuff, Wigglytuff, Vulpix and Ninetales.
- Added medicinal items: Berry Juice, Heal Powder, Remedy, Fine Remedy, Superb Remedy, Revive, Max Revive, Potion, Super Potion, Hyper Potion, Max Potion, Full Restore, Full Heal, Antidote, Awakening, Burn Heal, Ice Heal, and Paralyze Heal.
- Added battle items: X Attack, X Defence, X Sp.Atk, X Sp.Def, X Speed, Dire Hit, and Guard Spec.
- Added EV items: Power Anklet, Power Band, Power Belt, Power Bracelet, Power Lens, Power Weight.
- Added food items: Roasted Leek, Leek and Potato Stew, Braised Vivichoke, and Vivichoke Dip
- Added evolution items: Auspicious Armor and Malicious Armor, which can be used to evolve Charcadet into Armarouge or Ceruledge respectively.
- Added (mostly brewing) recipes for HP Up, Protein, Iron, Calcium, Zinc, Carbos, PP Up, PP Max, and Medicinal Leek to Magenta Dye.
- Added held items: Bright Powder, Destiny Knot
- Added AI for Nosepass to point towards world spawn when idle. We just think it's neat.
- Added shoulder mounting for Mimikyu.
- Added flying placeholder animations to Pidgey, Pidgeotto, Pidgeot, Golbat, Crobat, Scyther, Scizor, Zapdos, Moltres, Articuno, Dragonite, Rowlet, Dartrix, and Decidueye.
- Added loot to various vanilla chest loot tables (Link Cable in Ancient Cities, Woodland Mansions, End Cities, and Igloos, Vivichoke Seeds in Jungle Temples, Dungeons, and Plains, Savanna, Snowy, and Taiga Villages, and all 7 Apricorn Sprouts in Desert, Plains, Savanna, Snowy, and Taiga Villages, as well as the Bonus Chest, which can also have 5 of the basic Poké Ball types)
- Added a `doShinyStarters` gamerule to make it quick and easy to be offered shiny starters.
- Added a `doPokemonLoot` gamerule to toggle Pokémon dropping items/exp on death.
- Added ability activation announcement when in battle.
- Added animations for Wailord and made it BIGGER.
- Added Cherry Torterra variant.
- Added 2 new face spots for Spinda. The number of unique Spindas increases...
- Added Forretress Shulker variant.
- Added the `/teststore <player> <store> <properties>` command allowing command block/mcfunction users to query a party, PC or both for Pokémon matching specific properties and returning the match count, this will be a cheat command in the Minecraft permission system or use the permission `cobblemon.command.teststore` if a permission mod is present.
- Added the `/querylearnset <player> <slot> <move>` command allowing command block/mcfunction users to query a party slot and check if the Pokémon can learn a specific move returning a 1 if yes otherwise 0, this will be a cheat command in the Minecraft permission system or use the permission `cobblemon.command.querylearnset` if a permission mod is present.
- Added the `/testpcslot <player> <slot> <properties>` command allowing command block/mcfunction users to query a pc slot and check if the Pokémon matches specific properties returning a 1 if yes otherwise 0, this will be a cheat command in the Minecraft permission system or use the permission `cobblemon.command.testpcslot` if a permission mod is present.
@@ -39,18 +167,6 @@
- Added the `/clearparty <player>` command for emptying a player's party.
- Added the `/clearpc <player>` command for emptying a player's PC.
- Added the `/pokemonrestart <reset_starters>` and the `/pokemonrestartother <player> <reset_starters>` command allowing command block/mcfunction users to reset a players Pokémon data.
- Added support for "isBattle" and "isTouchingWater" properties on resource pack Pokémon poses. This allows your custom Pokémon to be posed differently when in battle.
- Added support for "isVisible" on a transformed part on resource pack Pokémon poses. This allows your custom Pokémon to have bones disappear in specific poses, such as hiding Greninja's throwing star when not in a battle pose.
- Added a "doShinyStarters" gamerule
- Added the `doPokemonLoot` gamerule to toggle Pokémon dropping items/exp on death.
- Added support for battle music. Sounds can be added to the ``battle.pvp.default`` and ``battle.pvw.default`` sound events.
- Added ability activation announcement when in battle.
- Added Auspicious Armor and Malicious Armor, which can be used to evolve Charcadet into Armarouge or Ceruledge respectively.
- Added animations for Wailord.
- Added Cherry Torterra variant.
- Added 2 new face spots for Spinda.
- Added Forretress Shulker variant.
- Added 'enabled' optional property on model layers, allowing later variations to disable previously-defined layers. See [this issue](https://gitlab.com/cable-mc/cobblemon/-/issues/335) for how this looks.
### Pokémon Added
#### Gen 2
@@ -268,39 +384,36 @@
- Clodsire
### Changes
- Updated model and textures of Spiritomb, Koffing, Weezing, Kadabra, Alakazam, Emolga, Oshawott, Doduo, Dodrio, Dratini, Dragonair, Dragonite, Sneasel, Weavile, Gyarados, Hitmonlee, Hitmonchan, Chesnaught, Spinda, Mamoswine, Steelix, Midreavus, Mismagius, Buneary, Lopunny, Golduck, Meowth, Persian, Fennekin, Braixen, Delphox, Snivy, Servine, Serperior, Ratatta, Raticate, Nidorina, Nidoqueen, NidoranM, Nidoking, Riolu, Lucario, Haunter, Mankey, Primeape, Mew, Mewtwo, Arcanine, Magnemite, Magneton, Magnezone, Exeggcute, Exeggutor, Elekid, Electabuzz, Electivire, Pichu, Pikachu, Raichu, Gengar, Wooper, Drowzee, Hypno, Aerodactyl, Spearow, Fearow, Lickitung, Pidgey, Pidgeotto, Pidgeot, Scyther, Scizor, Kleavor, Popplio, Brionne, Primarina, Torchic, Combusken, Blaziken, Aerodacyl, Scyther, Scizor, Kleavor, Lickitung, Lickilicky, Happiny, Chansey and Blissey.
- Updated animations for Steelix, Turtwig, Grotle, Torterra, Ponyta, Rapidash, Piplup, Prinplup, Empoleon, Drowzee, Hypno, Farfetch'd, Exeggcute, Exeggutor, Bidoof, Chimecho, Lickytung, Lickilicky, Popplio, Brionne, Luvdisc, Chimchar, Monferno, Infernape, Sobble, Drizzile, Inteleon, Greninja, Heatmor, Aerodactyl, Ditto, Lotad, Lombre, Ludicolo, Pumpkaboo, Gourgeist.
- Removed the existing shoulder effects from Pokémon until we have more balanced versions of them (they're too powerful!)
- Updated models and textures of Weedle, Dwebble and Crustle, Spiritomb, Koffing and Weezing, Kadabra and Alakazam, Emolga, Oshawott, Doduo and Dodrio, Dratini and Dragonair and Dragonite, Sneasel and Weavile, Gyarados, Hitmonlee and Hitmonchan, Chesnaught, Spinda, Mamoswine, Steelix, Misdreavus and Mismagius, Buneary and Lopunny, Golduck, Meowth and Persian, Fennekin and Braixen and Delphox, Snivy and Servine and Serperior, Ratatta and Raticate, Nidorina and Nidoqueen, Nidoran Male and Nidoking, Riolu and Lucario, Haunter and Gengar, Mankey and Primeape, Mew and Mewtwo, Arcanine, Magnemite and Magneton and Magnezone, Exeggcute and Exeggutor, Elekid and Electabuzz and Electivire, Pichu and Pikachu and Raichu, Wooper, Drowzee and Hypno, Aerodactyl, Spearow and Fearow, Lickitung and Lickilicky, Pidgey and Pidgeotto and Pidgeot, Scyther and Scizor and Kleavor, Popplio and Brionne and Primarina, Torchic and Combusken and Blaziken, Happiny and Chansey and Blissey.
- Updated animations for Steelix, Turtwig and Grotle and Torterra, Ponyta and Rapidash, Piplup and Prinplup and Empoleon, Drowzee and Hypno, Farfetch'd, Exeggcute and Exeggutor, Bidoof, Chimecho, Lickitung and Lickilicky, Popplio and Brionne, Luvdisc, Chimchar and Monferno and Infernape, Sobble and Drizzile and Inteleon, Greninja, Heatmor, Aerodactyl, Ditto, Lotad and Lombre and Ludicolo, Pumpkaboo and Gourgeist.
- Updated sprites for EV medicines, the rare candy, and the apricorn door item.
- Updated textures for apricorn doors and all the evolution stone ores.
- Ponyta and Rapidash now have animated textures; they look insane.
- Updated Apricorn Leaves color.
- Wild Pokémon now heal if you are defeated by them or flee from them.
- Doubled the default time between ambient Pokémon cries (they have cries if you're using a resource pack to add them)
- Moved spawn attempts per tick to a config option (ticksBetweenSpawnAttempts)
- PCs can now be waterlogged
- Starter selection prompt now appears as a tutorial-esque toast instead of plain text
- Cobblemon items can now all have their own tooltips via resourcepacks, to add a tooltip simply add a lang entry like "item.cobblemon.{item_id}.tooltip", if you want to add multiple tooltip lines you can do so with "item.cobblemon.{item_id}.tooltip_1" and upwards.
- Updated texture of Weedle.
- Updated shiny texture of Dwebble and Crustle.
- Reorganised the advancements recipes folder
- Pokéedit command now supports IVs and EVs.
- Reorganised creative categories
- Pokémon can now wander into non-solid blocks such as foliage
- Pokéballs now despawn after 30 seconds
- Thrown Poké Balls now despawn after 30 seconds so that they don't fly forever.
- Dive Balls will now have the same motion speed underwater as if they were thrown in the air.
- Hardcoded potion shoulder effects have been removed, you can now use any potion vanilla or otherwise with the parameters you'd like, for more information see the [Datapack & Resourcepack Creators](#datapack-&-resourcepack-creators) section.
- Clicking categories of the Stat sub-section or the party reorder button in the Summary screen will now produce a click sound.
- Hardcoded potion shoulder effects have been removed. You can now use any potion vanilla or otherwise with the parameters you'd like, for more information see the [Datapack & Resourcepack Creators](#datapack-&-resourcepack-creators) section.
- Clicking categories of the Stat subsection or the party reorder button in the Summary screen will now produce a click sound.
- Updated PC Recipe.
- Improved Pokémon AI and movement.
- Friendship will slowly increase when Pokémon are shoulder-mounted.
- Master balls are now unable to be burned when dropped into fire/lava.
- Master Balls are now unable to be burned when dropped into fire/lava. They're made from stronger stuff.
- Pokémon will appear red when hurt, like regular entities, except when they're fainting.
- Ponyta and Rapidash now have animated textures.
- Pokémon's air meter no longer depletes while battling underwater.
- Sleeping partially restores PP of Pokémon
- Item interaction evolutions and held item requirements now support NBT by creating an object JSON containing the key ``item`` for what used to be the existing condition support and a ``nbt`` key for the NBT format, this is the string [format](https://minecraft.fandom.com/wiki/NBT_format) expected in commands. Existing data does not need to be updated.
- Shoulder mounts now match the shoulder position a bit more accurately when sneaking.
- Poison Heal will now cause poisoned Pokémon to heal outside of battle.
- Updated Pokéball, PC, UI, evolution and Healing Machine sounds.
- Updated Poké Ball, PC, UI, evolution and Healing Machine sounds.
### Added cries to the following Pokémon:
- All starters and their evolutions
@@ -370,48 +483,48 @@
- Tatsugiri
### Fixes
- Fixed spawning moon phase dependent Pokémon only when the moon phase is wrong
- Fixed spawning moon phase dependent Pokémon only when the moon phase is wrong (that's a funny woopsy)
- Fixed large Pokémon spawning partially inside walls where they suffocate.
- Fixed custom Pokémon in your party or PC not being removed when the addon is removed, causing major issues.
- Fixed messages for entry hazards, screens, weather, damage, healing, Tailwind, Perish Song, Destiny Bond, Shed Skin, Uproar, Forewarn, Disguise, Arena Trap, Yawn, Curse, Clamp, Whirlpool, Liquid Ooze, Miracle Eye, Safeguard, Magic Bounce, Lock On, Focus Energy, Confusion, and more.
- Fixed Porygon not evolving with an Upgrade.
- Fixed super sized Pumpkaboo not having any moves.
- Fixed Infernape look animation.
- Fixed Garchomp t-posing while swimming.
- Fixed a bug that caused sleeping Pokémon to stay asleep.
- Fixed a bug that would freeze a battle when a Pokémon gets trapped due to an ability.
- Fixed Garchomp T-posing while swimming which was very funny.
- Fixed a bug that caused sleeping Pokémon to stay asleep. Forever. The years passing them by as they dream of a world without hate...
- Fixed a bug that would freeze a battle when a Pokémon gets trapped by an ability, making the trap abilities even scarier and trap-like than they were before.
- Fixed the Poké Ball close animation canceling whenever colliding with a block.
- Fixed faint animations not working properly in add-ons.
- Fixed lighting and Pokémon label issues when a Pokémon item frame is nearby.
- Fixed Pokémon being able to spawn outside the world border as a tease.
- Fixed deepslate water stone ore items looking like deepslate fire stone ores.
- Fixed a bunch of client-side logging errors when Pokémon are shoulder mounted.
- Fixed deepslate water stone ore items looking like deepslate fire stone ores. Huh?
- Fixed a bunch of client-side logging errors when Pokémon are shoulder mounted. You didn't notice? Good.
- Fixed a crash when wild Pokémon have to struggle under specific circumstances.
- Fixed uncolored pixels on Yanma's shiny texture.
- Fixed apricorn tree leaves looking gross on Fast graphics mode.
- Fixed apricorn tree leaves looking gross on the Fast graphics mode.
- Fixed hoes not breaking apricorn tree leaves any faster.
- Fixed Shiftry's PC model position.
- Fixed the /pc command not playing the opening sound.
- Fixed Shedinja not being able to recover naturally.
- Fixed different forms of Pokémon not being able to appear as different sizes.
- Fixed the Healing Machine soft locking you from using others when removed by non-players.
- Fixed animations being sped up when using the Replay Mod.
- Fixed particle animations not running when a Pokémon is off-screen.
- Fixed Pokémon variants and layers not rendering correctly when shouldered and playing on a dedicated server, existing shoulders affected will need to be retrieved and shouldered again.
- Shoulder effects will now stay applied through situations that remove potion effects such as drinking milk.
- Fixed Shedinja evolving to use the consumed PokéBall and removed the held item.
- Fixed non-existent species in spawn pool file causing random species to spawn.
- Fixed shearing Pokémon dropping 0-2 wool instead of 1-3.
- Fixed some alignment issues in the stat hexagon of the summary menu.
- Fixed capture calculations not applying ball bonuses entirely correctly.
- Fixed shoulder effects not staying applied through situations that remove potion effects such as drinking milk.
- Fixed Shedinja not being able to recover naturally.
- Fixed Shedinja evolving to use the consumed Poké Ball and removed the held item to prevent dupes.
- Fixed Shedinja healing above 1 HP.
- Fixed Shedinja, basically.
- Fixed shearing Pokémon dropping 0-2 wool instead of 1-3.
- Fixed some alignment issues in the stat hexagon of the summary menu. OCD people rejoice.
- Fixed capture calculations not applying ball bonuses entirely correctly.
- Fixed battles soft-locking when consecutive Pokémon faint on switch-in.
- Fixed timing and color of battle window messages.
- Fixed players being able to trade, battle and let out their Pokémon while in spectator mode.
- Fixed Galarian Yamask not being able to evolve and by proxy the ``damage_taken`` evolution requirement.
- Fixed Bisharp not being able to evolve and by proxy the ``defeat`` evolution requirement.
- Fixed White-Striped Basculin not being able to evolve and by proxy the ``recoil`` evolution requirement.
- Fixed Primeape, Qwilfish and Stantler not being able to evolve and by proxy the ``use_move`` evolution requirement.
- Fixed Bramblin, Pawmo, and Rellor not being able to evolve and by proxy the ``blocks_traveled`` evolution requirement.
- Fixed White-Striped Basculin not being able to evolve because of a broken ``recoil`` evolution requirement.
- Fixed Primeape, Qwilfish and Stantler not being able to evolve because of a broken ``use_move`` evolution requirement.
- Fixed Bramblin, Pawmo, and Rellor not being able to evolve because of a broken ``blocks_traveled`` evolution requirement.
- Fixed displayName property in spawn files not doing what it's meant to do.
- Fixed Pokémon not sleeping in the wild like we wanted them to.
@@ -424,9 +537,12 @@
- The various hardcoded potion shoulder effects have been removed, make use of PotionBaseEffect.
- Added ContextManager for tracking causes and contexts of conditions created during a battle. See BattleContext for types of conditions that are tracked.
- Added MongoDB support for storing Pokémon and Player data. Must be enabled in config, requires MongoDB core and sync drivers (4.10.0+).
- CobblemonShowdown updated to version 10.
- Generation of a battle can be set in BattleFormat.
- Pokémon now have ``teraType``, ``dmaxLevel``, and ``gmaxFactor`` properties. Gimmicks can be used during battle by adding the respective identifiers to ``keyItems`` in PlayerData: ``key_stone``, ``z_ring``, ``dynamax_band``, and ``tera_orb``. Dynamax is only supported in Gen 8 battles. Mega Evolution and Z-Power require custom held items to be added (e.g. an item with the path ``gengarite`` will allow Gengar to Mega Evolve). Currently custom Z-Crystals and Mega Stones are not supported.
### Datapack & Resourcepack Creators
- All potion related shoulder effects have had their IDs changed, they now all share the same type being `potion_effect` and use the vanilla Potion data [parameters](https://minecraft.fandom.com/wiki/Potion#Item_data), take for example the default Pidgey asset:
- All potion related shoulder effects have had their IDs changed. They now all share the same type being `potion_effect` and use the vanilla Potion data [parameters](https://minecraft.fandom.com/wiki/Potion#Item_data). For example, here is the converted Pidgey asset:
- ```json
{
"type": "potion_effect",
@@ -438,6 +554,22 @@
}
```
- Renamed the ``walked_steps`` evolution requirement to ``blocks_traveled``.
- Added support for scale in animations.
- Added support for jump keyframes (i.e. pre and post keyframes)
- Added structure spawning conditions
- Added Advancement trigger for defeating Pokémon and collecting varieties of Pokémon.
- Added support for "isBattle" and "isTouchingWater" properties on resource pack Pokémon poses. This allows your custom Pokémon to be posed differently when in battle.
- Added support for "isVisible" on a transformed part on resource pack Pokémon poses. This allows your custom Pokémon to have bones disappear in specific poses, such as hiding Greninja's throwing star when not in a battle pose.
- Added support for battle music. Sounds can be added to the ``battle.pvp.default`` and ``battle.pvw.default`` sound events.
- Added 'enabled' optional property on model layers, allowing later variations to disable previously-defined layers. See [this issue](https://gitlab.com/cable-mc/cobblemon/-/issues/335) for how this looks.
- Cobblemon items can now all have their own tooltips via resourcepacks. To add a tooltip, add a lang entry like "item.cobblemon.{item_id}.tooltip". If you want to add multiple tooltip lines you can do so with "item.cobblemon.{item_id}.tooltip_1" and upwards.
- Item interaction evolutions and held item requirements now support NBT by creating an object JSON containing the key ``item`` for what used to be the existing condition support and a ``nbt`` key for the NBT format, this is the string [format](https://minecraft.fandom.com/wiki/NBT_format) expected in commands. Existing data does not need to be updated.
- Fixed faint animations not working properly in add-ons.
- Fixed non-existent species in spawn pool files causing random species to spawn.
### Localization
- Added partial translations for Dutch, Polish, Swedish, Hungarian, Czech, Cyprus Greek, and even Esperanto.
- Updated translation for French and Canadian French, Simplified Chinese, Japanese, Korean, Spanish and Mexican Spanish, Pirate English, German, Thai, Turkish, Portuguese and Brazilian Portuguese, Ukrainian, and Russian.
## [1.3.1 (March 31st, 2023)](#1-3-1)
@@ -451,7 +583,7 @@
- Add lava surface spawn preset.
- Added an ``any`` evolution requirement allowing you to define ``possibilities`` of other evolution requirements, for example, this allows you to create an evolution that requires the Pokémon to be shiny or a female.
- Added the `/spawnpokemonfrompool [amount]` or `/forcespawn [amount]` command to spawn Pokémon(s) in the surrounding area using the natural spawn rates/pool of that area, this will be a cheat command in the Minecraft permission system or use the permission `cobblemon.command.spawnpokemon` if a permission mod is present. On a successful execution of the command, the amount of Pokémon spawned will be the output.
- Added the `/pokebox` and `/pokeboxall` commands to move Pokemon(s) to the PC from a Player's party, this will be a cheat command in the Minecraft permission system or use the permission `cobblemon.command.pokebox` if a permission mod is present. On a successful execution of the command the output will be the number of pokemon moved to the Player's PC.
- Added the `/pokebox` and `/pokeboxall` commands to move Pokémon(s) to the PC from a Player's party, this will be a cheat command in the Minecraft permission system or use the permission `cobblemon.command.pokebox` if a permission mod is present. On a successful execution of the command the output will be the number of pokemon moved to the Player's PC.
- Added the `/pc` command which opens up the PC UI the same way interacting with the block would, this will be a cheat command in the Minecraft permission system or use the permission `cobblemon.command.pc` if a permission mod is present.
### Changes
@@ -783,17 +915,17 @@
- Fixed spawning in several biome tag categories.
- Fixed resource pack support for Pokémon models and textures.
- **Model Fixes**
- Fixed Paras and Nidoqueen looking very weird.
- Fixed Hitmonchan asserting dominance with a T-pose as well as Grimer and Muk pointing their hands to the sky.
- Fixed specific Pokémon suddenly pausing their animation after staying still for a long time.
- Fixed Mankey's feet being buried in the ground.
- Updated the Substitute model and updated its shiny texture to be better for the red-green colorblind.
- Improved Horsea, Seadra, and Kingdra animations, especially on land.
- Fixed Paras and Nidoqueen looking very weird.
- Fixed Hitmonchan asserting dominance with a T-pose as well as Grimer and Muk pointing their hands to the sky.
- Fixed specific Pokémon suddenly pausing their animation after staying still for a long time.
- Fixed Mankey's feet being buried in the ground.
- Updated the Substitute model and updated its shiny texture to be better for the red-green colorblind.
- Improved Horsea, Seadra, and Kingdra animations, especially on land.
- **Battle Fixes**
- Fixed an issue with battles where Pokémon had a different max HP causing some desync issues with the health bars.
- Fixed Magnitude battle messages.
- Moves that are disabled or out of PP now show transparently in the battle GUI instead of being hidden completely.
- Statuses like sleep and frozen no longer last forever if it was carried over from a previous battle.
- Fixed an issue with battles where Pokémon had a different max HP causing some desync issues with the health bars.
- Fixed Magnitude battle messages.
- Moves that are disabled or out of PP now show transparently in the battle GUI instead of being hidden completely.
- Statuses like sleep and frozen no longer last forever if it was carried over from a previous battle.
### Localization
- Added species, ability, and move translations for `ko_ko`, `jp_jp`, `fr_fr`, `es_es`, `it_it`, and `zh_cn`.
+3 -1
View File
@@ -19,6 +19,7 @@ architectury {
repositories {
maven(url = "${rootProject.projectDir}/deps")
maven(url = "https://api.modrinth.com/maven")
mavenLocal()
}
@@ -28,9 +29,10 @@ dependencies {
modImplementation(libs.fabricLoader)
//Flywheel has no common dep so just pick one and don't use any platform specific code in common
modCompileOnly(libs.flywheelFabric)
// modCompileOnly(libs.flywheelFabric)
modApi(libs.molang)
compileOnlyApi(libs.jeiApi)
modCompileOnly(libs.adornFabric)
// For Showdown
modCompileOnly(libs.graal)
@@ -0,0 +1,20 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.duck;
import net.minecraft.sound.SoundCategory;
import net.minecraft.util.Identifier;
import org.jetbrains.annotations.Nullable;
public interface SoundManagerDuck {
void pauseSounds(@Nullable Identifier id, @Nullable SoundCategory category);
void resumeSounds(@Nullable Identifier id, @Nullable SoundCategory category);
}
@@ -0,0 +1,25 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.duck;
import net.minecraft.client.sound.SoundInstance;
import net.minecraft.sound.SoundCategory;
import net.minecraft.util.Identifier;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
public interface SoundSystemDuck {
void pauseSounds(@Nullable Identifier id, @Nullable SoundCategory category);
void resumeSounds(@Nullable Identifier id, @Nullable SoundCategory category);
Collection<SoundInstance> getSounds(@Nullable SoundCategory category);
}
@@ -0,0 +1,33 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.mixin;
import net.minecraft.entity.passive.VillagerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.village.VillagerProfession;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import com.cobblemon.mod.common.villager.VillagerGatherableItems;
import java.util.Objects;
@Mixin(VillagerEntity.class)
public abstract class EntityVillagerMixin {
@Inject(method = "canGather", at = @At(value = "RETURN"), cancellable = true)
private void cobblemon$canGather(ItemStack stack, CallbackInfoReturnable<Boolean> ci) {
final VillagerEntity villager = (VillagerEntity) (Object) this;
if(ci.getReturnValue() == false && Objects.equals(villager.getVillagerData().getProfession(), VillagerProfession.FARMER) && villager.getInventory().canInsert(stack)) {
if(VillagerGatherableItems.INSTANCE.getVillagerGatherableItems().contains(stack.getItem()))
ci.setReturnValue(true);
}
}
}
@@ -1,47 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.mixin;
import com.cobblemon.mod.common.CobblemonBlocks;
import com.cobblemon.mod.common.block.PastureBlock;
import net.minecraft.block.BlockState;
import net.minecraft.block.FenceBlock;
import net.minecraft.block.HorizontalFacingBlock;
import net.minecraft.util.math.Direction;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
@Mixin(value = FenceBlock.class)
public abstract class FenceBlockMixin {
// This could be done with a modify variable but it just doesn't seem to want to work, very crude unfinished explanation I had on Fabric discord was
// "boolean is a primitive, it isnt passed by reference but by value and you have your own object references anyway so assigning a new object to non-primitive references (variables) wont modify it after your mixin returns
//(you cant modify a random argument that mixin passes you that way, target the boolean not the FenceBlock)"
// However the issue is the only way to get all the params which we need is by passing in the entire method reference which enforces the return type.
@Redirect(method = "getStateForNeighborUpdate", at = @At(value = "INVOKE", target = "Lnet/minecraft/block/FenceBlock;canConnect(Lnet/minecraft/block/BlockState;ZLnet/minecraft/util/math/Direction;)Z"))
private boolean cobblemon$getStateForNeighborUpdate(FenceBlock instance, BlockState state, boolean neighborIsFullSquare, Direction dir) {
return instance.canConnect(state, neighborIsFullSquare, dir) || this.cobblemon$canConnect(state, dir);
}
@Redirect(method = "getPlacementState", at = @At(value = "INVOKE", target = "Lnet/minecraft/block/FenceBlock;canConnect(Lnet/minecraft/block/BlockState;ZLnet/minecraft/util/math/Direction;)Z"))
private boolean cobblemon$getPlacementState(FenceBlock instance, BlockState state, boolean neighborIsFullSquare, Direction dir) {
return instance.canConnect(state, neighborIsFullSquare, dir) || this.cobblemon$canConnect(state, dir);
}
private boolean cobblemon$canConnect(BlockState state, Direction dir) {
if (state.isOf(CobblemonBlocks.PASTURE) && state.get(PastureBlock.Companion.getPART()) == PastureBlock.PasturePart.BOTTOM) {
final Direction pastureFacing = state.get(HorizontalFacingBlock.FACING);
return dir == pastureFacing.rotateYClockwise() || dir == pastureFacing.rotateYCounterclockwise();
}
return false;
}
}
@@ -0,0 +1,37 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.mixin;
import com.cobblemon.mod.common.client.sound.battle.BattleMusicController;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.sound.MusicTracker;
import net.minecraft.client.sound.SoundInstance;
import org.jetbrains.annotations.Nullable;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(MusicTracker.class)
public class MusicTrackerMixin {
@Shadow @Final
private MinecraftClient client;
@Shadow @Nullable
private SoundInstance current;
/** Freezes the tracker while a BattleMusicInstance is in progress. Current SoundInstance being tracked will be paused by BattleMusicHandler. */
@Inject(method = "tick()V", at = @At("HEAD"), cancellable = true)
public void tick(CallbackInfo cb) {
if (this.client.getSoundManager().isPlaying(BattleMusicController.INSTANCE.getMusic())) cb.cancel();
}
}
@@ -1,44 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.mixin;
import com.cobblemon.mod.common.api.spawning.mixins.CachedOnlyChunkAccessor;
import com.mojang.datafixers.util.Either;
import net.minecraft.server.world.ChunkHolder;
import net.minecraft.server.world.ServerChunkManager;
import net.minecraft.util.math.ChunkPos;
import net.minecraft.world.chunk.Chunk;
import net.minecraft.world.chunk.ChunkManager;
import net.minecraft.world.chunk.ChunkStatus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import java.util.concurrent.CompletableFuture;
@Mixin(ServerChunkManager.class)
public abstract class ServerChunkManagerMixin extends ChunkManager implements CachedOnlyChunkAccessor {
@Shadow @Nullable protected abstract ChunkHolder getChunkHolder(long pos);
@Override
public Chunk cobblemon$request(int x, int z, @NotNull ChunkStatus status) {
long l = ChunkPos.toLong(x, z);
ChunkHolder holder = getChunkHolder(l);
if (holder != null) {
CompletableFuture<Either<Chunk, ChunkHolder.Unloaded>> future = holder.getFutureFor(status);
if (future.isDone()) {
return future.join().left().orElse(null);
}
}
return null;
}
}
@@ -8,36 +8,77 @@
package com.cobblemon.mod.common.mixin;
import com.cobblemon.mod.common.access.SoundManagerDuck;
import net.minecraft.client.sound.SoundInstance;
import net.minecraft.client.sound.SoundManager;
import com.cobblemon.mod.common.client.sound.battle.BattleMusicController;
import com.cobblemon.mod.common.duck.SoundManagerDuck;
import com.cobblemon.mod.common.duck.SoundSystemDuck;
import net.minecraft.client.sound.*;
import net.minecraft.sound.SoundCategory;
import net.minecraft.util.Identifier;
import org.jetbrains.annotations.Nullable;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(SoundManager.class)
public class SoundManagerMixin implements SoundManagerDuck {
public abstract class SoundManagerMixin implements SoundManagerDuck {
private boolean[] blockedCategories = new boolean[SoundCategory.values().length];
@Shadow
public abstract boolean isPlaying(SoundInstance sound);
@Override
public void toggleCategories(SoundCategory... categories) {
for (SoundCategory category : categories) {
int index = category.ordinal();
boolean blocked = blockedCategories[index];
blockedCategories[index] = !blocked;
}
@Shadow @Final
private SoundSystem soundSystem;
// Never-ending ambient loops are a special exception (they are only initiated once) and should always be paused if filtered.
private boolean isAmbientLoop(SoundInstance sound) {
return sound instanceof BiomeEffectSoundPlayer.MusicLoop || sound instanceof AmbientSoundLoops.Underwater;
}
private boolean filterCondition(SoundInstance sound) {
return !isAmbientLoop(sound) &&
this.isPlaying(BattleMusicController.INSTANCE.getMusic()) &&
BattleMusicController.INSTANCE.getFilteredCategories().contains(sound.getCategory());
}
private boolean ambientLoopCondition(SoundInstance sound) {
return isAmbientLoop(sound) &&
this.isPlaying(BattleMusicController.INSTANCE.getMusic()) &&
BattleMusicController.INSTANCE.getFilteredCategories().contains(sound.getCategory());
}
/** Pauses the queried SoundInstance(s). If id is null, will pause all sounds belonging to the SoundCategory. */
@Override
public void pauseSounds(@Nullable Identifier id, @Nullable SoundCategory category) {
((SoundSystemDuck)soundSystem).pauseSounds(id, category);
}
/** Resumes the queried SoundInstance(s). If id is null, will resume all sounds belonging to the SoundCategory. */
@Override
public void resumeSounds(@Nullable Identifier id, @Nullable SoundCategory category) {
((SoundSystemDuck)soundSystem).resumeSounds(id, category);
}
/** Blocks filtered sounds from being played while a BattleMusicInstance is in progress. */
@Inject(method = "play(Lnet/minecraft/client/sound/SoundInstance;)V", at = @At("HEAD"), cancellable = true)
public void play(SoundInstance sound, CallbackInfo cb) {
if (blockedCategories[sound.getCategory().ordinal()]) cb.cancel();
public void playStart(SoundInstance sound, CallbackInfo cb) {
if (filterCondition(sound)) cb.cancel();
}
@Inject(method = "play(Lnet/minecraft/client/sound/SoundInstance;I)V", at = @At("HEAD"), cancellable = true)
public void play(SoundInstance sound, int delay, CallbackInfo cb) {
if (blockedCategories[sound.getCategory().ordinal()]) cb.cancel();
public void playStart(SoundInstance sound, int delay, CallbackInfo cb) {
if (filterCondition(sound)) cb.cancel();
}
/** Pauses ambient loops while a BattleMusicInstance is in progress. */
@Inject(method = "play(Lnet/minecraft/client/sound/SoundInstance;)V", at = @At("TAIL"))
public void playEnd(SoundInstance sound, CallbackInfo cb) {
if (ambientLoopCondition(sound)) this.pauseSounds(sound.getId(), SoundCategory.AMBIENT);
}
@Inject(method = "play(Lnet/minecraft/client/sound/SoundInstance;I)V", at = @At("TAIL"))
public void playEnd(SoundInstance sound, int delay, CallbackInfo cb) {
if (ambientLoopCondition(sound)) this.pauseSounds(sound.getId(), SoundCategory.AMBIENT);
}
}
@@ -8,31 +8,102 @@
package com.cobblemon.mod.common.mixin;
import com.cobblemon.mod.common.client.sound.battle.BattleMusicController;
import com.cobblemon.mod.common.duck.SoundSystemDuck;
import com.google.common.collect.Multimap;
import net.minecraft.client.sound.SoundInstance;
import net.minecraft.client.sound.SoundSystem;
import net.minecraft.client.sound.*;
import net.minecraft.sound.SoundCategory;
import net.minecraft.util.Identifier;
import org.jetbrains.annotations.Nullable;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.util.Map;
@Mixin(SoundSystem.class)
public abstract class SoundSystemMixin {
public abstract class SoundSystemMixin implements SoundSystemDuck {
@Shadow
private boolean started;
@Shadow
private Multimap<SoundCategory, SoundInstance> sounds;
@Shadow @Final
private Map<SoundInstance, Channel.SourceManager> sources;
@Shadow
protected abstract void stop(SoundInstance sound);
@Shadow
public abstract boolean isPlaying(SoundInstance sound);
/** Resumes the Source belonging to the queried SoundInstance. */
private void resume(SoundInstance sound) {
Channel.SourceManager sourceManager = this.sources.get(sound);
if (this.started && sourceManager != null) sourceManager.run(Source::resume);
}
/** Pauses the Source belonging to the queried SoundInstance. */
private void pause(SoundInstance sound) {
Channel.SourceManager sourceManager = this.sources.get(sound);
if (this.started && sourceManager != null) sourceManager.run(Source::pause);
}
/** Resumes the SoundInstance(s) queried by id and/or category. */
@Override
public void resumeSounds(@Nullable Identifier id, @Nullable SoundCategory category) {
if (category != null) {
this.sounds.get(category).forEach((sound) -> {
if (id == null || sound.getId().equals(id)) resume(sound);
});
} else if (id == null) {
this.sources.keySet().forEach(this::resume);
} else {
this.sources.keySet().forEach(sound -> {
if (sound.getId().equals(id)) resume(sound);
});
}
}
/** Pauses the SoundInstances queried by id and/or category. */
@Override
public void pauseSounds(@Nullable Identifier id, @Nullable SoundCategory category) {
if (category != null) {
this.sounds.get(category).forEach((sound) -> {
if (id == null || sound.getId().equals(id)) pause(sound);
});
} else if (id == null) {
this.sources.keySet().forEach(this::pause);
} else {
this.sources.keySet().forEach(sound -> {
if (sound.getId().equals(id)) pause(sound);
});
}
}
/** Allows stopping all SoundInstances that belong to a queried category. */
@Inject(method = "stopSounds(Lnet/minecraft/util/Identifier;Lnet/minecraft/sound/SoundCategory;)V", at = @At("HEAD"), cancellable = true)
public void stopSounds(@Nullable Identifier id, @Nullable SoundCategory category, CallbackInfo cb) {
if (id == null && category != null) {
sounds.get(category).forEach(this::stop);
this.sounds.get(category).forEach(this::stop);
cb.cancel();
}
}
/** Different behavior for resuming SoundInstances while a BattleMusicInstance is being played. We do not want to resume filtered sounds. */
@Inject(method = "resumeAll()V", at = @At("HEAD"), cancellable = true)
public void resumeAll(CallbackInfo cb) {
if (this.isPlaying(BattleMusicController.INSTANCE.getMusic())) {
this.sounds.values().forEach(sound -> {
if (sound == BattleMusicController.INSTANCE.getMusic() || !BattleMusicController.INSTANCE.getFilteredCategories().contains(sound.getCategory())) {
resume(sound);
}
});
cb.cancel();
}
}
@@ -8,15 +8,16 @@
package com.cobblemon.mod.common.mixin.accessor;
import net.minecraft.client.sound.MusicTracker;
import net.minecraft.entity.vehicle.BoatEntity;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
@Mixin(MusicTracker.class)
public interface MusicTrackerAccessor {
@Accessor("timeUntilNextSong")
int timeUntilNextSong();
@Mixin(BoatEntity.class)
public interface BoatEntityAccessor {
@Accessor("timeUntilNextSong")
void setTimeUntilNextSong(int timeUntilNextSong);
@Accessor
void setFallVelocity(double fallVelocity);
@Accessor
BoatEntity.Location getLocation();
}
@@ -0,0 +1,20 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.mixin.invoker;
import net.minecraft.block.Block;
import org.spongepowered.asm.mixin.Mixin;
import net.minecraft.block.FireBlock;
import net.minecraft.block.Blocks;
import org.spongepowered.asm.mixin.gen.Invoker;
@Mixin(FireBlock.class)
public interface FireBlockInvoker {
@Invoker("registerFlammableBlock") void registerNewFlammableBlock(Block block, int burnChance, int spreadChance);
}
@@ -6,11 +6,10 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
@file:Suppress("unused")
package com.cobblemon.mod.common
import com.cobblemon.mod.common.advancement.CobblemonCriteria
import com.cobblemon.mod.common.advancement.criterion.EvolvePokemonContext
import com.cobblemon.mod.common.api.Priority
import com.cobblemon.mod.common.api.SeasonResolver
import com.cobblemon.mod.common.api.data.DataProvider
@@ -31,7 +30,6 @@ import com.cobblemon.mod.common.api.pokeball.catching.calculators.CaptureCalcula
import com.cobblemon.mod.common.api.pokeball.catching.calculators.CaptureCalculators
import com.cobblemon.mod.common.api.pokemon.PokemonSpecies
import com.cobblemon.mod.common.api.pokemon.effect.ShoulderEffectRegistry
import com.cobblemon.mod.common.api.pokemon.evolution.adapters.EvolutionRegistry
import com.cobblemon.mod.common.api.pokemon.experience.ExperienceCalculator
import com.cobblemon.mod.common.api.pokemon.experience.ExperienceGroups
import com.cobblemon.mod.common.api.pokemon.experience.StandardExperienceCalculator
@@ -43,7 +41,6 @@ import com.cobblemon.mod.common.api.pokemon.stats.EvCalculator
import com.cobblemon.mod.common.api.pokemon.stats.Generation8EvCalculator
import com.cobblemon.mod.common.api.pokemon.stats.StatProvider
import com.cobblemon.mod.common.api.properties.CustomPokemonProperty
import com.cobblemon.mod.common.api.registry.CobblemonRegistryKeys
import com.cobblemon.mod.common.api.scheduling.ScheduledTaskTracker
import com.cobblemon.mod.common.api.spawning.BestSpawner
import com.cobblemon.mod.common.api.spawning.CobblemonSpawningProspector
@@ -63,7 +60,6 @@ import com.cobblemon.mod.common.api.storage.player.PlayerDataStoreManager
import com.cobblemon.mod.common.api.storage.player.factory.JsonPlayerDataStoreFactory
import com.cobblemon.mod.common.api.storage.player.factory.MongoPlayerDataStoreFactory
import com.cobblemon.mod.common.api.tags.CobblemonEntityTypeTags
import com.cobblemon.mod.common.api.types.ElementalType
import com.cobblemon.mod.common.battles.BagItems
import com.cobblemon.mod.common.battles.BattleFormat
import com.cobblemon.mod.common.battles.BattleRegistry
@@ -166,7 +162,6 @@ object Cobblemon {
fun preInitialize(implementation: CobblemonImplementation) {
this.implementation = implementation
this.queueRegistryCreation()
implementation.registerPermissionValidator()
implementation.registerSoundEvents()
implementation.registerBlocks()
@@ -194,8 +189,6 @@ object Cobblemon {
ShoulderEffectRegistry.register()
EvolutionRegistry.init()
DATA_SYNCHRONIZED.subscribe {
storage.onPlayerDataSync(it)
playerData.get(it).sendToPlayer(it)
@@ -344,7 +337,7 @@ object Cobblemon {
// Ensure the config option is enabled and that the result was a ninjask and that shedinja exists
if (this.config.ninjaskCreatesShedinja && pokemon.species.resourceIdentifier == ninjaskIdentifier && PokemonSpecies.getByIdentifier(Pokemon.SHEDINJA) != null) {
val player = pokemon.getOwnerPlayer() ?: return@subscribe
if (player.inventory.containsAny { it.item is PokeBallItem }) {
if (player.isCreative || player.inventory.containsAny { it.item is PokeBallItem }) {
var pokeball = Items.AIR
player.inventory.combinedInventory.forEach {
it.forEach {
@@ -353,7 +346,12 @@ object Cobblemon {
}
}
}
player.inventory.removeAmountIf(1) { it.item is PokeBallItem }
if (!player.isCreative) {
player.inventory.removeAmountIf(1) { it.item is PokeBallItem }
}
if (pokeball == Items.AIR) {
pokeball = CobblemonItems.POKE_BALL
}
val properties = event.evolution.result.copy()
properties.species = Pokemon.SHEDINJA.toString()
val product = pokemon.clone()
@@ -361,6 +359,7 @@ object Cobblemon {
properties.apply(product)
product.caughtBall = (pokeball as PokeBallItem).pokeBall
pokemon.storeCoordinates.get()?.store?.add(product)
CobblemonCriteria.EVOLVE_POKEMON.trigger(player, EvolvePokemonContext(event.pokemon.preEvolution!!.species.resourceIdentifier, product.species.resourceIdentifier, playerData.get(player).advancementData.totalEvolvedCount))
}
}
}
@@ -372,8 +371,9 @@ object Cobblemon {
battleRegistry.startBattle(
BattleFormat.GEN_9_SINGLES,
BattleSide(PokemonBattleActor(UUID.randomUUID(), BattlePokemon(Pokemon().initialize()), -1F)),
BattleSide(PokemonBattleActor(UUID.randomUUID(), BattlePokemon(Pokemon().initialize()), -1F))
).apply { mute = true }
BattleSide(PokemonBattleActor(UUID.randomUUID(), BattlePokemon(Pokemon().initialize()), -1F)),
true
).ifSuccessful { it.mute = true }
}
}
@@ -480,8 +480,4 @@ object Cobblemon {
this.implementation.registerCommandArgument(cobblemonResource("pokemon_store"), PokemonStoreArgumentType::class, ConstantArgumentSerializer.of(PokemonStoreArgumentType::pokemonStore))
}
private fun queueRegistryCreation() {
this.implementation.createRegistry(CobblemonRegistryKeys.ELEMENTAL_TYPE, ElementalType.CODEC, ElementalType.NETWORK_CODEC)
}
}
@@ -8,10 +8,7 @@
package com.cobblemon.mod.common
import com.cobblemon.mod.common.block.entity.BerryBlockEntity
import com.cobblemon.mod.common.block.entity.HealingMachineBlockEntity
import com.cobblemon.mod.common.block.entity.PCBlockEntity
import com.cobblemon.mod.common.block.entity.PokemonPastureBlockEntity
import com.cobblemon.mod.common.block.entity.*
import com.cobblemon.mod.common.platform.PlatformRegistry
import net.minecraft.block.entity.BlockEntityType
import net.minecraft.registry.Registries
@@ -31,5 +28,9 @@ object CobblemonBlockEntities : PlatformRegistry<Registry<BlockEntityType<*>>, R
val BERRY = this.create("berry", BlockEntityType.Builder.create(::BerryBlockEntity, *CobblemonBlocks.berries().values.toTypedArray()).build(null))
@JvmField
val PASTURE: BlockEntityType<PokemonPastureBlockEntity> = this.create("pasture", BlockEntityType.Builder.create(::PokemonPastureBlockEntity, CobblemonBlocks.PASTURE).build(null))
@JvmField
val SIGN: BlockEntityType<CobblemonSignBlockEntity> = this.create("sign", BlockEntityType.Builder.create(::CobblemonSignBlockEntity, CobblemonBlocks.APRICORN_SIGN, CobblemonBlocks.APRICORN_WALL_SIGN).build(null))
@JvmField
val HANGING_SIGN: BlockEntityType<CobblemonHangingSignBlockEntity> = this.create("hanging_sign", BlockEntityType.Builder.create(::CobblemonHangingSignBlockEntity, CobblemonBlocks.APRICORN_HANGING_SIGN, CobblemonBlocks.APRICORN_WALL_HANGING_SIGN).build(null))
}
@@ -19,6 +19,10 @@ import com.cobblemon.mod.common.mixin.invoker.*
import com.cobblemon.mod.common.platform.PlatformRegistry
import com.cobblemon.mod.common.util.cobblemonResource
import com.cobblemon.mod.common.block.BerryBlock
import com.cobblemon.mod.common.block.sign.CobblemonHangingSignBlock
import com.cobblemon.mod.common.block.sign.CobblemonSignBlock
import com.cobblemon.mod.common.block.sign.CobblemonWallHangingSignBlock
import com.cobblemon.mod.common.block.sign.CobblemonWallSignBlock
import net.minecraft.block.*
import net.minecraft.block.piston.PistonBehavior
import net.minecraft.entity.effect.StatusEffects
@@ -33,6 +37,8 @@ import net.minecraft.util.math.intprovider.UniformIntProvider
@Suppress("SameParameterValue", "HasPlatformType", "MemberVisibilityCanBePrivate", "unused")
object CobblemonBlocks : PlatformRegistry<Registry<Block>, RegistryKey<Registry<Block>>, Block>() {
override val registry: Registry<Block> = Registries.BLOCK
override val registryKey: RegistryKey<Registry<Block>> = RegistryKeys.BLOCK
@@ -105,9 +111,14 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, RegistryKey<Registry<
val APRICORN_BUTTON = this.create("apricorn_button", BlocksInvoker.createWoodenButtonBlock(BlockSetType.OAK))
@JvmField
val APRICORN_PRESSURE_PLATE = this.create("apricorn_pressure_plate", PressurePlateBlockInvoker.`cobblemon$create`(PressurePlateBlock.ActivationRule.EVERYTHING, AbstractBlock.Settings.create().mapColor(APRICORN_PLANKS.defaultMapColor).noCollision().strength(0.5f).sounds(BlockSoundGroup.WOOD), APRICORN_BLOCK_SET_TYPE))
// Tag was removed be sure to add it back when implemented
//val APRICORN_SIGN = queue("apricorn_sign") { StandingSignBlock(AbstractBlock.Settings.of(Material.WOOD).noCollission().strength(1.0f).sounds(BlockSoundGroup.WOOD), APRICORN_WOOD_TYPE) }
//val APRICORN_WALL_SIGN = queue("apricorn_wall_sign") { WallSignBlock(AbstractBlock.Settings.of(Material.WOOD).noCollission().strength(1.0f).sounds(BlockSoundGroup.WOOD).dropsLike(APRICORN_SIGN), APRICORN_WOOD_TYPE) }
@JvmField
val APRICORN_SIGN = this.create("apricorn_sign", CobblemonSignBlock(AbstractBlock.Settings.copy(Blocks.OAK_SIGN), APRICORN_WOOD_TYPE))
@JvmField
val APRICORN_WALL_SIGN = this.create("apricorn_wall_sign", CobblemonWallSignBlock(AbstractBlock.Settings.copy(Blocks.OAK_WALL_SIGN), APRICORN_WOOD_TYPE))
@JvmField
val APRICORN_HANGING_SIGN = this.create("apricorn_hanging_sign", CobblemonHangingSignBlock(AbstractBlock.Settings.copy(Blocks.OAK_WALL_HANGING_SIGN), APRICORN_WOOD_TYPE))
@JvmField
val APRICORN_WALL_HANGING_SIGN = this.create("apricorn_wall_hanging_sign", CobblemonWallHangingSignBlock(AbstractBlock.Settings.copy(Blocks.OAK_HANGING_SIGN), APRICORN_WOOD_TYPE))
@JvmField
val APRICORN_SLAB = this.create("apricorn_slab", SlabBlock(AbstractBlock.Settings.create().mapColor(MapColor.OAK_TAN).strength(2.0f, 3.0f).sounds(BlockSoundGroup.WOOD)))
@JvmField
@@ -228,6 +239,8 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, RegistryKey<Registry<
APRICORN_LOG to STRIPPED_APRICORN_LOG
)
private fun apricornBlock(name: String, apricorn: Apricorn): ApricornBlock = this.create(name, ApricornBlock(AbstractBlock.Settings.create().mapColor(apricorn.mapColor()).ticksRandomly().strength(Blocks.OAK_LOG.hardness, Blocks.OAK_LOG.blastResistance).sounds(BlockSoundGroup.WOOD).nonOpaque(), apricorn))
private val berries = mutableMapOf<Identifier, BerryBlock>()
@@ -302,6 +315,25 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, RegistryKey<Registry<
val WIKI_BERRY = this.berryBlock("wiki")
val YACHE_BERRY = this.berryBlock("yache")
init {
/**
* Makes all blocks in array flammable by adding them to FireBlock's flammableRegistry.
* second value is burn chance and third value is spread chance
*/
arrayOf(
Triple(APRICORN_LOG, 5, 5),
Triple(STRIPPED_APRICORN_LOG, 5, 5),
Triple(APRICORN_WOOD, 5, 5),
Triple(STRIPPED_APRICORN_WOOD, 5, 5),
Triple(APRICORN_PLANKS, 5, 20),
Triple(APRICORN_LEAVES, 30, 60),
Triple(APRICORN_FENCE, 5, 20),
Triple(APRICORN_FENCE_GATE, 5, 20),
Triple(APRICORN_SLAB, 5, 20),
Triple(APRICORN_STAIRS, 5, 20)
).onEach{ data -> setFlammable(data.first, data.second, data.third) }
}
fun berries() = this.berries.toMap()
private fun berryBlock(name: String): BerryBlock {
@@ -312,14 +344,28 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, RegistryKey<Registry<
}
/**
* Helper method for creating logs
* copied over from Vanilla
* Calls helper method from Vanilla
*/
private fun log(name: String, arg: MapColor = MapColor.DIRT_BROWN, arg2: MapColor = MapColor.DIRT_BROWN): PillarBlock {
val block = BlocksInvoker.createLogBlock(arg, arg2)
return this.create(name, block)
}
/**
* Method uses generic E in order to keep the block as the same return type.
* If E is not a block then it will not be set as flammable.
* Calls Vanilla implementation of registering a flammable block.
* Mixins looks cursed but it is java's fault.
*/
private fun <E> setFlammable(block: E, burnChance: Int, spreadChance: Int): E {
if(block !is Block) return block
var fireBlock: FireBlock = Blocks.FIRE as FireBlock
//Cursed Mixin stuff
(fireBlock as FireBlockInvoker).registerNewFlammableBlock(block as Block, burnChance, spreadChance)
return block
}
private fun evolutionStoneOre(name: String) = this.create(name, ExperienceDroppingBlock(AbstractBlock.Settings.copy(Blocks.IRON_ORE), UniformIntProvider.create(1, 2)))
private fun deepslateEvolutionStoneOre(name: String) = this.create(name, ExperienceDroppingBlock(AbstractBlock.Settings.copy(Blocks.DEEPSLATE_IRON_ORE), UniformIntProvider.create(1, 2)))
@@ -8,7 +8,6 @@
package com.cobblemon.mod.common
import java.util.function.Supplier
import net.minecraft.block.Block
import net.minecraft.block.entity.BlockEntity
import net.minecraft.block.entity.BlockEntityType
@@ -19,11 +18,14 @@ import net.minecraft.client.particle.ParticleFactory
import net.minecraft.client.particle.SpriteProvider
import net.minecraft.client.render.RenderLayer
import net.minecraft.client.render.block.entity.BlockEntityRendererFactory
import net.minecraft.client.render.entity.EntityRendererFactory
import net.minecraft.client.render.entity.model.EntityModelLayer
import net.minecraft.entity.Entity
import net.minecraft.entity.EntityType
import net.minecraft.item.Item
import net.minecraft.particle.ParticleEffect
import net.minecraft.particle.ParticleType
import net.minecraft.resource.SynchronousResourceReloader
import java.util.function.Supplier
interface CobblemonClientImplementation {
fun registerLayer(modelLayer: EntityModelLayer, supplier: Supplier<TexturedModelData>)
@@ -38,5 +40,7 @@ interface CobblemonClientImplementation {
fun registerBlockColors(provider: BlockColorProvider, vararg blocks: Block)
fun <T : BlockEntity> registerBlockEntityRenderer(type: BlockEntityType<T>, factory: BlockEntityRendererFactory<T>)
fun <T : BlockEntity> registerBlockEntityRenderer(type: BlockEntityType<out T>, factory: BlockEntityRendererFactory<T>)
fun <T : Entity> registerEntityRenderer(type: EntityType<out T>, factory: EntityRendererFactory<T>)
}
@@ -46,5 +46,6 @@ object CobblemonCommands {
ClearPartyCommand.register(dispatcher)
ClearPCCommand.register(dispatcher)
PokemonRestartCommand.register(dispatcher)
BedrockParticleCommand.register(dispatcher)
}
}
@@ -9,6 +9,8 @@
package com.cobblemon.mod.common
import com.cobblemon.mod.common.api.pokeball.PokeBalls
import com.cobblemon.mod.common.entity.boat.CobblemonBoatEntity
import com.cobblemon.mod.common.entity.boat.CobblemonChestBoatEntity
import com.cobblemon.mod.common.entity.pokeball.EmptyPokeBallEntity
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import com.cobblemon.mod.common.platform.PlatformRegistry
@@ -45,6 +47,24 @@ object CobblemonEntities : PlatformRegistry<Registry<EntityType<*>>, RegistryKey
.build(EMPTY_POKEBALL_KEY.toString())
)
@JvmField
val BOAT_KEY = cobblemonResource("boat")
@JvmField
val BOAT: EntityType<CobblemonBoatEntity> = this.create(
BOAT_KEY.path,
EntityType.Builder.create(::CobblemonBoatEntity, SpawnGroup.MISC).setDimensions(1.375F, 0.5625F).maxTrackingRange(10)
.build(BOAT_KEY.toString())
)
@JvmField
val CHEST_BOAT_KEY = cobblemonResource("chest_boat")
@JvmField
val CHEST_BOAT: EntityType<CobblemonChestBoatEntity> = this.create(
CHEST_BOAT_KEY.path,
EntityType.Builder.create(::CobblemonChestBoatEntity, SpawnGroup.MISC).setDimensions(1.375F, 0.5625F).maxTrackingRange(10)
.build(CHEST_BOAT_KEY.toString())
)
fun registerAttributes(consumer: (EntityType<out LivingEntity>, DefaultAttributeContainer.Builder) -> Unit) {
consumer(POKEMON, PokemonEntity.createAttributes())
}
@@ -13,14 +13,14 @@ import com.cobblemon.mod.common.api.net.ClientNetworkPacketHandler
import com.cobblemon.mod.common.api.net.NetworkPacket
import com.cobblemon.mod.common.api.net.ServerNetworkPacketHandler
import com.mojang.brigadier.arguments.ArgumentType
import com.mojang.serialization.Codec
import kotlin.reflect.KClass
import net.minecraft.advancement.criterion.Criterion
import net.minecraft.block.ComposterBlock
import net.minecraft.command.argument.serialize.ArgumentSerializer
import net.minecraft.item.ItemConvertible
import net.minecraft.network.PacketByteBuf
import net.minecraft.network.listener.ClientPlayPacketListener
import net.minecraft.network.packet.Packet
import net.minecraft.registry.Registry
import net.minecraft.registry.RegistryKey
import net.minecraft.registry.tag.TagKey
import net.minecraft.resource.ResourceManager
@@ -28,12 +28,12 @@ import net.minecraft.resource.ResourceReloader
import net.minecraft.resource.ResourceType
import net.minecraft.server.MinecraftServer
import net.minecraft.server.network.ServerPlayerEntity
import net.minecraft.text.Text
import net.minecraft.util.Identifier
import net.minecraft.world.GameRules
import net.minecraft.world.biome.Biome
import net.minecraft.world.gen.GenerationStep
import net.minecraft.world.gen.feature.PlacedFeature
import org.jetbrains.annotations.ApiStatus
interface CobblemonImplementation {
val modAPI: ModAPI
@@ -172,33 +172,43 @@ interface CobblemonImplementation {
* @param manager The [ResourceManager] to reload from.
*/
fun <T> reloadJsonRegistry(registry: JsonDataRegistry<T>, manager: ResourceManager): HashMap<Identifier, T>
/**
* Queue the creation of a registry in the implementation.
* This registry will not be immediately available for access.
*
* @param T The type of the registry entries.
* @param registryKey The [RegistryKey] of this registry.
* @param codec The [Codec] used for this registry entries to be parsed on the server.
* @param networkCodec The [Codec] used when the client is synchronizing this registry from the server. If this is null the client will not require the registry aka not load any data.
*
* @see getRegistry
*/
@ApiStatus.Internal
fun <T> createRegistry(registryKey: RegistryKey<Registry<T>>, codec: Codec<T>, networkCodec: Codec<T>? = null)
/**
* Fetches a registry.
* This is intended for Cobblemon registries but can be used for any.
* Registers an item to the [ComposterBlock].
*
* @param T The type of the registry.
* @param registryKey The [RegistryKey] of the registry being fetched.
* @return The registry if present.
*
* @throws Exception If the registry doesn't exist or isn't loaded yet.
* @see createRegistry
* @param item The [ItemConvertible] being registered.
* @param chance The chance % of increasing the composter level, 0 to 1 expected.
*/
@ApiStatus.Internal
fun <T> getRegistry(registryKey: RegistryKey<Registry<T>>): Registry<T>
fun registerCompostable(item: ItemConvertible, chance: Float)
/**
* Registers a builtin resource pack.
*
* @param id The unique [Identifier] of this pack.
* @param title The title displayed in the resource pack GUI, the description is still a part of the pack metadata.
* @param activationBehaviour The [ResourcePackActivationBehaviour] for this pack.
*/
fun registerBuiltinResourcePack(id: Identifier, title: Text, activationBehaviour: ResourcePackActivationBehaviour)
}
enum class ResourcePackActivationBehaviour {
/**
* The resource pack will start disabled.
*/
NORMAL,
/**
* The resource pack will start enabled.
*/
DEFAULT_ENABLED,
/**
* The resource pack will always be enabled.
* The user can reorder it but cannot remove it.
*/
ALWAYS_ENABLED;
}
@@ -14,7 +14,9 @@ import com.cobblemon.mod.common.api.pokemon.Natures
import com.cobblemon.mod.common.api.pokemon.stats.Stats
import com.cobblemon.mod.common.api.pokemon.status.Statuses
import com.cobblemon.mod.common.block.BerryBlock
import com.cobblemon.mod.common.block.MintBlock
import com.cobblemon.mod.common.block.MintBlock.MintType
import com.cobblemon.mod.common.entity.boat.CobblemonBoatType
import com.cobblemon.mod.common.item.*
import com.cobblemon.mod.common.item.battle.DireHitItem
import com.cobblemon.mod.common.item.battle.GuardSpecItem
@@ -26,17 +28,21 @@ import com.cobblemon.mod.common.item.berry.PortionHealingBerryItem
import com.cobblemon.mod.common.item.berry.StatusCuringBerryItem
import com.cobblemon.mod.common.item.berry.VolatileCuringBerryItem
import com.cobblemon.mod.common.item.interactive.*
import com.cobblemon.mod.common.item.interactive.PotionItem
import com.cobblemon.mod.common.platform.PlatformRegistry
import com.cobblemon.mod.common.pokeball.PokeBall
import com.cobblemon.mod.common.pokemon.helditem.CobblemonHeldItemManager
import com.cobblemon.mod.common.util.cobblemonResource
import net.minecraft.block.Block
import net.minecraft.block.ComposterBlock
import net.minecraft.entity.LivingEntity
import net.minecraft.entity.effect.StatusEffectInstance
import net.minecraft.entity.effect.StatusEffects
import net.minecraft.item.*
import net.minecraft.item.BlockItem
import net.minecraft.item.FoodComponent
import net.minecraft.item.HangingSignItem
import net.minecraft.item.Item
import net.minecraft.item.ItemStack
import net.minecraft.item.SignItem
import net.minecraft.item.StewItem
import net.minecraft.registry.Registries
import net.minecraft.registry.Registry
import net.minecraft.registry.RegistryKey
@@ -117,40 +123,40 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, RegistryKey<Registry<It
val CHERISH_BALL = pokeBallItem(PokeBalls.CHERISH_BALL)
@JvmField
val VIVICHOKE = create("vivichoke", Item(Item.Settings()))
val VIVICHOKE = compostableItem("vivichoke")
@JvmField
val VIVICHOKE_SEEDS = create("vivichoke_seeds", VivichokeItem(CobblemonBlocks.VIVICHOKE_SEEDS))
val VIVICHOKE_SEEDS = compostableItem("vivichoke_seeds", VivichokeItem(CobblemonBlocks.VIVICHOKE_SEEDS))
@JvmField
val RED_APRICORN = create("red_apricorn", ApricornItem(CobblemonBlocks.RED_APRICORN))
val RED_APRICORN = apricornItem("red", ApricornItem(CobblemonBlocks.RED_APRICORN))
@JvmField
val YELLOW_APRICORN = create("yellow_apricorn", ApricornItem(CobblemonBlocks.YELLOW_APRICORN))
val YELLOW_APRICORN = apricornItem("yellow", ApricornItem(CobblemonBlocks.YELLOW_APRICORN))
@JvmField
val GREEN_APRICORN = create("green_apricorn", ApricornItem(CobblemonBlocks.GREEN_APRICORN))
val GREEN_APRICORN = apricornItem("green", ApricornItem(CobblemonBlocks.GREEN_APRICORN))
@JvmField
val BLUE_APRICORN = create("blue_apricorn", ApricornItem(CobblemonBlocks.BLUE_APRICORN))
val BLUE_APRICORN = apricornItem("blue", ApricornItem(CobblemonBlocks.BLUE_APRICORN))
@JvmField
val PINK_APRICORN = create("pink_apricorn", ApricornItem(CobblemonBlocks.PINK_APRICORN))
val PINK_APRICORN = apricornItem("pink", ApricornItem(CobblemonBlocks.PINK_APRICORN))
@JvmField
val BLACK_APRICORN = create("black_apricorn", ApricornItem(CobblemonBlocks.BLACK_APRICORN))
val BLACK_APRICORN = apricornItem("black", ApricornItem(CobblemonBlocks.BLACK_APRICORN))
@JvmField
val WHITE_APRICORN = create("white_apricorn", ApricornItem(CobblemonBlocks.WHITE_APRICORN))
val WHITE_APRICORN = apricornItem("white", ApricornItem(CobblemonBlocks.WHITE_APRICORN))
@JvmField
val RED_APRICORN_SEED = create("red_apricorn_seed", ApricornSeedItem(CobblemonBlocks.RED_APRICORN_SAPLING))
val RED_APRICORN_SEED = apricornSeedItem("red", ApricornSeedItem(CobblemonBlocks.RED_APRICORN_SAPLING))
@JvmField
val YELLOW_APRICORN_SEED = create("yellow_apricorn_seed", ApricornSeedItem(CobblemonBlocks.YELLOW_APRICORN_SAPLING))
val YELLOW_APRICORN_SEED = apricornSeedItem("yellow", ApricornSeedItem(CobblemonBlocks.YELLOW_APRICORN_SAPLING))
@JvmField
val GREEN_APRICORN_SEED = create("green_apricorn_seed", ApricornSeedItem(CobblemonBlocks.GREEN_APRICORN_SAPLING))
val GREEN_APRICORN_SEED = apricornSeedItem("green", ApricornSeedItem(CobblemonBlocks.GREEN_APRICORN_SAPLING))
@JvmField
val BLUE_APRICORN_SEED = create("blue_apricorn_seed", ApricornSeedItem(CobblemonBlocks.BLUE_APRICORN_SAPLING))
val BLUE_APRICORN_SEED = apricornSeedItem("blue", ApricornSeedItem(CobblemonBlocks.BLUE_APRICORN_SAPLING))
@JvmField
val PINK_APRICORN_SEED = create("pink_apricorn_seed", ApricornSeedItem(CobblemonBlocks.PINK_APRICORN_SAPLING))
val PINK_APRICORN_SEED = apricornSeedItem("pink", ApricornSeedItem(CobblemonBlocks.PINK_APRICORN_SAPLING))
@JvmField
val BLACK_APRICORN_SEED = create("black_apricorn_seed", ApricornSeedItem(CobblemonBlocks.BLACK_APRICORN_SAPLING))
val BLACK_APRICORN_SEED = apricornSeedItem("black", ApricornSeedItem(CobblemonBlocks.BLACK_APRICORN_SAPLING))
@JvmField
val WHITE_APRICORN_SEED = create("white_apricorn_seed", ApricornSeedItem(CobblemonBlocks.WHITE_APRICORN_SAPLING))
val WHITE_APRICORN_SEED = apricornSeedItem("white", ApricornSeedItem(CobblemonBlocks.WHITE_APRICORN_SAPLING))
@JvmField
val APRICORN_LOG = blockItem("apricorn_log", CobblemonBlocks.APRICORN_LOG)
@@ -163,13 +169,11 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, RegistryKey<Registry<It
@JvmField
val APRICORN_PLANKS = blockItem("apricorn_planks", CobblemonBlocks.APRICORN_PLANKS)
@JvmField
val APRICORN_LEAVES = blockItem("apricorn_leaves", CobblemonBlocks.APRICORN_LEAVES).also {
val compostChance = ComposterBlock.ITEM_TO_LEVEL_INCREASE_CHANCE.getFloat(Items.OAK_LEAVES)
// Should always pass unless Mojang reworks leaves to no longer work in the Composter, in that case we already updated w.o doing anything
if (compostChance != ComposterBlock.ITEM_TO_LEVEL_INCREASE_CHANCE.defaultReturnValue()) {
ComposterBlock.ITEM_TO_LEVEL_INCREASE_CHANCE[it] = compostChance
}
}
val APRICORN_LEAVES = compostableBlockItem("apricorn_leaves", CobblemonBlocks.APRICORN_LEAVES)
@JvmField
val APRICORN_BOAT = create("apricorn_boat", CobblemonBoatItem(CobblemonBoatType.APRICORN, false, Item.Settings().maxCount(1)))
@JvmField
val APRICORN_CHEST_BOAT = create("apricorn_chest_boat", CobblemonBoatItem(CobblemonBoatType.APRICORN, true, Item.Settings().maxCount(1)))
@JvmField
val APRICORN_DOOR = blockItem("apricorn_door", CobblemonBlocks.APRICORN_DOOR)
@@ -183,12 +187,14 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, RegistryKey<Registry<It
val APRICORN_BUTTON = blockItem("apricorn_button", CobblemonBlocks.APRICORN_BUTTON)
@JvmField
val APRICORN_PRESSURE_PLATE = blockItem("apricorn_pressure_plate", CobblemonBlocks.APRICORN_PRESSURE_PLATE)
//@JvmField
// val APRICORN_SIGN = create("apricorn_sign", SignItem(Item.Properties().stacksTo(16).tab(CreativeModeTab.TAB_DECORATIONS), CobblemonBlocks.APRICORN_SIGN, CobblemonBlocks.APRICORN_WALL_SIGN))
@JvmField
val APRICORN_SLAB = blockItem("apricorn_slab", CobblemonBlocks.APRICORN_SLAB)
@JvmField
val APRICORN_STAIRS = blockItem("apricorn_stairs", CobblemonBlocks.APRICORN_STAIRS)
@JvmField
val APRICORN_SIGN = this.create("apricorn_sign", SignItem(Item.Settings().maxCount(16), CobblemonBlocks.APRICORN_SIGN, CobblemonBlocks.APRICORN_WALL_SIGN))
@JvmField
val APRICORN_HANGING_SIGN = this.create("apricorn_hanging_sign", HangingSignItem(CobblemonBlocks.APRICORN_HANGING_SIGN, CobblemonBlocks.APRICORN_WALL_HANGING_SIGN, Item.Settings().maxCount(16)))
@JvmField
val HEALING_MACHINE = blockItem("healing_machine", CobblemonBlocks.HEALING_MACHINE)
@@ -353,11 +359,11 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, RegistryKey<Registry<It
}
})
@JvmField
val ENERGY_ROOT = create("energy_root", EnergyRootItem(CobblemonBlocks.ENERGY_ROOT, Item.Settings().food(FoodComponent.Builder().hunger(1).snack().saturationModifier(0.2f).build())))
val ENERGY_ROOT = compostableItem("energy_root", EnergyRootItem(CobblemonBlocks.ENERGY_ROOT, Item.Settings().food(FoodComponent.Builder().hunger(1).snack().saturationModifier(0.2f).build())))
@JvmField
val REVIVAL_HERB = create("revival_herb", RevivalHerbItem(CobblemonBlocks.REVIVAL_HERB))
val REVIVAL_HERB = compostableItem("revival_herb", RevivalHerbItem(CobblemonBlocks.REVIVAL_HERB))
@JvmField
val PEP_UP_FLOWER = blockItem("pep_up_flower", CobblemonBlocks.PEP_UP_FLOWER)
val PEP_UP_FLOWER = compostableBlockItem("pep_up_flower", CobblemonBlocks.PEP_UP_FLOWER)
@JvmField
val MEDICINAL_BREW = create("medicinal_brew", Item(Item.Settings()))
@JvmField
@@ -392,72 +398,74 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, RegistryKey<Registry<It
val PP_MAX = create("pp_max", PPUpItem(3))
@JvmField
val RED_MINT_SEEDS = blockItem("red_mint_seeds", MintType.RED.getCropBlock())
val RED_MINT_SEEDS = mintSeed("red", MintType.RED.getCropBlock())
@JvmField
val RED_MINT_LEAF = create("red_mint_leaf", MintLeafItem(MintType.RED))
val RED_MINT_LEAF = mintLeaf("red", MintLeafItem(MintType.RED))
@JvmField
val BLUE_MINT_SEEDS = blockItem("blue_mint_seeds", MintType.BLUE.getCropBlock())
val BLUE_MINT_SEEDS = mintSeed("blue", MintType.BLUE.getCropBlock())
@JvmField
val BLUE_MINT_LEAF = create("blue_mint_leaf", MintLeafItem(MintType.BLUE))
val BLUE_MINT_LEAF = mintLeaf("blue", MintLeafItem(MintType.BLUE))
@JvmField
val CYAN_MINT_SEEDS = blockItem("cyan_mint_seeds", MintType.CYAN.getCropBlock())
val CYAN_MINT_SEEDS = mintSeed("cyan", MintType.CYAN.getCropBlock())
@JvmField
val CYAN_MINT_LEAF = create("cyan_mint_leaf", MintLeafItem(MintType.CYAN))
val CYAN_MINT_LEAF = mintLeaf("cyan", MintLeafItem(MintType.CYAN))
@JvmField
val PINK_MINT_SEEDS = blockItem("pink_mint_seeds", MintType.PINK.getCropBlock())
val PINK_MINT_SEEDS = mintSeed("pink", MintType.PINK.getCropBlock())
@JvmField
val PINK_MINT_LEAF = create("pink_mint_leaf", MintLeafItem(MintType.PINK))
val PINK_MINT_LEAF = mintLeaf("pink", MintLeafItem(MintType.PINK))
@JvmField
val GREEN_MINT_SEEDS = blockItem("green_mint_seeds", MintType.GREEN.getCropBlock())
val GREEN_MINT_SEEDS = mintSeed("green", MintType.GREEN.getCropBlock())
@JvmField
val GREEN_MINT_LEAF = create("green_mint_leaf", MintLeafItem(MintType.GREEN))
val GREEN_MINT_LEAF = mintLeaf("green", MintLeafItem(MintType.GREEN))
@JvmField
val WHITE_MINT_SEEDS = blockItem("white_mint_seeds", MintType.WHITE.getCropBlock())
val WHITE_MINT_SEEDS = mintSeed("white", MintType.WHITE.getCropBlock())
@JvmField
val WHITE_MINT_LEAF = create("white_mint_leaf", MintLeafItem(MintType.WHITE))
val WHITE_MINT_LEAF = mintLeaf("white", MintLeafItem(MintType.WHITE))
val mints = mutableMapOf<String, MintItem>()
@JvmField
val LONELY_MINT = create("lonely_mint", MintItem(Natures.LONELY))
val LONELY_MINT = mintItem("lonely_mint", MintItem(Natures.LONELY))
@JvmField
val ADAMANT_MINT = create("adamant_mint", MintItem(Natures.ADAMANT))
val ADAMANT_MINT = mintItem("adamant_mint", MintItem(Natures.ADAMANT))
@JvmField
val NAUGHTY_MINT = create("naughty_mint", MintItem(Natures.NAUGHTY))
val NAUGHTY_MINT = mintItem("naughty_mint", MintItem(Natures.NAUGHTY))
@JvmField
val BRAVE_MINT = create("brave_mint", MintItem(Natures.BRAVE))
val BRAVE_MINT = mintItem("brave_mint", MintItem(Natures.BRAVE))
@JvmField
val BOLD_MINT = create("bold_mint", MintItem(Natures.BOLD))
val BOLD_MINT = mintItem("bold_mint", MintItem(Natures.BOLD))
@JvmField
val IMPISH_MINT = create("impish_mint", MintItem(Natures.IMPISH))
val IMPISH_MINT = mintItem("impish_mint", MintItem(Natures.IMPISH))
@JvmField
val LAX_MINT = create("lax_mint", MintItem(Natures.LAX))
val LAX_MINT = mintItem("lax_mint", MintItem(Natures.LAX))
@JvmField
val RELAXED_MINT = create("relaxed_mint", MintItem(Natures.RELAXED))
val RELAXED_MINT = mintItem("relaxed_mint", MintItem(Natures.RELAXED))
@JvmField
val MODEST_MINT = create("modest_mint", MintItem(Natures.MODEST))
val MODEST_MINT = mintItem("modest_mint", MintItem(Natures.MODEST))
@JvmField
val MILD_MINT = create("mild_mint", MintItem(Natures.MILD))
val MILD_MINT = mintItem("mild_mint", MintItem(Natures.MILD))
@JvmField
val RASH_MINT = create("rash_mint", MintItem(Natures.RASH))
val RASH_MINT = mintItem("rash_mint", MintItem(Natures.RASH))
@JvmField
val QUIET_MINT = create("quiet_mint", MintItem(Natures.QUIET))
val QUIET_MINT = mintItem("quiet_mint", MintItem(Natures.QUIET))
@JvmField
val CALM_MINT = create("calm_mint", MintItem(Natures.CALM))
val CALM_MINT = mintItem("calm_mint", MintItem(Natures.CALM))
@JvmField
val GENTLE_MINT = create("gentle_mint", MintItem(Natures.GENTLE))
val GENTLE_MINT = mintItem("gentle_mint", MintItem(Natures.GENTLE))
@JvmField
val CAREFUL_MINT = create("careful_mint", MintItem(Natures.CAREFUL))
val CAREFUL_MINT = mintItem("careful_mint", MintItem(Natures.CAREFUL))
@JvmField
val SASSY_MINT = create("sassy_mint", MintItem(Natures.SASSY))
val SASSY_MINT = mintItem("sassy_mint", MintItem(Natures.SASSY))
@JvmField
val TIMID_MINT = create("timid_mint", MintItem(Natures.TIMID))
val TIMID_MINT = mintItem("timid_mint", MintItem(Natures.TIMID))
@JvmField
val HASTY_MINT = create("hasty_mint", MintItem(Natures.HASTY))
val HASTY_MINT = mintItem("hasty_mint", MintItem(Natures.HASTY))
@JvmField
val JOLLY_MINT = create("jolly_mint", MintItem(Natures.JOLLY))
val JOLLY_MINT = mintItem("jolly_mint", MintItem(Natures.JOLLY))
@JvmField
val NAIVE_MINT = create("naive_mint", MintItem(Natures.NAIVE))
val NAIVE_MINT = mintItem("naive_mint", MintItem(Natures.NAIVE))
@JvmField
val SERIOUS_MINT = create("serious_mint", MintItem(Natures.SERIOUS))
val SERIOUS_MINT = mintItem("serious_mint", MintItem(Natures.SERIOUS))
@JvmField val X_ACCURACY = create("x_${Stats.ACCURACY.identifier.path}", XStatItem(Stats.ACCURACY))
@JvmField val X_ATTACK = create("x_${Stats.ATTACK.identifier.path}", XStatItem(Stats.ATTACK))
@@ -568,10 +576,14 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, RegistryKey<Registry<It
@JvmField
val CHOICE_SPECS = heldItem("choice_specs")
@JvmField
val CLEANSE_TAG = heldItem("cleanse_tag")
@JvmField
val DRAGON_FANG = heldItem("dragon_fang")
@JvmField
val EXP_SHARE = heldItem("exp_share")
@JvmField
val FAIRY_FEATHER = heldItem("fairy_feather")
@JvmField
val FOCUS_BAND = heldItem("focus_band")
@JvmField
val HARD_STONE = heldItem("hard_stone")
@@ -616,13 +628,13 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, RegistryKey<Registry<It
@JvmField
val WISE_GLASSES = heldItem("wise_glasses")
@JvmField
val MENTAL_HERB = heldItem("mental_herb")
val MENTAL_HERB = compostableHeldItem("mental_herb", null, 1F)
@JvmField
val MIRROR_HERB = heldItem("mirror_herb")
val MIRROR_HERB = compostableHeldItem("mirror_herb", null, 1F)
@JvmField
val POWER_HERB = heldItem("power_herb")
val POWER_HERB = compostableHeldItem("power_herb", null, 1F)
@JvmField
val WHITE_HERB = heldItem("white_herb")
val WHITE_HERB = compostableHeldItem("white_herb", null, 1F)
@JvmField
val BRIGHT_POWDER = heldItem("bright_powder")
@JvmField
@@ -645,6 +657,14 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, RegistryKey<Registry<It
val POWER_LENS = heldItem("power_lens")
@JvmField
val POWER_WEIGHT = heldItem("power_weight")
@JvmField
val FLAME_ORB = heldItem("flame_orb")
@JvmField
val LIFE_ORB = heldItem("life_orb")
@JvmField
val TOXIC_ORB = heldItem("toxic_orb")
@JvmField
val SMOKE_BALL = heldItem("smoke_ball")
// Mulch
@JvmField
@@ -696,9 +716,12 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, RegistryKey<Registry<It
}
)
private fun compostable(item: Item, increaseLevelChance: Float) = Cobblemon.implementation.registerCompostable(item, increaseLevelChance)
private fun berryItem(name: String, berryBlock: BerryBlock): BerryItem {
val finalName = "${name}_berry"
val item = this.create(finalName, BerryItem(berryBlock))
compostable(item, .65f)
this.berries[cobblemonResource(finalName)] = item
return item
}
@@ -706,7 +729,62 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, RegistryKey<Registry<It
private fun berryItem(name: String, berryItem: BerryItem): BerryItem {
val finalName = "${name}_berry"
val item = this.create(finalName, berryItem)
compostable(item, .65f)
this.berries[cobblemonResource(finalName)] = item
return item
}
private fun mintItem(name: String, mintItem: MintItem): MintItem {
val item = this.create(name, mintItem)
mints[item.nature.displayName] = item
compostable(item, .65f)
return item
}
private fun apricornItem(name: String, apricornItem: ApricornItem): ApricornItem {
val finalName = "${name}_apricorn"
val item = this.create(finalName, apricornItem)
compostable(item, .65f)
return item
}
private fun apricornSeedItem(name: String, apricornSeedItem: ApricornSeedItem): ApricornSeedItem {
val finalName = "${name}_apricorn_seed"
val item = this.create(finalName, apricornSeedItem)
compostable(item, .65f)
return item
}
private fun mintSeed(name: String, mintBlock: MintBlock): Item {
val finalName = "${name}_mint_seeds"
val item = this.blockItem(finalName, mintBlock)
compostable(item, .65f)
return item
}
private fun mintLeaf(name: String, mintLeafItem: MintLeafItem): MintLeafItem {
val finalName = "${name}_mint_leaf"
val item = this.create(finalName, mintLeafItem)
compostable(item, .65f)
return item
}
private fun compostableItem(name: String, item: Item? = null, increaseLevelChance: Float = .65f): Item {
val createdItem = this.create(name, item ?: Item(Item.Settings()))
compostable(createdItem, increaseLevelChance)
return createdItem
}
private fun compostableHeldItem(name: String, remappedName: String? = null, increaseLevelChance: Float = .65f): CobblemonItem {
val createdItem = heldItem(name, remappedName)
compostable(createdItem, increaseLevelChance)
return createdItem
}
private fun compostableBlockItem(name: String, block: Block, increaseLevelChance: Float = .65f): Item {
val createdItem = this.blockItem(name, block)
compostable(createdItem, increaseLevelChance)
return createdItem
}
}
@@ -11,8 +11,27 @@ package com.cobblemon.mod.common
import com.cobblemon.mod.common.api.net.ClientNetworkPacketHandler
import com.cobblemon.mod.common.api.net.NetworkPacket
import com.cobblemon.mod.common.api.net.ServerNetworkPacketHandler
import com.cobblemon.mod.common.client.net.PlayerInteractOptionsHandler
import com.cobblemon.mod.common.client.net.SetClientPlayerDataHandler
import com.cobblemon.mod.common.client.net.battle.*
import com.cobblemon.mod.common.client.net.battle.BattleApplyPassResponseHandler
import com.cobblemon.mod.common.client.net.battle.BattleCaptureEndHandler
import com.cobblemon.mod.common.client.net.battle.BattleCaptureShakeHandler
import com.cobblemon.mod.common.client.net.battle.BattleCaptureStartHandler
import com.cobblemon.mod.common.client.net.battle.BattleChallengeExpiredHandler
import com.cobblemon.mod.common.client.net.battle.BattleChallengeNotificationHandler
import com.cobblemon.mod.common.client.net.battle.BattleEndHandler
import com.cobblemon.mod.common.client.net.battle.BattleFaintHandler
import com.cobblemon.mod.common.client.net.battle.BattleHealthChangeHandler
import com.cobblemon.mod.common.client.net.battle.BattleInitializeHandler
import com.cobblemon.mod.common.client.net.battle.BattleMadeInvalidChoiceHandler
import com.cobblemon.mod.common.client.net.battle.BattleMakeChoiceHandler
import com.cobblemon.mod.common.client.net.battle.BattleMessageHandler
import com.cobblemon.mod.common.client.net.battle.BattleMusicHandler
import com.cobblemon.mod.common.client.net.battle.BattlePersistentStatusHandler
import com.cobblemon.mod.common.client.net.battle.BattleQueueRequestHandler
import com.cobblemon.mod.common.client.net.battle.BattleSetTeamPokemonHandler
import com.cobblemon.mod.common.client.net.battle.BattleSwitchPokemonHandler
import com.cobblemon.mod.common.client.net.battle.BattleUpdateTeamPokemonHandler
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
@@ -51,12 +70,16 @@ import com.cobblemon.mod.common.client.net.trade.TradeOfferExpiredHandler
import com.cobblemon.mod.common.client.net.trade.TradeOfferNotificationHandler
import com.cobblemon.mod.common.client.net.trade.TradeStartedHandler
import com.cobblemon.mod.common.client.net.trade.TradeUpdatedHandler
import com.cobblemon.mod.common.net.messages.client.PlayerInteractOptionsPacket
import com.cobblemon.mod.common.net.messages.client.battle.*
import com.cobblemon.mod.common.net.messages.client.callback.OpenMoveCallbackPacket
import com.cobblemon.mod.common.net.messages.client.callback.OpenPartyCallbackPacket
import com.cobblemon.mod.common.net.messages.client.callback.OpenPartyMoveCallbackPacket
import com.cobblemon.mod.common.net.messages.client.data.*
import com.cobblemon.mod.common.net.messages.client.data.AbilityRegistrySyncPacket
import com.cobblemon.mod.common.net.messages.client.data.BerryRegistrySyncPacket
import com.cobblemon.mod.common.net.messages.client.data.MovesRegistrySyncPacket
import com.cobblemon.mod.common.net.messages.client.data.PropertiesCompletionRegistrySyncPacket
import com.cobblemon.mod.common.net.messages.client.data.SpeciesRegistrySyncPacket
import com.cobblemon.mod.common.net.messages.client.data.UnlockReloadPacket
import com.cobblemon.mod.common.net.messages.client.effect.SpawnSnowstormParticlePacket
import com.cobblemon.mod.common.net.messages.client.pasture.ClosePasturePacket
@@ -96,12 +119,10 @@ import com.cobblemon.mod.common.net.messages.client.trade.TradeStartedPacket
import com.cobblemon.mod.common.net.messages.client.trade.TradeUpdatedPacket
import com.cobblemon.mod.common.net.messages.client.ui.InteractPokemonUIPacket
import com.cobblemon.mod.common.net.messages.client.ui.SummaryUIPacket
import com.cobblemon.mod.common.net.messages.server.BattleChallengePacket
import com.cobblemon.mod.common.net.messages.server.BenchMovePacket
import com.cobblemon.mod.common.net.messages.server.RequestMoveSwapPacket
import com.cobblemon.mod.common.net.messages.server.SelectStarterPacket
import com.cobblemon.mod.common.net.messages.server.SendOutPokemonPacket
import com.cobblemon.mod.common.net.messages.server.*
import com.cobblemon.mod.common.net.messages.server.battle.BattleSelectActionsPacket
import com.cobblemon.mod.common.net.messages.server.battle.RemoveSpectatorPacket
import com.cobblemon.mod.common.net.messages.server.battle.SpectateBattlePacket
import com.cobblemon.mod.common.net.messages.server.callback.move.MoveSelectCancelledPacket
import com.cobblemon.mod.common.net.messages.server.callback.move.MoveSelectedPacket
import com.cobblemon.mod.common.net.messages.server.callback.party.PartyPokemonSelectedPacket
@@ -131,7 +152,10 @@ import com.cobblemon.mod.common.net.messages.server.trade.ChangeTradeAcceptanceP
import com.cobblemon.mod.common.net.messages.server.trade.OfferTradePacket
import com.cobblemon.mod.common.net.messages.server.trade.UpdateTradeOfferPacket
import com.cobblemon.mod.common.net.serverhandling.ChallengeHandler
import com.cobblemon.mod.common.net.serverhandling.RequestInteractionsHandler
import com.cobblemon.mod.common.net.serverhandling.battle.BattleSelectActionsHandler
import com.cobblemon.mod.common.net.serverhandling.battle.RemoveSpectatorHandler
import com.cobblemon.mod.common.net.serverhandling.battle.SpectateBattleHandler
import com.cobblemon.mod.common.net.serverhandling.callback.move.MoveSelectCancelledHandler
import com.cobblemon.mod.common.net.serverhandling.callback.move.MoveSelectedHandler
import com.cobblemon.mod.common.net.serverhandling.callback.party.PartyPokemonSelectedHandler
@@ -165,12 +189,12 @@ import com.cobblemon.mod.common.net.serverhandling.trade.ChangeTradeAcceptanceHa
import com.cobblemon.mod.common.net.serverhandling.trade.OfferTradeHandler
import com.cobblemon.mod.common.net.serverhandling.trade.UpdateTradeOfferHandler
import com.cobblemon.mod.common.util.server
import kotlin.reflect.KClass
import net.minecraft.network.PacketByteBuf
import net.minecraft.network.listener.ClientPlayPacketListener
import net.minecraft.network.packet.Packet
import net.minecraft.server.network.ServerPlayerEntity
import net.minecraft.util.Identifier
import kotlin.reflect.KClass
/**
* Registers Cobblemon network packets.
@@ -235,6 +259,7 @@ object CobblemonNetwork : NetworkManager {
// UI Packets
this.createClientBound(SummaryUIPacket.ID, SummaryUIPacket::decode, SummaryUIPacketHandler)
this.createClientBound(InteractPokemonUIPacket.ID, InteractPokemonUIPacket::decode, InteractPokemonUIPacketHandler)
this.createClientBound(PlayerInteractOptionsPacket.ID, PlayerInteractOptionsPacket::decode, PlayerInteractOptionsHandler)
// Starter packets
this.createClientBound(OpenStarterUIPacket.ID, OpenStarterUIPacket::decode, StarterUIPacketHandler)
@@ -320,6 +345,7 @@ object CobblemonNetwork : NetworkManager {
// Interaction Packets
this.createServerBound(InteractPokemonPacket.ID, InteractPokemonPacket::decode, InteractPokemonHandler)
this.createServerBound(RequestPlayerInteractionsPacket.ID, RequestPlayerInteractionsPacket::decode, RequestInteractionsHandler)
// Storage Packets
this.createServerBound(SendOutPokemonPacket.ID, SendOutPokemonPacket::decode, SendOutPokemonHandler)
@@ -347,6 +373,8 @@ object CobblemonNetwork : NetworkManager {
// Battle packets
this.createServerBound(BattleSelectActionsPacket.ID, BattleSelectActionsPacket::decode, BattleSelectActionsHandler)
this.createServerBound(SpectateBattlePacket.ID, SpectateBattlePacket::decode, SpectateBattleHandler)
this.createServerBound(RemoveSpectatorPacket.ID, RemoveSpectatorPacket::decode, RemoveSpectatorHandler)
// Trade
this.createServerBound(AcceptTradeRequestPacket.ID, AcceptTradeRequestPacket::decode, AcceptTradeRequestHandler)
@@ -8,7 +8,6 @@
package com.cobblemon.mod.common.advancement.criterion
import com.cobblemon.mod.common.util.asIdentifierDefaultingNamespace
import com.google.gson.JsonObject
import net.minecraft.predicate.entity.LootContextPredicate
import net.minecraft.server.network.ServerPlayerEntity
@@ -31,11 +30,7 @@ class CaughtPokemonCriterionCondition(id: Identifier, predicate: LootContextPred
override fun fromJson(json: JsonObject) {
super.fromJson(json)
var stored = json.get("type")?.asString
if (stored != null && stored != "any") {
stored = stored.asIdentifierDefaultingNamespace().toString()
}
type = stored ?: "any"
type = json.get("type")?.asString ?: "any"
}
override fun matches(player: ServerPlayerEntity, context: CountablePokemonTypeContext): Boolean {
@@ -12,8 +12,6 @@ import com.cobblemon.mod.common.Cobblemon.LOGGER
import com.cobblemon.mod.common.api.PrioritizedList
import com.cobblemon.mod.common.api.Priority
import com.cobblemon.mod.common.pokemon.Species
import com.mojang.serialization.Codec
import com.mojang.serialization.DataResult
/**
* A pool of potential abilities, as a [PrioritizedList]. The added logic of this subclass
@@ -37,22 +35,4 @@ open class AbilityPool : PrioritizedList<PotentialAbility>() {
Exception().printStackTrace()
return Abilities.first().create() to Priority.LOWEST
}
companion object {
@JvmField
val CODEC: Codec<AbilityPool> = Codec.list(Codec.STRING)
.comapFlatMap(
{ raw ->
val pool = AbilityPool()
if (raw.isEmpty()) {
return@comapFlatMap DataResult.error { "Cannot create ability pool from an empty list" }
}
raw.forEach { }
DataResult.success(pool)
}
)
}
}
@@ -10,12 +10,9 @@ package com.cobblemon.mod.common.api.abilities
import com.cobblemon.mod.common.api.Priority
import com.google.gson.JsonElement
import com.mojang.serialization.Codec
interface PotentialAbilityType<T : PotentialAbility> {
fun parseFromJSON(element: JsonElement): T?
fun codec(): Codec<out PotentialAbilityType<*>>
}
/**
@@ -48,10 +45,6 @@ object CommonAbilityType : PotentialAbilityType<CommonAbility> {
}
}
}
override fun codec(): Codec<out PotentialAbilityType<*>> {
TODO("Not yet implemented")
}
}
open class CommonAbility(override val template: AbilityTemplate) : PotentialAbility {
@@ -10,8 +10,6 @@ package com.cobblemon.mod.common.api.ai
import com.cobblemon.mod.common.api.serialization.StringIdentifiedObjectAdapter
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import com.mojang.serialization.Codec
import com.mojang.serialization.DataResult
import net.minecraft.entity.ai.TargetPredicate
import net.minecraft.util.math.Box
@@ -46,11 +44,6 @@ interface SleepDepth {
"normal" to normal
)
val adapter = StringIdentifiedObjectAdapter { depths[it] ?: throw IllegalArgumentException("Unknown sleep depth: $it") }
val CODEC: Codec<SleepDepth> = Codec.STRING.flatXmap(
{ string -> depths[string]?.let { DataResult.success(it) } ?: DataResult.error { "Cannot find a SleepDepth with the ID $string" } },
{ depth -> depths.entries.firstOrNull { it.value == depth }?.let { DataResult.success(it.key) } ?: DataResult.error { "Cannot resolve a ID for the SleepDepth $depth" } }
)
}
fun canSleep(pokemonEntity: PokemonEntity): Boolean
@@ -40,14 +40,15 @@ import com.cobblemon.mod.common.net.messages.client.battle.BattleEndPacket
import com.cobblemon.mod.common.net.messages.client.battle.BattleMessagePacket
import com.cobblemon.mod.common.net.messages.client.battle.BattleMusicPacket
import com.cobblemon.mod.common.pokemon.evolution.progress.DefeatEvolutionProgress
import com.cobblemon.mod.common.pokemon.evolution.progress.LastBattleCriticalHitsEvolutionProgress
import com.cobblemon.mod.common.pokemon.evolution.requirements.DefeatRequirement
import com.cobblemon.mod.common.util.battleLang
import com.cobblemon.mod.common.util.getPlayer
import java.io.File
import java.util.UUID
import java.util.concurrent.ConcurrentLinkedQueue
import net.minecraft.server.network.ServerPlayerEntity
import net.minecraft.text.Text
import java.util.concurrent.ConcurrentLinkedDeque
/**
* Individual battle instance
@@ -55,6 +56,7 @@ import net.minecraft.text.Text
* @since January 16th, 2022
* @author Deltric, Hiroku
*/
@Suppress("unused", "MemberVisibilityCanBePrivate")
open class PokemonBattle(
val format: BattleFormat,
val side1: BattleSide,
@@ -67,8 +69,11 @@ open class PokemonBattle(
side1.battle = this
side2.battle = this
this.actors.forEach { actor ->
actor.battle = this
actor.pokemonList.forEach { battlePokemon ->
battlePokemon.criticalHits = 0
battlePokemon.effectedPokemon.evolutionProxy.current().progress()
.filterIsInstance<LastBattleCriticalHitsEvolutionProgress>()
.forEach { it.reset() }
}
}
}
@@ -82,12 +87,13 @@ open class PokemonBattle(
val playerUUIDs: Iterable<UUID>
get() = actors.flatMap { it.getPlayerUUIDs() }
val players = playerUUIDs.mapNotNull { it.getPlayer() }
val spectators = mutableListOf<UUID>()
val spectators = mutableSetOf<UUID>()
val battleId = UUID.randomUUID()
val showdownMessages = mutableListOf<String>()
val battleLog = mutableListOf<String>()
val chatLog = mutableListOf<Text>()
var started = false
var ended = false
// TEMP battle showcase stuff
@@ -97,7 +103,7 @@ open class PokemonBattle(
var dispatchResult = GO
val dispatches = ConcurrentLinkedQueue<BattleDispatch>()
val dispatches = ConcurrentLinkedDeque<BattleDispatch>()
val afterDispatches = mutableListOf<() -> Unit>()
val captureActions = mutableListOf<BattleCaptureAction>()
@@ -175,11 +181,8 @@ open class PokemonBattle(
}
fun broadcastChatMessage(component: Text) {
spectators.forEach { spectatorId ->
spectatorId.getPlayer()?.let {
CobblemonNetwork.sendPacketToPlayer(it, BattleMessagePacket(component))
}
}
chatLog.add(component)
sendSpectatorUpdate(BattleMessagePacket(component))
return actors.forEach { it.sendMessage(component) }
}
@@ -250,7 +253,6 @@ open class PokemonBattle(
}
}
sendUpdate(BattleEndPacket())
sendUpdate(BattleMusicPacket(null))
BattleRegistry.closeBattle(this)
}
@@ -317,6 +319,12 @@ open class PokemonBattle(
fun dispatch(dispatcher: () -> DispatchResult) {
dispatches.add(BattleDispatch { dispatcher() })
}
fun dispatchToFront(dispatcher: () -> DispatchResult) {
dispatches.addFirst(BattleDispatch { dispatcher() })
}
fun dispatchGo(dispatcher: () -> Unit) {
@@ -348,6 +356,10 @@ open class PokemonBattle(
dispatches.add(dispatcher)
}
fun dispatchToFront(dispatcher: BattleDispatch) {
dispatches.addFirst(dispatcher)
}
fun doWhenClear(action: () -> Unit) {
afterDispatches.add(action)
}
@@ -26,13 +26,20 @@ abstract class AIBattleActor(
super.sendUpdate(packet)
if (packet is BattleMakeChoicePacket) {
try {
setActionResponses(request!!.iterate(this.activePokemon, battleAI::choose))
} catch (exception: IllegalActionChoiceException) {
LOGGER.error("AI was unable to choose a move, we're going to need to pass!")
exception.printStackTrace()
setActionResponses(request!!.iterate(this.activePokemon) { _, _, _ -> PassActionResponse })
}
this.onChoiceRequested()
}
}
/**
* Called when the AI is requested to make a choice.
*/
open fun onChoiceRequested() {
try {
setActionResponses(request!!.iterate(this.activePokemon, battleAI::choose))
} catch (exception: IllegalActionChoiceException) {
LOGGER.error("AI was unable to choose a move, we're going to need to pass!")
exception.printStackTrace()
setActionResponses(request!!.iterate(this.activePokemon) { _, _, _ -> PassActionResponse })
}
}
}
@@ -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.api.conditional
import net.minecraft.registry.Registry
import net.minecraft.util.Identifier
class RegistryElementCondition<T>(val element: T, private val source: Identifier) : RegistryLikeCondition<T> {
override fun fits(value: T, registry: Registry<T>): Boolean = value == this.element
override fun pretty(): String = this.source.toString()
}
@@ -0,0 +1,31 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.conditional
import com.google.gson.JsonDeserializationContext
import com.google.gson.JsonDeserializer
import com.google.gson.JsonElement
import java.lang.reflect.Type
/**
* Adapter for [RegistryLikeCondition]s. Its logic is that the implementation of this adapter must
* provide a list of resolvers, and the deserializer will find the first resolver that returns a non-null
* value for the [JsonElement].
*
* @author Hiroku
* @since July 17th, 2022
*/
interface RegistryLikeAdapter<B> : JsonDeserializer<RegistryLikeCondition<B>> {
val registryLikeConditions: MutableList<(JsonElement) -> RegistryLikeCondition<B>?>
override fun deserialize(json: JsonElement, type: Type, ctx: JsonDeserializationContext): RegistryLikeCondition<B> {
return registryLikeConditions.firstNotNullOfOrNull { it(json) }
?: throw IllegalArgumentException("Unable to deserialize $json")
}
}
@@ -8,11 +8,7 @@
package com.cobblemon.mod.common.api.conditional
import com.mojang.serialization.Codec
import com.mojang.serialization.DataResult
import net.minecraft.registry.Registry
import net.minecraft.registry.tag.TagKey
import net.minecraft.util.Identifier
/**
* A condition which applies to an entry in some [Registry].
@@ -20,43 +16,6 @@ import net.minecraft.util.Identifier
* @author Hiroku
* @since July 16th, 2022
*/
sealed interface RegistryLikeCondition<T> {
/**
* Checks if a given [value] matches this condition.
*
* @param value The value being matched against this condition.
* @param registry The [Registry] of type [T] being queried.
* @return If the condition is fulfilled.
*/
fun fits(value: T, registry: Registry<T>): Boolean
/**
* Generates a string like human-friendly representation used by the Codec when serializing.
*
* @return The string like human-friendly representation.
*/
fun pretty(): String
companion object {
@JvmStatic
fun <T> createCodec(registryAccessor: () -> Registry<T>): Codec<RegistryLikeCondition<T>> = Codec.STRING.comapFlatMap(
{ string ->
val registry = registryAccessor.invoke()
val isTag = string.startsWith("#")
val rawIdentifier = if (isTag) string.substringAfter("#") else string
val identifier = Identifier.tryParse(rawIdentifier) ?: return@comapFlatMap DataResult.error { "Cannot resolve identifier/tag from the string $string" }
if (isTag) {
val tag = TagKey.of(registry.key, identifier)
return@comapFlatMap DataResult.success(RegistryTagCondition(tag))
}
val element = registry.get(identifier) ?: return@comapFlatMap DataResult.error { "Cannot find an element in registry ${registry.key.value} with the ID $identifier" }
return@comapFlatMap DataResult.success(RegistryElementCondition(element, identifier))
},
{ it.pretty() }
)
}
interface RegistryLikeCondition<T> {
fun fits(t: T, registry: Registry<T>): Boolean
}
@@ -0,0 +1,28 @@
/*
* 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.conditional
import com.google.gson.JsonElement
import net.minecraft.registry.Registry
import net.minecraft.util.Identifier
/**
* A condition for some registry type which asserts that the entry must have the given [Identifier].
*
* @author Hiroku
* @since July 16th, 2022
*/
open class RegistryLikeIdentifierCondition<T>(val identifier: Identifier) : RegistryLikeCondition<T> {
companion object {
fun <T> resolver(
constructor: (Identifier) -> RegistryLikeIdentifierCondition<T>
): (JsonElement) -> RegistryLikeIdentifierCondition<T>? = { constructor(Identifier(it.asString)) }
}
override fun fits(t: T, registry: Registry<T>) = registry.getId(t) == identifier
}
@@ -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.api.conditional
import com.google.gson.JsonElement
import net.minecraft.registry.Registry
import net.minecraft.registry.RegistryKey
import net.minecraft.registry.tag.TagKey
import net.minecraft.util.Identifier
/**
* A condition for some registry type that asserts that the entry must be inside the given [TagKey]. This is presented
* in JSONs as an identifier prefixed with a hash.
*
* @author Hiroku
* @since July 16th, 2022
*/
open class RegistryLikeTagCondition<T>(val tag: TagKey<T>) : RegistryLikeCondition<T> {
companion object {
const val PREFIX = "#"
fun <T> resolver(
registryKey: RegistryKey<Registry<T>>,
constructor: (TagKey<T>) -> RegistryLikeTagCondition<T>
): (JsonElement) -> RegistryLikeTagCondition<T>? = {
val firstSymbol = it.asString.substring(0, 1)
if (firstSymbol == PREFIX) {
val identifier = Identifier(it.asString.substring(1))
constructor(TagKey.of(registryKey, identifier))
} else {
null
}
}
}
override fun fits(t: T, registry: Registry<T>): Boolean {
// val registryHasTag = registry.containsTag(tag)
// if (!registryHasTag) {
//// LOGGER.warn("No tag in registry: ${tag.id}")
// return false
// }
return registry.getKey(t)
.flatMap(registry::getEntry)
.map { entry -> entry.isIn(tag) }
.orElse(false)
}
}
@@ -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.api.conditional
import net.minecraft.registry.Registry
import net.minecraft.registry.tag.TagKey
class RegistryTagCondition<T>(val tag: TagKey<T>) : RegistryLikeCondition<T> {
override fun fits(value: T, registry: Registry<T>): Boolean = registry.getEntry(value).isIn(this.tag)
override fun pretty(): String = "#${this.tag.id}"
}
@@ -10,11 +10,11 @@ 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 kotlin.random.Random
import net.minecraft.entity.LivingEntity
import net.minecraft.server.network.ServerPlayerEntity
import net.minecraft.server.world.ServerWorld
import net.minecraft.util.math.Vec3d
import kotlin.random.Random
/**
* A table of drops that can produce a list of [DropEntry]. You can produce a drop list from [getDrops] to
@@ -8,7 +8,11 @@
package com.cobblemon.mod.common.api.events
import com.cobblemon.mod.common.api.events.battles.*
import com.cobblemon.mod.common.api.events.battles.BattleFaintedEvent
import com.cobblemon.mod.common.api.events.battles.BattleFledEvent
import com.cobblemon.mod.common.api.events.battles.BattleStartedPostEvent
import com.cobblemon.mod.common.api.events.battles.BattleStartedPreEvent
import com.cobblemon.mod.common.api.events.battles.BattleVictoryEvent
import com.cobblemon.mod.common.api.events.berry.BerryHarvestEvent
import com.cobblemon.mod.common.api.events.berry.BerryMutationOfferEvent
import com.cobblemon.mod.common.api.events.berry.BerryMutationResultEvent
@@ -27,6 +31,7 @@ import com.cobblemon.mod.common.api.events.pokemon.*
import com.cobblemon.mod.common.api.events.pokemon.evolution.EvolutionAcceptedEvent
import com.cobblemon.mod.common.api.events.pokemon.evolution.EvolutionCompleteEvent
import com.cobblemon.mod.common.api.events.pokemon.evolution.EvolutionDisplayEvent
import com.cobblemon.mod.common.api.events.pokemon.evolution.EvolutionTestedEvent
import com.cobblemon.mod.common.api.events.pokemon.interaction.ExperienceCandyUseEvent
import com.cobblemon.mod.common.api.events.starter.StarterChosenEvent
import com.cobblemon.mod.common.api.events.storage.ReleasePokemonEvent
@@ -55,6 +60,8 @@ object CobblemonEvents {
@JvmField
val EVOLUTION_DISPLAY = EventObservable<EvolutionDisplayEvent>()
@JvmField
val EVOLUTION_TESTED = EventObservable<EvolutionTestedEvent>()
@JvmField
val EVOLUTION_COMPLETE = EventObservable<EvolutionCompleteEvent>()
@JvmField
val POKEMON_NICKNAMED = CancelableObservable<PokemonNicknamedEvent>()
@@ -102,12 +109,14 @@ object CobblemonEvents {
@JvmField
val ENTITY_SPAWN = CancelableObservable<SpawnEvent<*>>()
@Suppress("UNCHECKED_CAST")
@JvmField
val POKEMON_ENTITY_SPAWN = ENTITY_SPAWN
.pipe(
filter { it.entity is PokemonEntity },
map { it as SpawnEvent<PokemonEntity> }
map {
@Suppress("UNCHECKED_CAST")
it as SpawnEvent<PokemonEntity>
}
)
@JvmField
@@ -9,26 +9,19 @@
package com.cobblemon.mod.common.api.events.battles
import com.cobblemon.mod.common.api.battles.model.PokemonBattle
import com.cobblemon.mod.common.api.battles.model.actor.BattleActor
import com.cobblemon.mod.common.api.events.Cancelable
import com.cobblemon.mod.common.battles.BattleFormat
import net.minecraft.text.MutableText
/**
* Event fired before a [PokemonBattle] is started. Canceling this event prevents the battle from being
* created and launched.
*
* @property reason The text used to inform the participants why the battle was canceled. Keep null for a default error.
*
* @author Segfault Guy
* @since March 26th 2023
*/
data class BattleStartedPreEvent (
val participants: Collection<BattleActor>,
val format: BattleFormat,
val isPvP: Boolean,
val isPvN: Boolean,
val isPvW: Boolean
) : Cancelable()
data class BattleStartedPreEvent (override val battle: PokemonBattle, var reason: MutableText? = null) : BattleEvent, Cancelable()
/**
* Event fired after a [PokemonBattle] starts.
@@ -36,8 +29,4 @@ data class BattleStartedPreEvent (
* @author Segfault Guy
* @since March 26th 2023
*/
data class BattleStartedPostEvent (
override val battle: PokemonBattle
) : BattleEvent
data class BattleStartedPostEvent (override val battle: PokemonBattle) : BattleEvent
@@ -23,6 +23,6 @@ import com.cobblemon.mod.common.pokemon.Pokemon
* @since April 28th, 2022
*/
data class EvolutionAcceptedEvent(
val pokemon: Pokemon,
val evolution: Evolution
) : Cancelable()
override val pokemon: Pokemon,
override val evolution: Evolution
) : Cancelable(), EvolutionEvent
@@ -21,6 +21,6 @@ import com.cobblemon.mod.common.pokemon.Pokemon
* @since October 2nd, 2022
*/
data class EvolutionCompleteEvent(
val pokemon: Pokemon,
val evolution: Evolution
)
override val pokemon: Pokemon,
override val evolution: Evolution
) : EvolutionEvent
@@ -25,7 +25,7 @@ import com.cobblemon.mod.common.pokemon.Pokemon
* @since May 3rd, 2022
*/
data class EvolutionDisplayEvent(
val pokemon: Pokemon,
override val pokemon: Pokemon,
var display: EvolutionDisplay,
val evolution: Evolution
)
override val evolution: Evolution
) : EvolutionEvent
@@ -0,0 +1,29 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.events.pokemon.evolution
import com.cobblemon.mod.common.api.pokemon.evolution.Evolution
import com.cobblemon.mod.common.pokemon.Pokemon
/**
* The root of the various evolution related events.
*/
interface EvolutionEvent {
/**
* The Pokémon impacted in this event.
*/
val pokemon: Pokemon
/**
* The evolution triggering this event.
*/
val evolution: Evolution
}
@@ -0,0 +1,28 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.events.pokemon.evolution
import com.cobblemon.mod.common.api.pokemon.evolution.Evolution
import com.cobblemon.mod.common.pokemon.Pokemon
/**
* An event fired when [Evolution.test] has been performed.
* The final state [result] will be the return value of the test function.
*
* @property pokemon The [Pokemon] being tested against.
* @property evolution The [Evolution] instance performing the test.
* @property originalResult The base result from the Cobblemon implementation.
* @property result The final value returned by [Evolution.test].
*/
data class EvolutionTestedEvent(
override val pokemon: Pokemon,
override val evolution: Evolution,
val originalResult: Boolean,
var result: Boolean
) : EvolutionEvent
@@ -122,16 +122,27 @@ fun drawText(
y: Number,
centered: Boolean = false,
colour: Int,
shadow: Boolean = true
) {
shadow: Boolean = true,
pMouseX: Number? = null,
pMouseY: Number? = null
): Boolean {
val comp = if (font == null) text else text.setStyle(text.style.withFont(font))
val textRenderer = MinecraftClient.getInstance().textRenderer
var x = x
val width = textRenderer.getWidth(comp)
if (centered) {
val width = textRenderer.getWidth(comp)
x = x.toDouble() - width / 2
}
context.drawText(textRenderer, comp, x.toInt(), y.toInt(), colour, shadow)
var isHovered = false
if (pMouseY != null && pMouseX != null) {
if (pMouseX.toInt() >= x.toInt() && pMouseX.toInt() <= x.toInt() + width &&
pMouseY.toInt() >= y.toInt() && pMouseY.toInt() <= y.toInt() + textRenderer.fontHeight
) {
isHovered = true
}
}
return isHovered
}
fun drawText(
@@ -185,6 +196,8 @@ fun drawPortraitPokemon(
val context = RenderContext()
PokemonModelRepository.getTextureNoSubstitute(species.resourceIdentifier, aspects, 0f).let { it -> context.put(RenderContext.TEXTURE, it) }
context.put(RenderContext.SCALE, species.getForm(aspects).baseScale)
context.put(RenderContext.SPECIES, species.resourceIdentifier)
context.put(RenderContext.ASPECTS, aspects)
val renderType = model.getLayer(texture)
@@ -66,7 +66,15 @@ interface PokemonSelectingItem {
return if (entity != null) {
val pokemon = entity.pokemon
if (entity.ownerUuid == player.uuid) {
applyToPokemon(player, stack, pokemon) ?: TypedActionResult.pass(stack)
val typedActionResult = applyToPokemon(player, stack, pokemon)
if (typedActionResult != null)
{
CobblemonCriteria.POKEMON_INTERACT.trigger(player, PokemonInteractContext(pokemon.species.resourceIdentifier, Registries.ITEM.getId(stack.item)))
typedActionResult
}
else {
TypedActionResult.pass(stack)
}
} else {
TypedActionResult.fail(stack)
}
@@ -1,43 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.moves
import com.cobblemon.mod.common.util.lang
import com.mojang.serialization.Codec
import net.minecraft.text.MutableText
import net.minecraft.util.StringIdentifiable
/**
* Represents the damage category of a [MoveTemplate]/[Move].
*
* @see MoveTemplate
* @see Move
*/
enum class DamageCategory : StringIdentifiable {
PHYSICAL,
SPECIAL,
STATUS;
override fun asString(): String = this.name
/**
* Resolves the display name of this damage category.
*
* @return The generated text.
*/
fun displayName(): MutableText = lang("move.category.${this.name.lowercase()}")
companion object {
val CODEC: Codec<DamageCategory> = StringIdentifiable.createCodec(DamageCategory::values)
}
}
@@ -8,6 +8,7 @@
package com.cobblemon.mod.common.api.moves
import com.cobblemon.mod.common.api.moves.categories.DamageCategory
import com.cobblemon.mod.common.api.reactive.SimpleObservable
import com.cobblemon.mod.common.api.types.ElementalType
import com.cobblemon.mod.common.net.IntSize
@@ -8,15 +8,14 @@
package com.cobblemon.mod.common.api.moves
import com.cobblemon.mod.common.api.registry.CobblemonRegistries
import com.cobblemon.mod.common.api.moves.categories.DamageCategories
import com.cobblemon.mod.common.api.moves.categories.DamageCategory
import com.cobblemon.mod.common.api.types.ElementalType
import com.cobblemon.mod.common.api.types.ElementalTypes
import com.cobblemon.mod.common.battles.MoveTarget
import com.cobblemon.mod.common.util.lang
import com.google.gson.annotations.SerializedName
import com.mojang.serialization.Codec
import com.mojang.serialization.codecs.RecordCodecBuilder
import net.minecraft.text.MutableText
import net.minecraft.util.math.random.Random
/**
* This class represents the base of a Move.
@@ -49,27 +48,6 @@ open class MoveTemplate(
val effectChances: Array<Double>
) {
companion object {
fun dummy(name: String) = Dummy(name)
val CODEC: Codec<MoveTemplate> = RecordCodecBuilder.create { builder ->
builder.group(
Codec.STRING.fieldOf("name").forGetter(MoveTemplate::name),
Codec.INT.fieldOf("num").forGetter(MoveTemplate::num),
CobblemonRegistries.ELEMENTAL_TYPE.codec.fieldOf("type").forGetter(MoveTemplate::elementalType),
DamageCategory.CODEC.fieldOf("damageCategory").forGetter(MoveTemplate::damageCategory),
Codec.DOUBLE.fieldOf("power").forGetter(MoveTemplate::power),
MoveTarget.CODEC.fieldOf("target").forGetter(MoveTemplate::target),
Codec.DOUBLE.fieldOf("accuracy").forGetter(MoveTemplate::accuracy),
Codec.INT.fieldOf("pp").forGetter(MoveTemplate::pp),
Codec.INT.fieldOf("priority").forGetter(MoveTemplate::priority),
Codec.DOUBLE.fieldOf("critRatio").forGetter(MoveTemplate::critRatio),
Codec.list(Codec.DOUBLE).fieldOf("effectChances").xmap({ e -> e.toTypedArray() }, { e -> e.toList() }).forGetter(MoveTemplate::effectChances)
).apply(builder, ::MoveTemplate)
}
}
val displayName: MutableText
get() = lang("move.$name")
val description: MutableText
@@ -79,8 +57,8 @@ open class MoveTemplate(
class Dummy(name: String) : MoveTemplate(
name = name,
num = -1,
elementalType = CobblemonRegistries.ELEMENTAL_TYPE.getRandom(Random.create()).orElseThrow().value(),
damageCategory = DamageCategory.STATUS,
elementalType = ElementalTypes.NORMAL,
damageCategory = DamageCategories.STATUS,
power = 0.0,
target = MoveTarget.all,
accuracy = 100.0,
@@ -90,6 +68,10 @@ open class MoveTemplate(
effectChances = emptyArray()
)
companion object {
fun dummy(name: String) = Dummy(name)
}
/**
* Creates the Move with full PP
*/
@@ -110,5 +92,4 @@ open class MoveTemplate(
template = this
)
}
}
@@ -10,8 +10,9 @@ package com.cobblemon.mod.common.api.moves
import com.cobblemon.mod.common.Cobblemon
import com.cobblemon.mod.common.api.data.DataRegistry
import com.cobblemon.mod.common.api.moves.categories.DamageCategories
import com.cobblemon.mod.common.api.reactive.SimpleObservable
import com.cobblemon.mod.common.api.registry.CobblemonRegistries
import com.cobblemon.mod.common.api.types.ElementalTypes
import com.cobblemon.mod.common.battles.MoveTarget
import com.cobblemon.mod.common.battles.runner.ShowdownService
import com.cobblemon.mod.common.net.messages.client.data.MovesRegistrySyncPacket
@@ -43,8 +44,8 @@ object Moves : DataRegistry {
val id = jsMove.get("id").asString
try {
val num = jsMove.get("num").asInt
val elementalType = CobblemonRegistries.ELEMENTAL_TYPE.first { it.showdownId() == jsMove.get("type").asString }
val damageCategory = DamageCategory.valueOf(jsMove.get("category").asString.uppercase())
val elementalType = ElementalTypes.getOrException(jsMove.get("type").asString)
val damageCategory = DamageCategories.getOrException(jsMove.get("category").asString)
val power = jsMove.get("basePower").asDouble
val target = MoveTarget.fromShowdownId(jsMove.get("target").asString)
// If not a double it's always true
@@ -0,0 +1,30 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.moves.adapters
import com.cobblemon.mod.common.api.moves.categories.DamageCategories
import com.cobblemon.mod.common.api.moves.categories.DamageCategory
import com.google.gson.JsonDeserializationContext
import com.google.gson.JsonDeserializer
import com.google.gson.JsonElement
import com.google.gson.JsonPrimitive
import com.google.gson.JsonSerializationContext
import com.google.gson.JsonSerializer
import java.lang.reflect.Type
object DamageCategoryAdapter: JsonSerializer<DamageCategory>, JsonDeserializer<DamageCategory> {
override fun serialize(src: DamageCategory, typeOfSrc: Type, context: JsonSerializationContext): JsonElement {
return JsonPrimitive(src.name)
}
override fun deserialize(json: JsonElement, typeOfT: Type, context: JsonDeserializationContext): DamageCategory {
return DamageCategories.getOrException(json.asString)
}
}
@@ -0,0 +1,64 @@
/*
* 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.moves.categories
import com.cobblemon.mod.common.util.cobblemonResource
import net.minecraft.text.Text
import net.minecraft.util.Identifier
object DamageCategories {
private val allCategories = mutableListOf<DamageCategory>()
val PHYSICAL = register(
name = "physical",
displayName = Text.translatable("cobblemon.move.category.physical"),
textureXMultiplier = 0
)
val SPECIAL = register(
name = "special",
displayName = Text.translatable("cobblemon.move.category.special"),
textureXMultiplier = 1
)
val STATUS = register(
name = "status",
displayName = Text.translatable("cobblemon.move.category.status"),
textureXMultiplier = 2
)
fun register(
name: String,
displayName: Text,
resourceLocation: Identifier = cobblemonResource("textures/gui/categories.png"),
textureXMultiplier: Int
): DamageCategory {
return DamageCategory(
name = name,
displayName = displayName,
textureXMultiplier = textureXMultiplier,
resourceLocation = resourceLocation
).also {
allCategories.add(it)
}
}
fun register(damageCategory: DamageCategory): DamageCategory {
allCategories.add(damageCategory)
return damageCategory
}
fun get(name: String): DamageCategory? {
return allCategories.firstOrNull { cat -> cat.name.equals(name, ignoreCase = true) }
}
fun getOrException(name: String): DamageCategory {
return allCategories.first { cat -> cat.name.equals(name, ignoreCase = true) }
}
fun count() = allCategories.size
}
@@ -0,0 +1,28 @@
/*
* 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.moves.categories
import com.cobblemon.mod.common.util.cobblemonResource
import net.minecraft.text.Text
import net.minecraft.util.Identifier
/**
* Representing a DamageCategory from the Pokemon Game
*
* @param name: The English name used to load / find it (spaces -> _)
* @param displayName: A Component used to display the name, normally a TranslatableText
* @param resourceLocation: The location of the resource used in the GUI
*/
class DamageCategory(
val name: String,
val displayName: Text,
val textureXMultiplier: Int,
val resourceLocation: Identifier = cobblemonResource("textures/gui/categories.png")
) {
}
@@ -27,11 +27,13 @@ object CobblemonPermissions {
val HEAL_POKEMON_SELF = this.create("$HEAL_POKEMON_BASE.self", PermissionLevel.CHEAT_COMMANDS_AND_COMMAND_BLOCKS)
val HEAL_POKEMON_OTHER = this.create("$HEAL_POKEMON_BASE.other", PermissionLevel.CHEAT_COMMANDS_AND_COMMAND_BLOCKS)
private const val LEVEL_UP_BASE = "${COMMAND_PREFIX}levelup"
val LEVEL_UP_SELF = this.create("$LEVEL_UP_BASE.self", PermissionLevel.CHEAT_COMMANDS_AND_COMMAND_BLOCKS)
val LEVEL_UP_OTHER = this.create("$LEVEL_UP_BASE.other", PermissionLevel.CHEAT_COMMANDS_AND_COMMAND_BLOCKS)
val OPEN_STARTER_SCREEN = this.create("${COMMAND_PREFIX}openstarterscreen", PermissionLevel.CHEAT_COMMANDS_AND_COMMAND_BLOCKS)
val BEDROCK_PARTICLE = this.create("${COMMAND_PREFIX}bedrockparticle", PermissionLevel.CHEAT_COMMANDS_AND_COMMAND_BLOCKS)
private const val POKEMON_EDIT_BASE = "${COMMAND_PREFIX}pokemonedit"
val POKEMON_EDIT_SELF = this.create("$POKEMON_EDIT_BASE.self", PermissionLevel.CHEAT_COMMANDS_AND_COMMAND_BLOCKS)
@@ -24,7 +24,7 @@ import com.cobblemon.mod.common.api.pokemon.labels.CobblemonPokemonLabels
import com.cobblemon.mod.common.api.pokemon.stats.Stats
import com.cobblemon.mod.common.api.pokemon.status.Statuses
import com.cobblemon.mod.common.api.reactive.SimpleObservable
import com.cobblemon.mod.common.api.types.CobblemonElementalTypeTags
import com.cobblemon.mod.common.api.types.ElementalTypes
import com.cobblemon.mod.common.pokeball.PokeBall
import com.cobblemon.mod.common.util.cobblemonResource
import com.google.gson.Gson
@@ -136,13 +136,13 @@ object PokeBalls : JsonDataRegistry<PokeBall> {
createDefault("fast_ball", BaseStatModifier(Stats.SPEED, { it >= 100 }, 4F))
createDefault("level_ball", CatchRateModifiers.LEVEL)
// ToDo we will need fishing context here once fishing is implemented for a multiplier
createDefault("lure_ball", CatchRateModifiers.typeBoosting(2F, CobblemonElementalTypeTags.LURE_BALL_BOOSTING))
createDefault("lure_ball", CatchRateModifiers.typeBoosting(2F, ElementalTypes.WATER))
createDefault("heavy_ball", CatchRateModifiers.WEIGHT_BASED)
createDefault("love_ball", CatchRateModifiers.LOVE)
createDefault("friend_ball", effects = listOf(CaptureEffects.friendshipSetter(150)))
createDefault("moon_ball", CatchRateModifiers.MOON_PHASES)
createDefault("sport_ball", MultiplierModifier(1.5F))
createDefault("net_ball", CatchRateModifiers.typeBoosting(3F, CobblemonElementalTypeTags.NET_BALL_BOOSTING))
createDefault("net_ball", CatchRateModifiers.typeBoosting(3F, ElementalTypes.BUG, ElementalTypes.WATER))
createDefault("dive_ball", CatchRateModifiers.SUBMERGED_IN_WATER, waterDragValue = 0.99F)
createDefault("nest_ball", CatchRateModifiers.NEST)
// ToDo implement effect once pokedex is implemented, we have a custom multiplier of 2.5 instead of the official pokeball
@@ -14,8 +14,7 @@ import com.cobblemon.mod.common.api.pokemon.status.Status
import com.cobblemon.mod.common.api.tags.CobblemonBiomeTags
import com.cobblemon.mod.common.api.types.ElementalType
import com.cobblemon.mod.common.battles.BattleRegistry
import com.cobblemon.mod.common.api.pokemon.gender.Gender
import net.minecraft.registry.tag.TagKey
import com.cobblemon.mod.common.pokemon.Gender
/**
* A collection of some default usages of [CatchRateModifier]s.
@@ -140,11 +139,11 @@ object CatchRateModifiers {
* Used by [PokeBalls.NET_BALL].
* Boosts the catch rate if the target is of the given types.
*
* @param multiplier The multiplier to be applied if the target has any of the accepted [typeTag].
* @param typeTag The [ElementalType] [TagKey] that will trigger the multiplier.
* @param multiplier The multiplier to be applied if the target has any of the accepted [types].
* @param types The [ElementalType]s that will trigger the multiplier.
* @return The multiplier modifier.
*/
fun typeBoosting(multiplier: Float, typeTag: TagKey<ElementalType>): CatchRateModifier = MultiplierModifier(multiplier) { _, pokemon -> pokemon.types.any { type -> type.isIn(typeTag) } }
fun typeBoosting(multiplier: Float, vararg types: ElementalType): CatchRateModifier = MultiplierModifier(multiplier) { _, pokemon -> pokemon.types.any { type -> types.contains(type) } }
/**
* Used by [PokeBalls.DREAM_BALL].
@@ -12,14 +12,13 @@ import com.cobblemon.mod.common.Cobblemon
import com.cobblemon.mod.common.api.abilities.Abilities
import com.cobblemon.mod.common.api.pokeball.PokeBalls
import com.cobblemon.mod.common.api.pokemon.aspect.AspectProvider
import com.cobblemon.mod.common.api.pokemon.gender.Gender
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
import com.cobblemon.mod.common.api.registry.CobblemonRegistries
import com.cobblemon.mod.common.api.types.ElementalType
import com.cobblemon.mod.common.api.types.ElementalTypes
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import com.cobblemon.mod.common.pokemon.EVs
import com.cobblemon.mod.common.pokemon.Gender
import com.cobblemon.mod.common.pokemon.IVs
import com.cobblemon.mod.common.pokemon.Pokemon
import com.cobblemon.mod.common.pokemon.RenderablePokemon
@@ -31,12 +30,10 @@ import com.cobblemon.mod.common.util.splitMap
import com.google.gson.JsonArray
import com.google.gson.JsonObject
import kotlin.random.Random
import com.mojang.serialization.Codec
import net.minecraft.nbt.NbtCompound
import net.minecraft.nbt.NbtElement
import net.minecraft.nbt.NbtList
import net.minecraft.nbt.NbtString
import net.minecraft.registry.Registry
import net.minecraft.text.MutableText
import net.minecraft.text.Text
import net.minecraft.util.Identifier
@@ -94,7 +91,7 @@ open class PokemonProperties {
props.ability = parseStringOfRegistry(keyPairs, listOf("ability")) { Abilities.get(it)?.name }
props.status = parseStringOfRegistry(keyPairs, listOf("status")) { (Statuses.getStatus(it) ?: Statuses.getStatus(it.asIdentifierDefaultingNamespace()))?.showdownName }
props.nickname = parseText(keyPairs, listOf("nickname", "nick"))
props.teraType = parseRegistryValue(CobblemonRegistries.ELEMENTAL_TYPE, keyPairs, "tera_type", "tera")
props.teraType = parseStringOfRegistry(keyPairs, listOf("tera_type", "tera")) { ElementalTypes.get(it)?.name }
props.dmaxLevel = parseIntProperty(keyPairs, listOf("dmax_level", "dmax"))?.coerceIn(0, Cobblemon.config.maxDynamaxLevel)
props.gmaxFactor = parseBooleanProperty(keyPairs, listOf("gmax_factor", "gmax"))
props.tradeable = parseBooleanProperty(keyPairs, listOf("tradeable", "tradable"))
@@ -159,7 +156,7 @@ open class PokemonProperties {
}
private fun parseSpeciesIdentifier(keyPairs: MutableList<Pair<String, String?>>): String? {
fun cleanSpeciesName(string: String) = string.lowercase().replace("[^a-z0-9:]".toRegex(), "")
fun cleanSpeciesName(string: String) = string.lowercase().replace("[^a-z0-9_:]".toRegex(), "")
val matched = getMatchedKeyPair(keyPairs, listOf("species"))
if (matched != null) {
val value = matched.second?.let(::cleanSpeciesName) ?: return null
@@ -199,17 +196,6 @@ open class PokemonProperties {
}
}
private fun <T> parseRegistryValue(registry: Registry<T>, keyPairs: MutableList<Pair<String, String?>>, vararg labels: String): T? {
val matchingKeyPair = getMatchedKeyPair(keyPairs, labels.asIterable()) ?: return null
val rawId = matchingKeyPair.second ?: return null
return try {
val id = Identifier(rawId)
registry.get(id)
} catch (_: InvalidIdentifierException) {
null
}
}
private fun parseForm(keyPairs: MutableList<Pair<String, String?>>): String? {
val matchingKeyPair = getMatchedKeyPair(keyPairs, listOf("form")) ?: return null
keyPairs.remove(matchingKeyPair)
@@ -254,9 +240,6 @@ open class PokemonProperties {
}
return null
}
val CODEC: Codec<PokemonProperties> = Codec.STRING.xmap(PokemonProperties::parse, PokemonProperties::asString)
}
var originalString: String = ""
@@ -273,7 +256,7 @@ open class PokemonProperties {
var ability: String? = null
var aspects: Set<String> = emptySet()
var status: String? = null
var teraType: ElementalType? = null
var teraType: String? = null
var dmaxLevel: Int? = null
var gmaxFactor: Boolean? = null
var tradeable: Boolean? = null
@@ -326,7 +309,7 @@ open class PokemonProperties {
pokemon.setEV(stat.key, stat.value)
}
}
teraType?.let { type -> pokemon.teraType = type }
teraType?.let { ElementalTypes.get(it)?.let { type -> pokemon.teraType = type } }
dmaxLevel?.let { pokemon.dmaxLevel = it }
gmaxFactor?.let { pokemon.gmaxFactor = it }
tradeable?.let { pokemon.tradeable = it }
@@ -366,7 +349,7 @@ open class PokemonProperties {
pokemonEntity.pokemon.setEV(stat.key, stat.value)
}
}
teraType?.let { type -> pokemonEntity.pokemon.teraType = type }
teraType?.let { ElementalTypes.get(it)?.let { type -> pokemonEntity.pokemon.teraType = type } }
dmaxLevel?.let { pokemonEntity.pokemon.dmaxLevel = it }
gmaxFactor?.let { pokemonEntity.pokemon.gmaxFactor = it }
tradeable?.let { pokemonEntity.pokemon.tradeable = it }
@@ -404,7 +387,7 @@ open class PokemonProperties {
evs?.forEach{ stat ->
if (stat.value != pokemon.evs[stat.key]) { return false }
}
teraType?.takeIf { it != pokemon.teraType }?.let { return false }
teraType?.takeIf { it != pokemon.teraType.name }?.let { return false }
dmaxLevel?.takeIf { it != pokemon.dmaxLevel }?.let { return false }
gmaxFactor?.takeIf { it != pokemon.gmaxFactor }?.let { return false }
tradeable?.takeIf { it != pokemon.tradeable }?.let { return false }
@@ -425,7 +408,7 @@ open class PokemonProperties {
if (pokemonEntity.pokemon.species != species) {
return false
}
} catch (_: InvalidIdentifierException) {}
} catch (e: InvalidIdentifierException) {}
}
nickname?.takeIf { it != pokemonEntity.pokemon.nickname }?.let { return false }
form?.takeIf { !it.equals(pokemonEntity.pokemon.form.name, true) }?.let { return false }
@@ -440,7 +423,7 @@ open class PokemonProperties {
evs?.forEach{ stat ->
if (stat.value != pokemonEntity.pokemon.evs[stat.key]) { return false }
}
teraType?.takeIf { it != pokemonEntity.pokemon.teraType }?.let { return false }
teraType?.takeIf { it != pokemonEntity.pokemon.teraType.name }?.let { return false }
dmaxLevel?.takeIf { it != pokemonEntity.pokemon.dmaxLevel }?.let { return false }
gmaxFactor?.takeIf { it != pokemonEntity.pokemon.gmaxFactor }?.let { return false }
tradeable?.takeIf { it != pokemonEntity.pokemon.tradeable }?.let { return false }
@@ -461,7 +444,7 @@ open class PokemonProperties {
if (properties.species != species.toString()) {
return false
}
} catch (_: InvalidIdentifierException) {}
} catch (e: InvalidIdentifierException) {}
}
nickname?.takeIf { it != properties.nickname }?.let { return false }
form?.takeIf { !it.equals(properties.form, true) }?.let { return false }
@@ -503,9 +486,8 @@ open class PokemonProperties {
fun roll(pokemon: Pokemon) {
val baseTypes = pokemon.species.types.toList()
if (this.shiny == null) pokemon.shiny = Cobblemon.config.shinyRate.checkRate()
if (this.gmaxFactor == null) pokemon.gmaxFactor = Cobblemon.config.gigantamaxFactorRate.checkRate()
if (this.teraType == null) pokemon.teraType =
if (Cobblemon.config.teraTypeRate.checkRate()) CobblemonRegistries.ELEMENTAL_TYPE.filter { !baseTypes.contains(it) }.random()
if (Cobblemon.config.teraTypeRate.checkRate()) ElementalTypes.all().filter { !baseTypes.contains(it) }.random()
else baseTypes.random()
}
@@ -532,7 +514,7 @@ open class PokemonProperties {
status?.let { nbt.putString(DataKeys.POKEMON_STATUS_NAME, it) }
ivs?.let { nbt.put(DataKeys.POKEMON_IVS, it.saveToNBT(NbtCompound())) }
evs?.let { nbt.put(DataKeys.POKEMON_EVS, it.saveToNBT(NbtCompound())) }
teraType?.let { nbt.putString(DataKeys.POKEMON_TERA_TYPE, it.id().toString()) }
teraType?.let { nbt.putString(DataKeys.POKEMON_TERA_TYPE, it) }
dmaxLevel?.let { nbt.putInt(DataKeys.POKEMON_DMAX_LEVEL, it) }
gmaxFactor?.let { nbt.putBoolean(DataKeys.POKEMON_GMAX_FACTOR, it) }
tradeable?.let { nbt.putBoolean(DataKeys.POKEMON_TRADEABLE, it) }
@@ -557,7 +539,7 @@ open class PokemonProperties {
status = if (tag.contains(DataKeys.POKEMON_STATUS_NAME)) tag.getString(DataKeys.POKEMON_STATUS_NAME) else null
ivs = if (tag.contains(DataKeys.POKEMON_IVS)) ivs?.loadFromNBT(tag.getCompound(DataKeys.POKEMON_IVS)) as IVs? else null
evs = if (tag.contains(DataKeys.POKEMON_EVS)) evs?.loadFromNBT(tag.getCompound(DataKeys.POKEMON_EVS)) as EVs? else null
teraType = if (tag.contains(DataKeys.POKEMON_TERA_TYPE)) CobblemonRegistries.ELEMENTAL_TYPE.get(Identifier(tag.getString(DataKeys.POKEMON_TERA_TYPE))) else null
teraType = if (tag.contains(DataKeys.POKEMON_TERA_TYPE)) tag.getString(DataKeys.POKEMON_TERA_TYPE) else null
dmaxLevel = if (tag.contains(DataKeys.POKEMON_DMAX_LEVEL)) tag.getInt(DataKeys.POKEMON_DMAX_LEVEL) else null
gmaxFactor = if (tag.contains(DataKeys.POKEMON_GMAX_FACTOR)) tag.getBoolean(DataKeys.POKEMON_GMAX_FACTOR) else null
tradeable = if (tag.contains(DataKeys.POKEMON_TRADEABLE)) tag.getBoolean(DataKeys.POKEMON_TRADEABLE) else null
@@ -584,7 +566,7 @@ open class PokemonProperties {
status?.let { json.addProperty(DataKeys.POKEMON_STATUS_NAME, it) }
ivs?.let { json.add(DataKeys.POKEMON_IVS, it.saveToJSON(JsonObject())) }
evs?.let { json.add(DataKeys.POKEMON_EVS, it.saveToJSON(JsonObject())) }
teraType?.let { json.addProperty(DataKeys.POKEMON_TERA_TYPE, it.id().toString()) }
teraType?.let { json.addProperty(DataKeys.POKEMON_TERA_TYPE, it) }
dmaxLevel?.let { json.addProperty(DataKeys.POKEMON_DMAX_LEVEL, it) }
gmaxFactor?.let { json.addProperty(DataKeys.POKEMON_GMAX_FACTOR, it) }
tradeable?.let { json.addProperty(DataKeys.POKEMON_TRADEABLE, it) }
@@ -610,9 +592,7 @@ open class PokemonProperties {
status = json.get(DataKeys.POKEMON_STATUS_NAME)?.asString
ivs?.loadFromJSON(json.getAsJsonObject(DataKeys.POKEMON_IVS))
evs?.loadFromJSON(json.getAsJsonObject(DataKeys.POKEMON_EVS))
teraType = json.get(DataKeys.POKEMON_TERA_TYPE)?.asString?.let { CobblemonRegistries.ELEMENTAL_TYPE.get(
Identifier(it)
) }
teraType = json.get(DataKeys.POKEMON_TERA_TYPE)?.asString
dmaxLevel = json.get(DataKeys.POKEMON_DMAX_LEVEL)?.asInt
gmaxFactor = json.get(DataKeys.POKEMON_GMAX_FACTOR)?.asBoolean
tradeable = json.get(DataKeys.POKEMON_TRADEABLE)?.asBoolean
@@ -642,7 +622,7 @@ open class PokemonProperties {
evs?.forEach{ stat ->
pieces.add("${stat.key}_ev=${stat.value}")
}
teraType?.let { pieces.add("tera_type=${it.id()}") }
teraType?.let { pieces.add("tera_type=$it") }
dmaxLevel?.let { pieces.add("dmax_level=$it") }
gmaxFactor?.let { pieces.add("gmax_factor=$it") }
tradeable?.let { pieces.add("tradeable=$it") }
@@ -23,6 +23,7 @@ import com.cobblemon.mod.common.api.pokemon.effect.ShoulderEffect
import com.cobblemon.mod.common.api.pokemon.effect.adapter.ShoulderEffectAdapter
import com.cobblemon.mod.common.api.pokemon.egg.EggGroup
import com.cobblemon.mod.common.api.pokemon.evolution.Evolution
import com.cobblemon.mod.common.api.pokemon.evolution.PreEvolution
import com.cobblemon.mod.common.api.pokemon.evolution.requirement.EvolutionRequirement
import com.cobblemon.mod.common.api.pokemon.experience.ExperienceGroup
import com.cobblemon.mod.common.api.pokemon.experience.ExperienceGroupAdapter
@@ -37,14 +38,14 @@ import com.cobblemon.mod.common.net.messages.client.data.SpeciesRegistrySyncPack
import com.cobblemon.mod.common.pokemon.FormData
import com.cobblemon.mod.common.pokemon.Species
import com.cobblemon.mod.common.pokemon.SpeciesAdditions
import com.cobblemon.mod.common.pokemon.evolution.adapters.CobblemonEvolutionAdapter
import com.cobblemon.mod.common.pokemon.evolution.adapters.CobblemonPreEvolutionAdapter
import com.cobblemon.mod.common.pokemon.evolution.adapters.CobblemonRequirementAdapter
import com.cobblemon.mod.common.pokemon.evolution.adapters.NbtItemPredicateAdapter
import com.cobblemon.mod.common.pokemon.evolution.predicate.NbtItemPredicate
import com.cobblemon.mod.common.pokemon.helditem.CobblemonHeldItemManager
import com.cobblemon.mod.common.util.adapters.*
import com.cobblemon.mod.common.util.cobblemonResource
import com.cobblemon.mod.common.util.codec.toTypeAdapter
import com.cobblemon.mod.common.util.server
import com.google.common.collect.HashBasedTable
import com.google.gson.Gson
import com.google.gson.GsonBuilder
@@ -55,12 +56,12 @@ import net.minecraft.entity.effect.StatusEffect
import net.minecraft.item.Item
import net.minecraft.nbt.NbtCompound
import net.minecraft.registry.Registries
import net.minecraft.registry.RegistryKeys
import net.minecraft.resource.ResourceType
import net.minecraft.server.network.ServerPlayerEntity
import net.minecraft.util.Identifier
import net.minecraft.util.math.Box
import net.minecraft.world.biome.Biome
import net.minecraft.world.gen.structure.Structure
object PokemonSpecies : JsonDataRegistry<Species> {
@@ -76,8 +77,11 @@ object PokemonSpecies : JsonDataRegistry<Species> {
.registerTypeAdapter(ExperienceGroup::class.java, ExperienceGroupAdapter)
.registerTypeAdapter(EntityDimensions::class.java, EntityDimensionsAdapter)
.registerTypeAdapter(Learnset::class.java, LearnsetAdapter)
.registerTypeAdapter(Evolution::class.java, CobblemonEvolutionAdapter)
.registerTypeAdapter(Box::class.java, BoxAdapter)
.registerTypeAdapter(AbilityPool::class.java, AbilityPoolAdapter)
.registerTypeAdapter(EvolutionRequirement::class.java, CobblemonRequirementAdapter)
.registerTypeAdapter(PreEvolution::class.java, CobblemonPreEvolutionAdapter)
.registerTypeAdapter(TypeToken.getParameterized(Set::class.java, Evolution::class.java).type, LazySetAdapter(Evolution::class))
.registerTypeAdapter(IntRange::class.java, IntRangeAdapter)
.registerTypeAdapter(PokemonProperties::class.java, pokemonPropertiesShortAdapter)
@@ -87,9 +91,10 @@ object PokemonSpecies : JsonDataRegistry<Species> {
.registerTypeAdapter(SleepDepth::class.java, SleepDepth.adapter)
.registerTypeAdapter(DropEntry::class.java, DropEntryAdapter)
.registerTypeAdapter(NbtCompound::class.java, NbtCompoundAdapter)
.registerTypeAdapter(TypeToken.getParameterized(RegistryLikeCondition::class.java, Biome::class.java).type, RegistryLikeCondition.createCodec { server()!!.registryManager.get(RegistryKeys.BIOME) }.toTypeAdapter())
.registerTypeAdapter(TypeToken.getParameterized(RegistryLikeCondition::class.java, Block::class.java).type, RegistryLikeCondition.createCodec { Registries.BLOCK }.toTypeAdapter())
.registerTypeAdapter(TypeToken.getParameterized(RegistryLikeCondition::class.java, Item::class.java).type, RegistryLikeCondition.createCodec { Registries.ITEM }.toTypeAdapter())
.registerTypeAdapter(TypeToken.getParameterized(RegistryLikeCondition::class.java, Biome::class.java).type, BiomeLikeConditionAdapter)
.registerTypeAdapter(TypeToken.getParameterized(RegistryLikeCondition::class.java, Block::class.java).type, BlockLikeConditionAdapter)
.registerTypeAdapter(TypeToken.getParameterized(RegistryLikeCondition::class.java, Item::class.java).type, ItemLikeConditionAdapter)
.registerTypeAdapter(TypeToken.getParameterized(RegistryLikeCondition::class.java, Structure::class.java).type, StructureLikeConditionAdapter)
.registerTypeAdapter(EggGroup::class.java, EggGroupAdapter)
.registerTypeAdapter(StatusEffect::class.java, RegistryElementAdapter<StatusEffect> { Registries.STATUS_EFFECT })
.registerTypeAdapter(NbtItemPredicate::class.java, NbtItemPredicateAdapter)
@@ -208,7 +213,7 @@ object PokemonSpecies : JsonDataRegistry<Species> {
"H" to "No Ability",
"S" to "No Ability"
)
val types = (form?.types ?: species.types).map { it.showdownId() }
val types = (form?.types ?: species.types).map { it.name.replaceFirstChar(Char::uppercase) }
val preevo: String? = (form?.preEvolution ?: species.preEvolution)?.let { if (it.form == it.species.standardForm) createShowdownName(it.species) else "${createShowdownName(it.species)}-${it.form.name}" }
// For the context of battles the content here doesn't matter whatsoever and due to how PokemonProperties work we can't guarantee an actual specific species is defined.
val evos = if ((form?.evolutions ?: species.evolutions).isEmpty()) emptyList() else arrayListOf("")
@@ -233,8 +238,8 @@ object PokemonSpecies : JsonDataRegistry<Species> {
"spd" to (form?.baseStats?.get(Stats.SPECIAL_DEFENCE) ?: species.baseStats[Stats.SPECIAL_DEFENCE] ?: 1),
"spe" to (form?.baseStats?.get(Stats.SPEED) ?: species.baseStats[Stats.SPEED] ?: 1)
)
val heightm = form?.height ?: species.height
val weightkg = form?.weight ?: species.weight
val heightm = (form?.height ?: species.height) / 10
val weightkg = (form?.weight ?: species.weight) / 10
// This is ugly, but we already have it hardcoded in the mod anyway
val maxHP = if (species.showdownId() == "shedinja") 1 else null
val canGigantamax: String? = if (form?.gigantamaxMove != null) form.gigantamaxMove.name else null
@@ -8,9 +8,6 @@
package com.cobblemon.mod.common.api.pokemon.egg
import com.mojang.serialization.Codec
import net.minecraft.util.StringIdentifiable
/**
* These represent categories which determine which Pokémon are able to interbreed.
*
@@ -18,7 +15,7 @@ import net.minecraft.util.StringIdentifiable
*
* @property showdownID used for data synchronization with Showdown data format.
*/
enum class EggGroup(internal val showdownID: String) : StringIdentifiable {
enum class EggGroup(internal val showdownID: String) {
MONSTER("Monster"),
WATER_1("Water 1"),
@@ -34,15 +31,6 @@ enum class EggGroup(internal val showdownID: String) : StringIdentifiable {
WATER_2("Water 2"),
DITTO("Ditto"),
DRAGON("Dragon"),
UNDISCOVERED("Undiscovered");
override fun asString(): String = this.name
companion object {
@JvmField
val CODEC: Codec<EggGroup> = StringIdentifiable.createCodec(EggGroup::values)
}
UNDISCOVERED("Undiscovered")
}
@@ -11,10 +11,10 @@ package com.cobblemon.mod.common.api.pokemon.evolution
import com.cobblemon.mod.common.CobblemonSounds
import com.cobblemon.mod.common.api.events.CobblemonEvents
import com.cobblemon.mod.common.api.events.pokemon.evolution.EvolutionCompleteEvent
import com.cobblemon.mod.common.api.events.pokemon.evolution.EvolutionTestedEvent
import com.cobblemon.mod.common.api.moves.BenchedMove
import com.cobblemon.mod.common.api.moves.MoveTemplate
import com.cobblemon.mod.common.api.pokemon.PokemonProperties
import com.cobblemon.mod.common.api.pokemon.evolution.adapters.Variant
import com.cobblemon.mod.common.api.pokemon.evolution.requirement.EvolutionRequirement
import com.cobblemon.mod.common.pokemon.Pokemon
import com.cobblemon.mod.common.pokemon.activestate.ShoulderedState
@@ -22,7 +22,6 @@ import com.cobblemon.mod.common.pokemon.evolution.variants.ItemInteractionEvolut
import com.cobblemon.mod.common.pokemon.evolution.variants.LevelUpEvolution
import com.cobblemon.mod.common.pokemon.evolution.variants.TradeEvolution
import com.cobblemon.mod.common.util.lang
import com.mojang.serialization.Codec
import net.minecraft.item.ItemStack
import net.minecraft.sound.SoundCategory
@@ -62,18 +61,18 @@ interface Evolution : EvolutionLike {
*/
val learnableMoves: MutableSet<MoveTemplate>
/**
* The [Variant] of this [Evolution].
*/
val variant: Variant<Evolution>
/**
* Checks if the given [Pokemon] passes all the conditions and is ready to evolve.
*
* @param pokemon The [Pokemon] being queried.
* @return If the [Evolution] can start.
*/
fun test(pokemon: Pokemon) = this.requirements.all { requirement -> requirement.check(pokemon) }
fun test(pokemon: Pokemon): Boolean {
val result = this.requirements.all { requirement -> requirement.check(pokemon) }
val event = EvolutionTestedEvent(pokemon, this, result, result)
CobblemonEvents.EVOLUTION_TESTED.post(event)
return event.result
}
/**
* Starts this evolution or queues it if [optional] is true.
@@ -126,12 +125,4 @@ interface Evolution : EvolutionLike {
fun applyTo(pokemon: Pokemon) {
result.apply(pokemon)
}
/**
* TODO
*
* @return
*/
fun codec(): Codec<out Evolution> = this.variant.codec
}
@@ -8,10 +8,9 @@
package com.cobblemon.mod.common.api.pokemon.evolution
import com.cobblemon.mod.common.api.pokemon.species.Species
import com.cobblemon.mod.common.api.registry.CobblemonRegistries
import com.mojang.serialization.Codec
import net.minecraft.util.Identifier
import com.cobblemon.mod.common.pokemon.FormData
import com.cobblemon.mod.common.pokemon.Species
import com.cobblemon.mod.common.pokemon.evolution.StandardPreEvolution
/**
* Represents the previous stage in the evolutionary line of a given Pokémon.
@@ -20,14 +19,15 @@ import net.minecraft.util.Identifier
* @author Licious
* @since March 22nd, 2022
*/
class PreEvolution internal constructor(private val speciesKey: Identifier){
interface PreEvolution {
val species: Species by lazy { CobblemonRegistries.SPECIES.get(this.speciesKey)!! }
val species: Species
val form: FormData
companion object {
@JvmField
val CODEC: Codec<PreEvolution> = Identifier.CODEC.xmap(::PreEvolution, PreEvolution::speciesKey)
fun of(species: Species, form: FormData = species.standardForm): PreEvolution = StandardPreEvolution(species, form)
}
@@ -0,0 +1,35 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.pokemon.evolution.adapters
import com.cobblemon.mod.common.api.pokemon.evolution.Evolution
import com.cobblemon.mod.common.pokemon.evolution.adapters.CobblemonEvolutionAdapter
import com.google.gson.JsonDeserializer
import com.google.gson.JsonSerializer
import kotlin.reflect.KClass
/**
* Saves and loads [Evolution]s with JSON.
* For the default implementation see [CobblemonEvolutionAdapter].
*
* @author Licious
* @since March 20th, 2022
*/
interface EvolutionAdapter : JsonDeserializer<Evolution>, JsonSerializer<Evolution> {
/**
* Registers the given type of [Evolution] to it's associated ID for deserialization.
*
* @param T The type of [Evolution].
* @param id The id of the evolution event.
* @param type The [KClass] of the type.
*/
fun <T : Evolution> registerType(id: String, type: KClass<T>)
}
@@ -1,112 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.pokemon.evolution.adapters
import com.cobblemon.mod.common.api.pokemon.evolution.Evolution
import com.cobblemon.mod.common.api.pokemon.evolution.requirement.EvolutionRequirement
import com.cobblemon.mod.common.pokemon.evolution.requirements.*
import com.cobblemon.mod.common.pokemon.evolution.variants.BlockClickEvolution
import com.cobblemon.mod.common.pokemon.evolution.variants.ItemInteractionEvolution
import com.cobblemon.mod.common.pokemon.evolution.variants.LevelUpEvolution
import com.cobblemon.mod.common.pokemon.evolution.variants.TradeEvolution
import com.cobblemon.mod.common.util.cobblemonResource
import com.mojang.serialization.Codec
import com.mojang.serialization.Lifecycle
import net.minecraft.registry.RegistryKey
import net.minecraft.registry.SimpleRegistry
/**
*
*/
object EvolutionRegistry {
private val EVOLUTION_REGISTRY = SimpleRegistry<Variant<Evolution>>(RegistryKey.ofRegistry(cobblemonResource("evolution_variants")), Lifecycle.stable())
private val REQUIREMENT_REGISTRY = SimpleRegistry<Variant<EvolutionRequirement>>(RegistryKey.ofRegistry(cobblemonResource("evolution_requirements")), Lifecycle.stable())
/**
* A [Codec] for [Evolution].
* If you wish to register more variants see [registerEvolutionVariant].
*/
@JvmField
val EVOLUTION_CODEC: Codec<Evolution> = EVOLUTION_REGISTRY.codec.dispatch("variant", Evolution::variant) { variant -> variant.codec }
/**
* A [Codec] for [EvolutionRequirement].
* If you wish to register more variants see [registerRequirementVariant].
*/
@JvmField
val REQUIREMENT_CODEC: Codec<EvolutionRequirement> = REQUIREMENT_REGISTRY.codec.dispatch("variant", EvolutionRequirement::variant) { variant -> variant.codec }
/**
* Registers an [Evolution] type.
*
* @param variant The [Variant] of an [Evolution] being registered.
*
* @throws IllegalStateException If the backing registry already contains an entry with the [Variant.identifier].
* @throws AssertionError If the registry is missing an intrusive holder.
*/
@JvmStatic
fun registerEvolutionVariant(variant: Variant<Evolution>) {
EVOLUTION_REGISTRY.add(RegistryKey.of(EVOLUTION_REGISTRY.key, variant.identifier), variant, Lifecycle.stable())
}
/**
* Registers an [EvolutionRequirement] type.
*
* @param variant The [Variant] of an [EvolutionRequirement] being registered.
*
* @throws IllegalStateException If the backing registry already contains an entry with the [Variant.identifier].
* @throws AssertionError If the registry is missing an intrusive holder.
*/
@JvmStatic
fun registerRequirementVariant(variant: Variant<EvolutionRequirement>) {
REQUIREMENT_REGISTRY.add(RegistryKey.of(REQUIREMENT_REGISTRY.key, variant.identifier), variant, Lifecycle.stable())
}
internal fun init() {
this.registerDefaultEvolutions()
this.registerDefaultRequirements()
}
private fun registerDefaultEvolutions() {
this.registerEvolutionVariant(BlockClickEvolution.VARIANT)
this.registerEvolutionVariant(ItemInteractionEvolution.VARIANT)
this.registerEvolutionVariant(LevelUpEvolution.MAIN_VARIANT)
this.registerEvolutionVariant(LevelUpEvolution.ALTERNATIVE_VARIANT)
this.registerEvolutionVariant(TradeEvolution.VARIANT)
}
private fun registerDefaultRequirements() {
this.registerRequirementVariant(AllOfRequirement.VARIANT)
this.registerRequirementVariant(AnyOfRequirement.VARIANT)
this.registerRequirementVariant(AreaRequirement.VARIANT)
this.registerRequirementVariant(AttackDefenceRatioRequirement.VARIANT)
this.registerRequirementVariant(BattleCriticalHitsRequirement.VARIANT)
this.registerRequirementVariant(BiomeRequirement.VARIANT)
this.registerRequirementVariant(BlocksTraveledRequirement.VARIANT)
this.registerRequirementVariant(DamageTakenRequirement.VARIANT)
this.registerRequirementVariant(DefeatRequirement.VARIANT)
this.registerRequirementVariant(FriendshipRequirement.VARIANT)
this.registerRequirementVariant(HeldItemRequirement.VARIANT)
this.registerRequirementVariant(LevelRequirement.VARIANT)
this.registerRequirementVariant(MoonPhaseRequirement.VARIANT)
this.registerRequirementVariant(MoveSetRequirement.VARIANT)
this.registerRequirementVariant(MoveTypeRequirement.VARIANT)
this.registerRequirementVariant(NoneOfRequirement.VARIANT)
this.registerRequirementVariant(NotRequirement.VARIANT)
this.registerRequirementVariant(PartyMemberRequirement.VARIANT)
this.registerRequirementVariant(PokemonPropertiesRequirement.VARIANT)
this.registerRequirementVariant(RecoilRequirement.VARIANT)
this.registerRequirementVariant(TimeRangeRequirement.VARIANT)
this.registerRequirementVariant(UseMoveRequirement.VARIANT)
this.registerRequirementVariant(WeatherRequirement.VARIANT)
this.registerRequirementVariant(WorldRequirement.VARIANT)
}
}
@@ -0,0 +1,35 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.pokemon.evolution.adapters
import com.cobblemon.mod.common.api.pokemon.evolution.requirement.EvolutionRequirement
import com.cobblemon.mod.common.pokemon.evolution.adapters.CobblemonRequirementAdapter
import com.google.gson.JsonDeserializer
import com.google.gson.JsonSerializer
import kotlin.reflect.KClass
/**
* Saves and loads [EvolutionRequirement]s with JSON.
* For the default implementation see [CobblemonRequirementAdapter].
*
* @author Licious
* @since March 21st, 2022
*/
interface RequirementAdapter : JsonDeserializer<EvolutionRequirement>, JsonSerializer<EvolutionRequirement> {
/**
* Registers the given type of [EvolutionRequirement] to it's associated ID for deserialization.
*
* @param T The type of [EvolutionRequirement].
* @param id The id of the evolution event.
* @param type The [KClass] of the type.
*/
fun <T : EvolutionRequirement> registerType(id: String, type: KClass<T>)
}
@@ -1,17 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.pokemon.evolution.adapters
import com.mojang.serialization.Codec
import net.minecraft.util.Identifier
data class Variant<T>(
val identifier: Identifier,
val codec: Codec<out T>
)
@@ -8,14 +8,16 @@
package com.cobblemon.mod.common.api.pokemon.evolution.progress
import com.cobblemon.mod.common.pokemon.evolution.progress.RecoilEvolutionProgress
import com.cobblemon.mod.common.pokemon.evolution.progress.UseMoveEvolutionProgress
import com.cobblemon.mod.common.pokemon.evolution.progress.*
object EvolutionProgressFactory {
private val variants = hashMapOf<String, () -> EvolutionProgress<*>>()
init {
registerVariant(DamageTakenEvolutionProgress.ID.toString()) { DamageTakenEvolutionProgress() }
registerVariant(DefeatEvolutionProgress.ID.toString()) { DefeatEvolutionProgress() }
registerVariant(LastBattleCriticalHitsEvolutionProgress.ID.toString()) { LastBattleCriticalHitsEvolutionProgress() }
registerVariant(RecoilEvolutionProgress.ID.toString()) { RecoilEvolutionProgress() }
registerVariant(UseMoveEvolutionProgress.ID.toString()) { UseMoveEvolutionProgress() }
}
@@ -10,10 +10,7 @@ package com.cobblemon.mod.common.api.pokemon.evolution.requirement
import com.cobblemon.mod.common.api.pokemon.evolution.ContextEvolution
import com.cobblemon.mod.common.api.pokemon.evolution.Evolution
import com.cobblemon.mod.common.api.pokemon.evolution.adapters.EvolutionRegistry
import com.cobblemon.mod.common.api.pokemon.evolution.adapters.Variant
import com.cobblemon.mod.common.pokemon.Pokemon
import com.mojang.serialization.Codec
/**
* Represents a requirement for an evolution.
@@ -25,12 +22,7 @@ import com.mojang.serialization.Codec
* @author Licious
* @since March 19th, 2022
*/
interface EvolutionRequirement {
/**
*
*/
val variant: Variant<EvolutionRequirement>
fun interface EvolutionRequirement {
/**
* Checks if the given [Pokemon] satisfies the requirement.
@@ -40,17 +32,4 @@ interface EvolutionRequirement {
*/
fun check(pokemon: Pokemon): Boolean
/**
* TODO
*
* @return
*/
fun codec(): Codec<out EvolutionRequirement> = this.variant.codec
companion object {
val CODEC: Codec<EvolutionRequirement> = EvolutionRegistry.REQUIREMENT_CODEC
}
}
@@ -18,7 +18,6 @@ import com.google.gson.JsonElement
import com.google.gson.JsonPrimitive
import com.google.gson.JsonSerializationContext
import com.google.gson.JsonSerializer
import com.mojang.serialization.Codec
import java.lang.reflect.Type
import kotlin.math.max
import net.minecraft.text.MutableText
@@ -75,10 +74,6 @@ interface ExperienceGroup : LevelCurve {
override fun getExperience(level: Int) = 0
override fun getLevel(experience: Int) = 1
}
@JvmField
val CODEC: Codec<ExperienceGroup> = Codec.STRING.xmap(ExperienceGroups::findByName, ExperienceGroup::name)
}
}
@@ -1,54 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.pokemon.gender
import com.cobblemon.mod.common.api.data.ShowdownIdentifiable
import com.cobblemon.mod.common.api.pokemon.species.Species
import com.cobblemon.mod.common.pokemon.Pokemon
import java.util.*
/**
* Represents the [Gender] of a [Pokemon].
* This is taken into account by [Species] when generating the [Pokemon].
*
* @property showdownId The ID of the [Gender] in Showdown.
*
* @see Species.genderSelector
* @see Pokemon.gender
* @see GenderSelector
*/
enum class Gender(private val showdownId: String) : ShowdownIdentifiable {
MALE("M"),
FEMALE("F"),
GENDERLESS("N");
override fun showdownId(): String = this.showdownId
companion object {
/**
* The [Gender]s when a ratio is attached to a [GenderSelector].
*
* @see GenderSelector.maleRatio
*/
@JvmField
val RATIO_BASED_GENDERS: Set<Gender> = EnumSet.of(MALE, FEMALE)
/**
* The [Gender]s when no ratio is attached to a [GenderSelector].
*
* @see GenderSelector.maleRatio
*/
@JvmField
val NO_RATIO_GENDERS: Set<Gender> = EnumSet.of(GENDERLESS)
}
}
@@ -1,72 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.pokemon.gender
import com.cobblemon.mod.common.api.pokemon.species.Species
import com.cobblemon.mod.common.pokemon.Pokemon
import com.mojang.serialization.Codec
import kotlin.random.Random
/**
* Class responsible for querying possible [Gender]s of [Species] and assigning them randomly to generated [Pokemon].
*
* @property maleRatio The raw ratio for the [Gender.MALE] despite the naming this is able to cover all possible genders.
*
* @see Species.genderSelector
*
* @throws IllegalArgumentException If male ratio is greater than 1.
*/
@Suppress("MemberVisibilityCanBePrivate")
class GenderSelector internal constructor(private val maleRatio: Float) {
init {
if (this.maleRatio < 1F) {
throw IllegalArgumentException("Male ratio cannot be greater than 1.0")
}
}
/**
* Collects all the possible [Gender]s from [generate].
*
* @return The possible [Gender]s.
*/
fun possibleGenders(): Set<Gender> = if (this.maleRatio < 0F) Gender.NO_RATIO_GENDERS else Gender.RATIO_BASED_GENDERS
/**
* Randomly picks a [Gender] using the [maleRatio].
*
* @return The generated [Gender].
*/
fun generate(): Gender = when {
this.maleRatio < 0F -> Gender.GENDERLESS
this.maleRatio == 1F || Random.nextFloat() < this.maleRatio -> Gender.MALE
else -> Gender.FEMALE
}
/**
* Checks if the given [gender] is a possible selection of [generate].
*
* @param gender The [Gender] being checked.
* @return If the [gender] is possible with the context in this [GenderSelector].
*/
fun isValid(gender: Gender): Boolean = this.possibleGenders().contains(gender)
companion object {
/**
* A [Codec] for [GenderSelector].
* This will (de)serialize from a primitive float.
* It will error if the value is not between [Float.MIN_VALUE] and 1F.
*/
@JvmField
val CODEC: Codec<GenderSelector> = Codec.floatRange(Float.MIN_VALUE, 1F).xmap(::GenderSelector, GenderSelector::maleRatio)
}
}
@@ -79,6 +79,16 @@ interface HeldItemManager {
*/
fun take(pokemon: BattlePokemon, showdownId: String)
/**
* Tests if the given [BattlePokemon] should have their item consumed.
* This method is expected to be used in each implementation when needed.
*
* @param pokemon The [BattlePokemon] being tested.
* @param battle The [PokemonBattle] the [pokemon] is participating in.
* @param showdownId The literal ID of the held item on Showdown.
*/
fun shouldConsumeItem(pokemon: BattlePokemon, battle: PokemonBattle, showdownId: String): Boolean = false
companion object {
/**
@@ -1,55 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.pokemon.species
import com.cobblemon.mod.common.api.data.ShowdownIdentifiable
import com.cobblemon.mod.common.api.registry.CobblemonRegistries
import com.mojang.serialization.Codec
import com.mojang.serialization.codecs.RecordCodecBuilder
import net.minecraft.util.Identifier
/**
* Additional data only present in species that are a variation of an existing species.
* This is commonly referred to as a Pokémon form.
* In the context of Cobblemon aspects are used when a form is purely cosmetic.
* This is only present if a [Species] has actual stat related differences from the "base".
*
* @see <a href="https://bulbapedia.bulbagarden.net/wiki/Variant_Pok%C3%A9mon">Bulbapedias entry on variant Pokémon</a>
*/
class FormData internal constructor(
private var baseSpeciesIdentifier: Identifier,
private var battleOnly: Boolean
) {
/**
* Resolves the base species of this form.
*
* @return The [Species] that is the base of this form.
*/
fun baseSpecies(): Species = CobblemonRegistries.SPECIES.get(this.baseSpeciesIdentifier)!!
/**
* Checks if this [FormData] can only exist in battles.
*
* @return True if this [FormData] can only exist in battles.
*/
fun isBattleOnly(): Boolean = this.battleOnly
companion object {
val CODEC: Codec<FormData> = RecordCodecBuilder.create { builder ->
builder.group(
Identifier.CODEC.fieldOf("baseSpecies").forGetter(FormData::baseSpeciesIdentifier),
Codec.BOOL.fieldOf("battleOnly").forGetter(FormData::battleOnly)
).apply(builder, ::FormData)
}
}
}
@@ -1,198 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.pokemon.species
import com.cobblemon.mod.common.Cobblemon
import com.cobblemon.mod.common.api.abilities.AbilityPool
import com.cobblemon.mod.common.api.data.ShowdownIdentifiable
import com.cobblemon.mod.common.api.pokemon.egg.EggGroup
import com.cobblemon.mod.common.api.pokemon.evolution.Evolution
import com.cobblemon.mod.common.api.pokemon.evolution.PreEvolution
import com.cobblemon.mod.common.api.pokemon.experience.ExperienceGroup
import com.cobblemon.mod.common.api.pokemon.gender.Gender
import com.cobblemon.mod.common.api.pokemon.gender.GenderSelector
import com.cobblemon.mod.common.api.pokemon.moves.Learnset
import com.cobblemon.mod.common.api.pokemon.species.internal.*
import com.cobblemon.mod.common.api.pokemon.stats.StatMap
import com.cobblemon.mod.common.api.registry.CobblemonRegistryElement
import com.cobblemon.mod.common.api.registry.CobblemonRegistryKeys
import com.cobblemon.mod.common.api.types.ElementalType
import com.cobblemon.mod.common.pokemon.Pokemon
import com.cobblemon.mod.common.pokemon.ai.PokemonBehaviour
import com.cobblemon.mod.common.util.codec.ExtraCodecs
import com.mojang.serialization.Codec
import com.mojang.serialization.codecs.RecordCodecBuilder
import net.minecraft.entity.EntityDimensions
import net.minecraft.registry.Registry
import net.minecraft.registry.entry.RegistryEntry
import net.minecraft.text.MutableText
import net.minecraft.text.Text
import net.minecraft.util.Identifier
import java.util.*
@Suppress("unused")
class Species internal constructor(
nationalPokedexNumber: Int,
types: Pair<ElementalType, Optional<ElementalType>>,
abilities: AbilityPool,
baseStats: StatMap,
catchRate: Int,
genderSelector: GenderSelector,
private val experienceData: ExperienceData,
private val eggData: EggData,
learnset: Learnset,
private val behaviourData: BehaviourData,
private val evolutionData: EvolutionData,
baseFriendship: Int,
evYield: StatMap,
private val cosmeticData: CosmeticData,
formData: Optional<FormData>
): CobblemonRegistryElement<Species>, ShowdownIdentifiable {
companion object {
private val TYPES_CODEC = ExtraCodecs.ENTITY_DIMENSIONS
val codec = RecordCodecBuilder.create { builder ->
builder.group(
Codec.INT.fieldOf("nationalPokedexNumber").forGetter(Species::nationalPokedexNumber),
ExtraCodecs.DUAL_TYPE_CODEC.fieldOf("types").forGetter(Species::types),
// ToDo: abilities
StatMap.BASE_STATS_CODEC.fieldOf("baseStats").forGetter(Species::baseStats),
Codec.INT.fieldOf("catchRate").forGetter(Species::catchRate),
GenderSelector.CODEC.fieldOf("genderSelector").forGetter(Species::genderSelector),
ExperienceData.MAP_CODEC.forGetter(Species::experienceData),
EggData.MAP_CODEC.fieldOf("eggData").forGetter(Species::eggData),
// ToDo: learnset
BehaviourData.MAP_CODEC.forGetter(Species::behaviourData),
EvolutionData.MAP_CODEC.forGetter(Species::evolutionData),
Codec.INT.fieldOf("baseFriendship").forGetter(Species::baseFriendship),
StatMap.BASE_STATS_CODEC.fieldOf("evYield").forGetter(Species::evYield),
CosmeticData.MAP_CODEC.forGetter(Species::cosmeticData),
FormData.CODEC.optionalFieldOf("formData").forGetter(Species::formData)
).apply(builder, ::Species)
}
}
val displayName: MutableText by lazy { Text.translatable("${this.id().namespace}.species.${this.id().path.replace("/", ".")}.name") }
var nationalPokedexNumber: Int = nationalPokedexNumber
private set
var types: Pair<ElementalType, Optional<ElementalType>> = types
private set
val primaryType: ElementalType get() = this.types.first
val secondaryType: Optional<ElementalType> get() = this.types.second
var abilities: AbilityPool = abilities
private set
var baseStats: StatMap = baseStats
private set
var catchRate: Int = catchRate
private set
/**
* Responsible for picking a [Gender] for this [Species] on [create].
*/
var genderSelector: GenderSelector = genderSelector
private set
val shoulderMountable: Boolean get() = this.behaviourData.shoulderMountable
val baseExperienceYield: Int get() = this.experienceData.baseExperienceYield
val experienceGroup: ExperienceGroup get() = this.experienceData.experienceGroup
val eggCycles: Int get() = this.eggData.eggCycles
val eggGroups: Set<EggGroup> get() = this.eggData.eggGroups
var learnset: Learnset = learnset
private set
val behaviour: PokemonBehaviour get() = this.behaviourData.pokemonBehaviour
val evolutions: Set<Evolution> get() = this.evolutionData.evolutions
val preEvolution: Optional<PreEvolution> get() = this.evolutionData.preEvolution
val baseScale: Float get() = this.cosmeticData.baseScale
val hitbox: EntityDimensions get() = this.cosmeticData.hitbox
var baseFriendship: Int = baseFriendship
private set
var evYield: StatMap = evYield
private set
val weight: Float get() = this.cosmeticData.weight
val height: Float get() = this.cosmeticData.height
val aspects: Set<String> get() = this.cosmeticData.aspects
val features: Set<String> get() = this.behaviourData.features
val standingEyeHeight: Float get() = this.cosmeticData.standingEyeHeight
val swimmingEyeHeight: Float get() = this.cosmeticData.swimmingEyeHeight
val flyingEyeHeight: Float get() = this.cosmeticData.flyingEyeHeight
var formData: Optional<FormData> = formData
private set
/**
* TODO
*
* @param level
* @return
*/
fun create(level: Int): Pokemon {
TODO("Not yet implemented")
}
/**
* Picks a randomly generated [Gender] using the [genderSelector].
*
* @return The picked [Gender].
*/
fun pickGender(): Gender = this.genderSelector.generate()
/**
* Checks if this [Species] can be of the given [gender].
* This is checked against the [genderSelector].
*
* @param gender The [Gender] being checked.
* @return If the given [gender] is possible for this [Species].
*/
fun canBeOfGender(gender: Gender): Boolean = this.genderSelector.isValid(gender)
override fun showdownId(): String {
val id = this.id()
val showdownId = ShowdownIdentifiable.REGEX.replace(id.path, "")
if (id.namespace == Cobblemon.MODID) {
return showdownId
}
return id.namespace + showdownId
}
override fun id(): Identifier = this.registry().getId(this)!!
override fun registryEntry(): RegistryEntry<Species> = this.registry().getEntry(this)
override fun registry(): Registry<Species> = Cobblemon.implementation.getRegistry(CobblemonRegistryKeys.SPECIES)
}
@@ -1,43 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.pokemon.species.internal
import com.cobblemon.mod.common.api.pokemon.species.Species
import com.cobblemon.mod.common.pokemon.ai.PokemonBehaviour
import com.cobblemon.mod.common.util.codec.setCodec
import com.mojang.serialization.Codec
import com.mojang.serialization.MapCodec
import com.mojang.serialization.codecs.RecordCodecBuilder
/**
* Intermediate for [Species] data.
*/
internal data class BehaviourData(
var pokemonBehaviour: PokemonBehaviour,
var shoulderMountable: Boolean,
var features: Set<String>,
var dynamaxBlocked: Boolean,
) {
companion object {
val MAP_CODEC: MapCodec<BehaviourData> = RecordCodecBuilder.mapCodec { builder ->
builder.group(
PokemonBehaviour.CODEC.fieldOf("pokemonBehaviour").forGetter(BehaviourData::pokemonBehaviour),
Codec.BOOL.fieldOf("shoulderMountable").forGetter(BehaviourData::shoulderMountable),
setCodec(Codec.STRING).fieldOf("features").forGetter(BehaviourData::features),
Codec.BOOL.optionalFieldOf("dynamaxBlocked", false).forGetter(BehaviourData::dynamaxBlocked)
).apply(builder, ::BehaviourData)
}
val CODEC: Codec<BehaviourData> = MAP_CODEC.codec()
}
}
@@ -1,54 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.pokemon.species.internal
import com.cobblemon.mod.common.api.pokemon.species.Species
import com.cobblemon.mod.common.util.codec.ExtraCodecs
import com.cobblemon.mod.common.util.codec.setCodec
import com.mojang.serialization.Codec
import com.mojang.serialization.MapCodec
import com.mojang.serialization.codecs.RecordCodecBuilder
import net.minecraft.entity.EntityDimensions
/**
* Intermediate for [Species] data.
*/
internal data class CosmeticData(
var baseScale: Float,
var hitbox: EntityDimensions,
var weight: Float,
var height: Float,
var aspects: Set<String>,
var standingEyeHeight: Float,
var swimmingEyeHeight: Float,
var flyingEyeHeight: Float,
) {
companion object {
val MAP_CODEC: MapCodec<CosmeticData> = RecordCodecBuilder.mapCodec { builder ->
builder.group(
Codec.FLOAT.fieldOf("baseScale").forGetter(CosmeticData::baseScale),
ExtraCodecs.ENTITY_DIMENSIONS.fieldOf("hitbox").forGetter(CosmeticData::hitbox),
Codec.FLOAT.fieldOf("weight").forGetter(CosmeticData::weight),
Codec.FLOAT.fieldOf("height").forGetter(CosmeticData::height),
setCodec(Codec.STRING).fieldOf("aspects").forGetter(CosmeticData::aspects),
Codec.FLOAT.optionalFieldOf("standingEyeHeight", VANILLA_DEFAULT_EYE_HEIGHT).forGetter(CosmeticData::standingEyeHeight),
Codec.FLOAT.optionalFieldOf("swimmingEyeHeight", VANILLA_DEFAULT_EYE_HEIGHT).forGetter(CosmeticData::swimmingEyeHeight),
Codec.FLOAT.optionalFieldOf("flyingEyeHeight", VANILLA_DEFAULT_EYE_HEIGHT).forGetter(CosmeticData::flyingEyeHeight),
).apply(builder, ::CosmeticData)
}
val CODEC: Codec<CosmeticData> = MAP_CODEC.codec()
private const val VANILLA_DEFAULT_EYE_HEIGHT = 0.85F
}
}
@@ -1,40 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.pokemon.species.internal
import com.cobblemon.mod.common.api.pokemon.egg.EggGroup
import com.cobblemon.mod.common.api.pokemon.species.Species
import com.cobblemon.mod.common.util.codec.setCodec
import com.mojang.serialization.Codec
import com.mojang.serialization.MapCodec
import com.mojang.serialization.codecs.RecordCodecBuilder
import java.util.EnumSet
/**
* Intermediate for [Species] data.
*/
internal data class EggData(
var eggCycles: Int,
var eggGroups: EnumSet<EggGroup>,
) {
companion object {
val MAP_CODEC: MapCodec<EggData> = RecordCodecBuilder.mapCodec { builder ->
builder.group(
Codec.INT.fieldOf("eggCycles").forGetter(EggData::eggCycles),
setCodec(EggGroup.CODEC).fieldOf("eggGroups").xmap({ set -> EnumSet.copyOf(set) }, { enumSet -> enumSet }).forGetter { eggData -> eggData.eggGroups }
).apply(builder, ::EggData)
}
val CODEC: Codec<EggData> = MAP_CODEC.codec()
}
}
@@ -1,42 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.pokemon.species.internal
import com.cobblemon.mod.common.api.pokemon.evolution.Evolution
import com.cobblemon.mod.common.api.pokemon.evolution.PreEvolution
import com.cobblemon.mod.common.api.pokemon.evolution.adapters.EvolutionRegistry
import com.cobblemon.mod.common.api.pokemon.species.Species
import com.cobblemon.mod.common.util.codec.setCodec
import com.mojang.serialization.Codec
import com.mojang.serialization.MapCodec
import com.mojang.serialization.codecs.RecordCodecBuilder
import java.util.*
/**
* Intermediate for [Species] data.
*/
internal data class EvolutionData(
var evolutions: Set<Evolution>,
var preEvolution: Optional<PreEvolution>,
) {
companion object {
val MAP_CODEC: MapCodec<EvolutionData> = RecordCodecBuilder.mapCodec { builder ->
builder.group(
setCodec(EvolutionRegistry.EVOLUTION_CODEC).optionalFieldOf("evolutions", emptySet()).forGetter(EvolutionData::evolutions),
PreEvolution.CODEC.optionalFieldOf("preEvolution").forGetter(EvolutionData::preEvolution)
).apply(builder, ::EvolutionData)
}
val CODEC: Codec<EvolutionData> = MAP_CODEC.codec()
}
}
@@ -1,36 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.pokemon.species.internal
import com.cobblemon.mod.common.api.pokemon.experience.ExperienceGroup
import com.cobblemon.mod.common.api.pokemon.species.Species
import com.mojang.serialization.Codec
import com.mojang.serialization.MapCodec
import com.mojang.serialization.codecs.RecordCodecBuilder
/**
* Intermediate for [Species] data.
*/
internal data class ExperienceData(
var baseExperienceYield: Int,
var experienceGroup: ExperienceGroup
) {
companion object {
val MAP_CODEC: MapCodec<ExperienceData> = RecordCodecBuilder.mapCodec { builder ->
builder.group(
Codec.INT.fieldOf("baseExperienceYield").forGetter(ExperienceData::baseExperienceYield),
ExperienceGroup.CODEC.fieldOf("experienceGroup").forGetter(ExperienceData::experienceGroup),
).apply(builder, ::ExperienceData)
}
}
}
@@ -1,130 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.pokemon.stats
import com.mojang.serialization.Codec
import kotlin.math.absoluteValue
import kotlin.math.min
/**
* An implementation of [StatMap] aimed solely at the EV data structure.
* This exists due to a few extra constraints present in EVs regarding the total value of the structure.
*
* @see <a href="https://bulbapedia.bulbagarden.net/wiki/Effort_values">Effort values Bulbapedia entry</a>
*/
@Suppress("MemberVisibilityCanBePrivate")
class EvMap internal constructor(stats: HashMap<Stat, Int>) : StatMap(Variant.EV, stats) {
init {
if (this.values.sum() > MAX_TOTAL) {
throw IllegalArgumentException("Cannot instance ${this::class.simpleName} with values total exceeding $MAX_TOTAL")
}
}
/**
* Inherits the logic of [StatMap.validateValue].
* This has the added constraint of the maximum possible total value being [MAX_TOTAL].
*
* @see StatMap.validateValue
*/
override fun validateValue(key: Stat, value: Int) {
super.validateValue(key, value)
val existing = this[key]
val current = this.values.sum() - existing
if (current + value > MAX_TOTAL) {
throw IllegalArgumentException("The total of the values of an ${this::class.simpleName} cannot exceed $MAX_TOTAL")
}
}
/**
* Adds to the given [stat].
*
* @param stat The [Stat] being added to.
* @param amount The amount being added. This value will be sanitized with [Int.absoluteValue].
* @param coerceSafe Should the value be coerced to be safe to add?
* @return The new resulting value of [stat].
*
* @throws IllegalArgumentException if [validateValue] fails.
*
* @see subtract
* @see mutate
*/
fun add(stat: Stat, amount: Int, coerceSafe: Boolean): Int = this.mutate(stat, amount.absoluteValue, coerceSafe)
/**
* Subtracts from the given [stat].
*
* @param stat The [Stat] being subtracted from.
* @param amount The amount being subtracted. This value will be sanitized with [Int.absoluteValue].
* @param coerceSafe Should the value be coerced to be safe to subtract?
* @return The new resulting value of [stat].
*
* @throws IllegalArgumentException if [validateValue] fails.
*
* @see add
* @see mutate
*/
fun subtract(stat: Stat, amount: Int, coerceSafe: Boolean): Int = this.mutate(stat, amount.absoluteValue, coerceSafe)
/**
* Mutates the given [stat].
*
* @param stat The [Stat] being mutated.
* @param amount The amount being used in the mutation operation.
* @param coerceSafe Should the value be coerced to be safe to operate with?
* @return The new resulting value of [stat].
*
* @throws IllegalArgumentException if [validateValue] fails.
*
* @see add
* @see subtract
*/
fun mutate(stat: Stat, amount: Int, coerceSafe: Boolean): Int {
var result = this[stat] + amount
if (coerceSafe) {
result = result.coerceIn(this.variant.minValue, min(this.variant.maxValue, this.remaining()))
}
this.put(stat, result)
return result
}
/**
* Resolves how many EVs can still be allocated to this structure.
*
* @return How many EVs can still be allocated.
*/
fun remaining(): Int = MAX_TOTAL - this.values.sum()
companion object {
/**
* A [Codec] for a [EvMap].
*/
@JvmField
val EV_STATS_CODEC: Codec<EvMap> = Codec.unboundedMap(Stat.CODEC, Codec.intRange(Variant.EV.minValue, Variant.EV.maxValue))
.xmap({ map -> EvMap(HashMap(map)) }, { evMap -> evMap })
/**
* The maximum total EV values.
*/
const val MAX_TOTAL = 510
/**
* Creates a [EvMap] with the given params.
*
* @param map The base map to take values from.
* @return The generated [EvMap].
*
* @throws IllegalArgumentException If the constraints seen in [StatMap.create] are not fulfilled or if the total of the values exceeds [MAX_TOTAL].
*/
fun create(map: Map<Stat, Int>): EvMap = EvMap(HashMap(map))
}
}
@@ -8,8 +8,6 @@
package com.cobblemon.mod.common.api.pokemon.stats
import com.cobblemon.mod.common.Cobblemon
import com.mojang.serialization.Codec
import net.minecraft.text.Text
import net.minecraft.util.Identifier
@@ -63,10 +61,4 @@ interface Stat {
}
companion object {
val CODEC: Codec<Stat> = Identifier.CODEC.xmap(Cobblemon.statProvider::fromIdentifierOrThrow, Stat::identifier)
}
}
@@ -1,287 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.pokemon.stats
import com.cobblemon.mod.common.Cobblemon
import com.cobblemon.mod.common.api.serialization.BufferSerializer
import com.cobblemon.mod.common.api.serialization.DataSerializer
import com.cobblemon.mod.common.pokemon.EVs
import com.cobblemon.mod.common.pokemon.IVs
import com.google.gson.JsonObject
import com.mojang.serialization.Codec
import com.mojang.serialization.JsonOps
import net.minecraft.nbt.NbtCompound
import net.minecraft.nbt.NbtOps
import net.minecraft.network.PacketByteBuf
import kotlin.jvm.optionals.getOrDefault
/**
* Represents a map-like structure that is used solely for the purpose of various stat-like Pokémon data structures.
*
* @property variant The [Variant] of this map.
* @property stats The base map used for this map.
*
* @see <a href="https://bulbapedia.bulbagarden.net/wiki/Base_stats">Base stats Bulbapedia entry</a>
* @see <a href="https://bulbapedia.bulbagarden.net/wiki/Effort_values">Effort values Bulbapedia entry</a>
* @see <a href="https://bulbapedia.bulbagarden.net/wiki/Individual_values">Individual values Bulbapedia entry</a>
*
*/
@Suppress("unused", "MemberVisibilityCanBePrivate")
open class StatMap internal constructor(
val variant: Variant,
protected val stats: HashMap<Stat, Int>
) : Map<Stat, Int>, DataSerializer<NbtCompound, JsonObject>, BufferSerializer {
init {
if (!Cobblemon.statProvider.ofType(Stat.Type.PERMANENT).all(this.stats::containsKey)) {
throw IllegalArgumentException("Cannot instance ${this::class.simpleName} without all ${Stat.Type.PERMANENT.name} ${Stat::class.simpleName}")
}
if (!this.stats.values.any { value -> this.variant.fits(value) }) {
throw IllegalArgumentException("Cannot instance ${this::class.simpleName} with values not in range [${this.variant.minValue}-${this.variant.maxValue}]")
}
}
override val entries: Set<Map.Entry<Stat, Int>>
get() = this.stats.entries
override val keys: Set<Stat>
get() = this.stats.keys
override val size: Int
get() = this.stats.size
override val values: Collection<Int>
get() = this.stats.values
/**
* A constraint of implementing [Map].
* This is impossible to be false.
*
* @return Always true.
*/
override fun isEmpty(): Boolean = false
/**
* Returns the value corresponding to the given [key].
* Due to implementation details unlike a typical [Map.get] this will never return null.
*
* @param key The [Stat] being checked.
* @return The value attached to the [key].
*/
override fun get(key: Stat): Int = this.stats[key]!!
override fun containsValue(value: Int): Boolean = this.stats.containsValue(value)
override fun containsKey(key: Stat): Boolean = this.stats.containsKey(key)
override fun loadFromNBT(nbt: NbtCompound) {
this.codec().decode(NbtOps.INSTANCE, nbt)
.result()
.ifPresent { pair -> this.putAll(pair.first) }
}
override fun saveToNBT(): NbtCompound {
val result = this.codec().encodeStart(NbtOps.INSTANCE, this)
.result()
.getOrDefault(NbtCompound())
// It's safe to cast it will always result in a NbtCompound
return result as NbtCompound
}
override fun loadFromJson(json: JsonObject) {
this.codec().decode(JsonOps.INSTANCE, json)
.result()
.ifPresent { pair -> this.putAll(pair.first) }
}
override fun saveToJson(): JsonObject {
val result = this.codec().encodeStart(JsonOps.INSTANCE, this)
.result()
.getOrDefault(JsonObject())
// It's safe to cast it will always result in a JsonObject
return result as JsonObject
}
override fun saveToBuffer(buffer: PacketByteBuf, toClient: Boolean) {
buffer.writeMap(this.stats, { pb, stat -> pb.writeIdentifier(stat.identifier) }, PacketByteBuf::writeInt)
}
override fun loadFromBuffer(buffer: PacketByteBuf) {
// This is safe to do as the server will have sanitized the values.
this.stats.clear()
this.stats.putAll(buffer.readMap({ pb -> Cobblemon.statProvider.decode(pb) }, PacketByteBuf::readInt))
}
/**
* Resets the value for the given [key] to the [Variant.minValue] of [variant].
*
* @param key The [Stat] being reset.
* @return The previous attached value.
*
* @throws IllegalArgumentException If the [key] fails [validateKey].
*/
fun reset(key: Stat): Int {
this.validateKey(key)
val existing = this.stats[key]!!
this.stats[key] = this.variant.minValue
return existing
}
/**
* Resets all values of this map to the [Variant.minValue] of [variant].
*/
fun reset() {
Cobblemon.statProvider.ofType(Stat.Type.PERMANENT).forEach(this::reset)
}
/**
* Merges key-value pairs from a map into this [StatMap].
*
* @param from The map being merged.
*
* @throws IllegalArgumentException If any value of [from] fails [validateValue].
*/
fun putAll(from: Map<out Stat, Int>) {
from.forEach(this::put)
}
/**
* Puts the given [value] on the given [key] [Stat] of this [StatMap].
*
* @param key The [Stat] being set.
* @param value The value being set to the [key].
* @return The previously attached value.
*
* @throws IllegalArgumentException If the [value] fails [validateValue].
*/
fun put(key: Stat, value: Int): Int {
this.validateValue(key, value)
val existing = this.stats[key]!!
this.stats[key] = value
return existing
}
/**
* Resolves the [Codec] for this instance.
* This is done based on the [variant].
*
* @return The [Codec] for this specific [StatMap] setup.
*
* @see StatMap.BASE_STATS_CODEC
* @see StatMap.EV_STATS_CODEC
* @see StatMap.IV_STATS_CODEC
*/
fun codec(): Codec<StatMap> = when (this.variant) {
Variant.BASE_STATS -> BASE_STATS_CODEC
Variant.IV -> IV_STATS_CODEC
Variant.EV -> EV_STATS_CODEC
}
/**
* Checks if a [Stat.Type] is [Stat.Type.PERMANENT].
*
* @param stat The [Stat] being checked.
*
* @throws IllegalArgumentException If the [Stat.Type] is not [Stat.Type.PERMANENT].
*/
protected open fun validateKey(stat: Stat) {
if (stat.type != Stat.Type.PERMANENT) {
throw IllegalArgumentException("Unsupported stat type of ${stat.type.name} for ${stat.identifier}")
}
}
/**
* Checks if a value is possible for this map.
*
* @param key The key having the [value] assigned.
* @param value The value being assigned.
*
* @throws IllegalArgumentException If the [value] doesn't fulfill [Variant.fits] of the [variant].
*/
protected open fun validateValue(key: Stat, value: Int) {
if (!this.variant.fits(value)) {
throw IllegalArgumentException("Cannot accept $value, a value must be in range [${this.variant.minValue}-${this.variant.maxValue}]")
}
}
/**
* Represents a type of data collected inside [StatMap].
*
* @property minValue The minimum possible value for a value of a [StatMap].
* @property maxValue The maximum possible value for a value of a [StatMap].
*/
enum class Variant(val minValue: Int, val maxValue: Int) {
/**
* Used to represent [base stats](https://bulbapedia.bulbagarden.net/wiki/Base_stats).
*/
BASE_STATS(1, Int.MAX_VALUE),
/**
* Used to represent [effort values](https://bulbapedia.bulbagarden.net/wiki/Effort_values).
*/
EV(0, EVs.MAX_STAT_VALUE),
/**
* Used to represent [individual values](https://bulbapedia.bulbagarden.net/wiki/Individual_values).
*/
IV(0, IVs.MAX_VALUE);
/**
* Checks if the given [value] fits within the range created by [minValue] & [maxValue].
*
* @param value The value being checked.
* @return If the value can fit in this variant.
*/
fun fits(value: Int): Boolean = value >= this.minValue && value <= this.maxValue
}
companion object {
/**
* A [Codec] for a [StatMap] of the [Variant.BASE_STATS] variant.
*/
@JvmField
val BASE_STATS_CODEC: Codec<StatMap> = this.createCodec(Variant.BASE_STATS)
/**
* A [Codec] for a [StatMap] of the [Variant.EV] variant.
* For the [EvMap] typed Codec see [EvMap.EV_STATS_CODEC].
* The result as far as instance types go is the same this is just a constraint of [Codec].
*
* @see EvMap.EV_STATS_CODEC
*/
@JvmField
val EV_STATS_CODEC: Codec<StatMap> = EvMap.EV_STATS_CODEC.xmap({ evMap -> this.create(Variant.EV, evMap) }, EvMap::create)
/**
* A [Codec] for a [StatMap] of the [Variant.IV] variant.
*/
@JvmField
val IV_STATS_CODEC: Codec<StatMap> = this.createCodec(Variant.IV)
/**
* Creates a [StatMap] with the given params.
*
* @param variant The [StatMap] [Variant].
* @param map The base map to take values from.
* @return The generated [StatMap].
*
* @throws IllegalArgumentException If map doesn't contain every possible key with type [Stat.Type.PERMANENT] or if any value doesn't respect [Variant.fits] for the given [variant].
*/
fun create(variant: Variant, map: Map<Stat, Int>): StatMap = when (variant) {
Variant.BASE_STATS -> StatMap(variant, HashMap(map))
Variant.EV -> EvMap(HashMap(map))
Variant.IV -> StatMap(variant, HashMap(map))
}
private fun createCodec(variant: Variant): Codec<StatMap> = Codec.unboundedMap(Stat.CODEC, Codec.intRange(variant.minValue, variant.maxValue))
.xmap({ map -> StatMap(variant, HashMap(map)) }, { statMap -> statMap })
}
}
@@ -9,7 +9,11 @@
package com.cobblemon.mod.common.api.pokemon.stats
import com.cobblemon.mod.common.Cobblemon
import com.cobblemon.mod.common.pokemon.*
import com.cobblemon.mod.common.pokemon.EVs
import com.cobblemon.mod.common.pokemon.FormData
import com.cobblemon.mod.common.pokemon.IVs
import com.cobblemon.mod.common.pokemon.Pokemon
import com.cobblemon.mod.common.pokemon.Species
import com.cobblemon.mod.common.pokemon.stat.CobblemonStatProvider
import net.minecraft.network.PacketByteBuf
import net.minecraft.util.Identifier
@@ -8,6 +8,7 @@
package com.cobblemon.mod.common.api.pokemon.status
import com.cobblemon.mod.common.pokemon.status.PersistentStatus
import com.cobblemon.mod.common.pokemon.status.statuses.BurnStatus
import com.cobblemon.mod.common.pokemon.status.statuses.FrozenStatus
import com.cobblemon.mod.common.pokemon.status.statuses.ParalysisStatus
@@ -39,4 +40,5 @@ object Statuses {
fun getStatus(name: Identifier) = allStatuses.find { status -> status.name == name }
fun getStatus(showdownName: String) = allStatuses.find { it.showdownName == showdownName }
fun getPersistentStatuses() = allStatuses.filterIsInstance<PersistentStatus>()
}
@@ -1,25 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.registry
import com.cobblemon.mod.common.Cobblemon
import com.cobblemon.mod.common.api.pokemon.species.Species
import com.cobblemon.mod.common.api.types.ElementalType
import net.minecraft.registry.Registry
import net.minecraft.registry.RegistryKey
object CobblemonRegistries {
val ELEMENTAL_TYPE: Registry<ElementalType> get() = this.get(CobblemonRegistryKeys.ELEMENTAL_TYPE)
val SPECIES: Registry<Species> get() = this.get(CobblemonRegistryKeys.SPECIES)
private fun <T> get(key: RegistryKey<Registry<T>>): Registry<T> = Cobblemon.implementation.getRegistry(key)
}
@@ -1,26 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.registry
import net.minecraft.registry.Registry
import net.minecraft.registry.entry.RegistryEntry
import net.minecraft.registry.tag.TagKey
import net.minecraft.util.Identifier
interface CobblemonRegistryElement<T : CobblemonRegistryElement<T>> {
fun isIn(tag: TagKey<T>): Boolean = this.registryEntry().isIn(tag)
fun id(): Identifier
fun registryEntry(): RegistryEntry<T>
fun registry(): Registry<T>
}
@@ -1,29 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.registry
import com.cobblemon.mod.common.api.moves.MoveTemplate
import com.cobblemon.mod.common.api.pokemon.species.Species
import com.cobblemon.mod.common.api.types.ElementalType
import com.cobblemon.mod.common.util.cobblemonResource
import net.minecraft.registry.Registry
import net.minecraft.registry.RegistryKey
/**
* Contains the various [RegistryKey]s for Cobblemon.
*/
object CobblemonRegistryKeys {
val ELEMENTAL_TYPE: RegistryKey<Registry<ElementalType>> = this.create("elemental_types")
val SPECIES: RegistryKey<Registry<Species>> = this.create("species")
private fun <T> create(key: String): RegistryKey<Registry<T>> = RegistryKey.ofRegistry(cobblemonResource(key))
}
@@ -10,7 +10,6 @@ package com.cobblemon.mod.common.api.spawning
import com.cobblemon.mod.common.Cobblemon
import com.cobblemon.mod.common.Cobblemon.config
import com.cobblemon.mod.common.api.spawning.mixins.CachedOnlyChunkAccessor
import com.cobblemon.mod.common.api.spawning.prospecting.SpawningProspector
import com.cobblemon.mod.common.api.spawning.spawner.Spawner
import com.cobblemon.mod.common.api.spawning.spawner.SpawningArea
@@ -21,6 +20,7 @@ import net.minecraft.util.math.BlockPos
import net.minecraft.util.math.Box
import net.minecraft.util.math.ChunkSectionPos.getSectionCoord
import net.minecraft.util.math.Vec3d
import net.minecraft.world.LightType
import net.minecraft.world.chunk.Chunk
import net.minecraft.world.chunk.ChunkStatus
@@ -70,7 +70,7 @@ object CobblemonSpawningProspector : SpawningProspector {
.map { it.pos }
val defaultState = Blocks.STONE.defaultState
val defaultBlockData = WorldSlice.BlockData(defaultState, 0)
val defaultBlockData = WorldSlice.BlockData(defaultState, 0, 0)
val blocks = Array(area.length) { Array(height) { Array(area.width) { defaultBlockData } } }
val skyLevel = Array(area.length) { Array(area.width) { world.topY } }
@@ -78,25 +78,25 @@ object CobblemonSpawningProspector : SpawningProspector {
val chunks = mutableMapOf<Pair<Int, Int>, Chunk?>()
val yRange = (baseY until baseY + height).reversed()
val lightingProvider = world.lightingProvider
for (x in area.baseX until area.baseX + area.length) {
for (z in area.baseZ until area.baseZ + area.width) {
val query = chunks.computeIfAbsent(Pair(getSectionCoord(x), getSectionCoord(z))) {
val manager = world.chunkManager as CachedOnlyChunkAccessor
manager.`cobblemon$request`(it.first, it.second, ChunkStatus.FULL)
world.getChunk(it.first, it.second, ChunkStatus.FULL, false)
} ?: continue
var canSeeSky = world.isSkyVisibleAllowingSea(pos.set(x, yRange.first, z))
for (y in yRange) {
val skyLight = lightingProvider.get(LightType.SKY).getLightLevel(pos.set(x, y, z))
val state = query.getBlockState(pos.set(x, y, z))
blocks[x - area.baseX][y - baseY][z - area.baseZ] = WorldSlice.BlockData(
state = state,
light = world.getLightLevel(pos)
light = world.getLightLevel(pos),
skyLight = skyLight
)
if (canSeeSky) {
skyLevel[x - area.baseX][z - area.baseZ] = y
}
if (state.fluidState.isEmpty && !state.isIn(CobblemonBlockTags.SEES_SKY)) {
canSeeSky = false
}
@@ -19,15 +19,12 @@ import com.cobblemon.mod.common.api.spawning.detail.PossibleHeldItem
import com.cobblemon.mod.common.api.spawning.preset.SpawnDetailPreset
import com.cobblemon.mod.common.util.adapters.*
import com.cobblemon.mod.common.util.cobblemonResource
import com.cobblemon.mod.common.util.codec.toTypeAdapter
import com.cobblemon.mod.common.util.server
import com.google.gson.Gson
import com.google.gson.GsonBuilder
import com.google.gson.reflect.TypeToken
import com.mojang.datafixers.util.Either
import net.minecraft.block.Block
import net.minecraft.fluid.Fluid
import net.minecraft.registry.Registries
import net.minecraft.registry.RegistryKeys
import net.minecraft.registry.tag.TagKey
import net.minecraft.resource.ResourceType
@@ -51,9 +48,9 @@ object SpawnDetailPresets : JsonDataRegistry<SpawnDetailPreset> {
.disableHtmlEscaping()
.registerTypeAdapter(SpawnBucket::class.java, SpawnBucketAdapter)
.registerTypeAdapter(RegisteredSpawningContext::class.java, RegisteredSpawningContextAdapter)
.registerTypeAdapter(TypeToken.getParameterized(RegistryLikeCondition::class.java, Biome::class.java).type, RegistryLikeCondition.createCodec { server()!!.registryManager.get(RegistryKeys.BIOME) }.toTypeAdapter())
.registerTypeAdapter(TypeToken.getParameterized(RegistryLikeCondition::class.java, Block::class.java).type, RegistryLikeCondition.createCodec { Registries.BLOCK }.toTypeAdapter())
.registerTypeAdapter(TypeToken.getParameterized(RegistryLikeCondition::class.java, Fluid::class.java).type, RegistryLikeCondition.createCodec { Registries.FLUID }.toTypeAdapter())
.registerTypeAdapter(TypeToken.getParameterized(RegistryLikeCondition::class.java, Biome::class.java).type, BiomeLikeConditionAdapter)
.registerTypeAdapter(TypeToken.getParameterized(RegistryLikeCondition::class.java, Block::class.java).type, BlockLikeConditionAdapter)
.registerTypeAdapter(TypeToken.getParameterized(RegistryLikeCondition::class.java, Fluid::class.java).type, FluidLikeConditionAdapter)
.registerTypeAdapter(
TypeToken.getParameterized(
Either::class.java,
@@ -17,15 +17,12 @@ import com.cobblemon.mod.common.api.spawning.context.RegisteredSpawningContext
import com.cobblemon.mod.common.api.spawning.detail.PossibleHeldItem
import com.cobblemon.mod.common.api.spawning.detail.SpawnDetail
import com.cobblemon.mod.common.util.adapters.*
import com.cobblemon.mod.common.util.codec.toTypeAdapter
import com.cobblemon.mod.common.util.server
import com.google.gson.GsonBuilder
import com.google.gson.reflect.TypeToken
import com.mojang.datafixers.util.Either
import net.minecraft.block.Block
import net.minecraft.fluid.Fluid
import net.minecraft.nbt.NbtCompound
import net.minecraft.registry.Registries
import net.minecraft.registry.RegistryKeys
import net.minecraft.registry.tag.TagKey
import net.minecraft.util.Identifier
@@ -44,9 +41,9 @@ object SpawnLoader {
.setPrettyPrinting()
.disableHtmlEscaping()
.setLenient()
.registerTypeAdapter(TypeToken.getParameterized(RegistryLikeCondition::class.java, Biome::class.java).type, RegistryLikeCondition.createCodec { server()!!.registryManager.get(RegistryKeys.BIOME) }.toTypeAdapter())
.registerTypeAdapter(TypeToken.getParameterized(RegistryLikeCondition::class.java, Block::class.java).type, RegistryLikeCondition.createCodec { Registries.BLOCK }.toTypeAdapter())
.registerTypeAdapter(TypeToken.getParameterized(RegistryLikeCondition::class.java, Fluid::class.java).type, RegistryLikeCondition.createCodec { Registries.FLUID }.toTypeAdapter())
.registerTypeAdapter(TypeToken.getParameterized(RegistryLikeCondition::class.java, Biome::class.java).type, BiomeLikeConditionAdapter)
.registerTypeAdapter(TypeToken.getParameterized(RegistryLikeCondition::class.java, Block::class.java).type, BlockLikeConditionAdapter)
.registerTypeAdapter(TypeToken.getParameterized(RegistryLikeCondition::class.java, Fluid::class.java).type, FluidLikeConditionAdapter)
.registerTypeAdapter(
TypeToken.getParameterized(
Either::class.java,
@@ -31,12 +31,16 @@ open class SpawnerManager {
open fun registerSpawner(spawner: Spawner) {
spawners.add(spawner)
spawner.influences.addAll(influences)
if (spawner !is TickingSpawner) {
spawner.influences.addAll(influences)
}
}
open fun unregisterSpawner(spawner: Spawner) {
spawners.remove(spawner)
spawner.influences.removeAll(influences)
if (spawner !is TickingSpawner) {
spawner.influences.removeAll(influences)
}
}
open fun onServerStarted() {
@@ -10,8 +10,6 @@ package com.cobblemon.mod.common.api.spawning
import com.cobblemon.mod.common.api.spawning.TimeRange.Companion.timeRanges
import com.cobblemon.mod.common.api.spawning.condition.SpawningCondition
import com.mojang.serialization.Codec
import com.mojang.serialization.DataResult
/**
* A range of time ticks for a world mainly to be used in [SpawningCondition]s. A time range
@@ -43,12 +41,6 @@ class TimeRange : IntRanges {
"morning" to TimeRange(0..4999),
"afternoon" to TimeRange(7000..12039)
)
val CODEC: Codec<TimeRange> = Codec.STRING.flatXmap(
{ string -> timeRanges[string]?.let { DataResult.success(it) } ?: DataResult.error { "Can't find a time range with ID $string" } },
{ timeRange -> timeRanges.entries.firstOrNull { (_, range) -> range == timeRange }?.let { DataResult.success(it.key) } ?: DataResult.error { "Couldn't resolve a time range ID for $timeRange" } }
)
}
constructor() : super()
@@ -44,7 +44,8 @@ class WorldSlice(
) {
class BlockData(
val state: BlockState,
val light: Int
val light: Int,
val skyLight: Int
)
val length = blocks.size
@@ -83,6 +84,15 @@ class WorldSlice(
}
fun getLight(position: BlockPos, elseLight: Int = 0) = getLight(position.x, position.y, position.z, elseLight)
fun getSkyLight(x: Int, y: Int, z: Int, elseLight: Int = 0): Int {
return if (!isInBounds(x, y, z)) {
elseLight
} else {
getBlockData(x, y, z).skyLight
}
}
fun getSkyLight(position: BlockPos, elseLight: Int = 0) = getSkyLight(position.x, position.y, position.z, elseLight)
fun skySpaceAbove(x: Int, y: Int, z: Int): Int {
return if (!isInBounds(x, y, z) || skyLevel[x - baseX][z - baseZ] > y) {
0
@@ -8,7 +8,6 @@
package com.cobblemon.mod.common.api.spawning.condition
import net.minecraft.util.StringIdentifiable
import net.minecraft.world.World
/**
@@ -18,7 +17,7 @@ import net.minecraft.world.World
* @author Licious
* @since January 25th, 2023
*/
enum class MoonPhase : StringIdentifiable {
enum class MoonPhase {
FULL_MOON,
WANING_GIBBOUS,
@@ -29,8 +28,6 @@ enum class MoonPhase : StringIdentifiable {
FIRST_QUARTER,
WAXING_GIBBOUS;
override fun asString(): String = this.name
companion object {
private val VALUES = values()
@@ -52,6 +52,8 @@ abstract class SpawningCondition<T : SpawningContext> {
var maxZ: Float? = null
var minLight: Int? = null
var maxLight: Int? = null
var minSkyLight: Int? = null
var maxSkyLight: Int? = null
var isRaining: Boolean? = null
var isThundering: Boolean? = null
var timeRange: TimeRange? = null
@@ -88,6 +90,8 @@ abstract class SpawningCondition<T : SpawningContext> {
return false
} else if (ctx.light > maxLight.orMax() || ctx.light < minLight.orMin()) {
return false
} else if (ctx.skyLight > maxSkyLight.orMax() || ctx.skyLight < minSkyLight.orMin()) {
return false
} else if (timeRange != null && !timeRange!!.contains((ctx.world.timeOfDay % 24000).toInt())) {
return false
} else if (canSeeSky != null && canSeeSky != ctx.canSeeSky) {
@@ -134,6 +138,8 @@ abstract class SpawningCondition<T : SpawningContext> {
maxZ = merger.mergeSingle(maxZ, other.maxZ)
minLight = merger.mergeSingle(minLight, other.minLight)
maxLight = merger.mergeSingle(maxLight, other.maxLight)
minSkyLight = merger.mergeSingle(minSkyLight, other.minSkyLight)
maxSkyLight = merger.mergeSingle(maxSkyLight, other.maxSkyLight)
timeRange = merger.mergeSingle(timeRange, other.timeRange)
structures = merger.merge(structures, other.structures)?.toMutableList()
}
@@ -30,6 +30,7 @@ open class AreaSpawningContext(
override val world: ServerWorld,
override val position: BlockPos,
override val light: Int,
override val skyLight: Int,
override val canSeeSky: Boolean,
override val influences: MutableList<SpawningInfluence>,
/** Space above. */
@@ -27,12 +27,13 @@ abstract class FlooredSpawningContext(
world: ServerWorld,
position: BlockPos,
light: Int,
skyLight: Int,
canSeeSky: Boolean,
influences: MutableList<SpawningInfluence>,
height: Int,
nearbyBlocks: List<BlockState>,
slice: WorldSlice
) : AreaSpawningContext(cause, world, position, light, canSeeSky, influences, height, nearbyBlocks, slice) {
) : AreaSpawningContext(cause, world, position, light, skyLight, canSeeSky, influences, height, nearbyBlocks, slice) {
/** The block that the spawning is occurring on. */
val baseBlock = slice.getBlockState(position.x, position.y, position.z)
}
@@ -48,12 +49,13 @@ open class GroundedSpawningContext(
world: ServerWorld,
position: BlockPos,
light: Int,
skyLight: Int,
canSeeSky: Boolean,
influences: MutableList<SpawningInfluence>,
height: Int,
nearbyBlocks: List<BlockState>,
slice: WorldSlice
) : FlooredSpawningContext(cause, world, position, light, canSeeSky, influences, height, nearbyBlocks, slice)
) : FlooredSpawningContext(cause, world, position, light, skyLight, canSeeSky, influences, height, nearbyBlocks, slice)
/**
* A spawning context that occurs at the bottom of a body of water.
@@ -66,12 +68,13 @@ open class SeafloorSpawningContext(
world: ServerWorld,
position: BlockPos,
light: Int,
skyLight: Int,
canSeeSky: Boolean,
influences: MutableList<SpawningInfluence>,
height: Int,
nearbyBlocks: List<BlockState>,
slice: WorldSlice
) : FlooredSpawningContext(cause, world, position, light, canSeeSky, influences, height, nearbyBlocks, slice) {
) : FlooredSpawningContext(cause, world, position, light, skyLight, canSeeSky, influences, height, nearbyBlocks, slice) {
override fun isSafeSpace(world: ServerWorld, pos: BlockPos, state: BlockState) = state.fluidState.isIn(FluidTags.WATER)
}
@@ -86,12 +89,13 @@ open class LavafloorSpawningContext(
world: ServerWorld,
position: BlockPos,
light: Int,
skyLight: Int,
canSeeSky: Boolean,
influences: MutableList<SpawningInfluence>,
height: Int,
nearbyBlocks: List<BlockState>,
slice: WorldSlice
) : FlooredSpawningContext(cause, world, position, light, canSeeSky, influences, height, nearbyBlocks, slice) {
) : FlooredSpawningContext(cause, world, position, light, skyLight, canSeeSky, influences, height, nearbyBlocks, slice) {
override fun isSafeSpace(world: ServerWorld, pos: BlockPos, state: BlockState) = state.fluidState.isIn(FluidTags.LAVA)
}
@@ -100,10 +104,11 @@ open class SurfaceSpawningContext(
world: ServerWorld,
position: BlockPos,
light: Int,
skyLight: Int,
canSeeSky: Boolean,
influences: MutableList<SpawningInfluence>,
height: Int,
val depth: Int,
nearbyBlocks: List<BlockState>,
slice: WorldSlice
) : FlooredSpawningContext(cause, world, position, light, canSeeSky, influences, height, nearbyBlocks, slice)
) : FlooredSpawningContext(cause, world, position, light, skyLight, canSeeSky, influences, height, nearbyBlocks, slice)
@@ -61,6 +61,8 @@ abstract class SpawningContext {
abstract val position: BlockPos
/** The light level at this location. */
abstract val light: Int
/** The sky light level at this location. (15 - The distance to the nearest block that would be illuminated by the sun */
abstract val skyLight: Int
/** Whether or not the sky is visible at this location. */
abstract val canSeeSky: Boolean
/** A list of [SpawningInfluence]s that apply due to this specific context. */
@@ -26,13 +26,14 @@ open class SubmergedSpawningContext(
world: ServerWorld,
position: BlockPos,
light: Int,
skyLight: Int,
canSeeSky: Boolean,
influences: MutableList<SpawningInfluence>,
height: Int,
val depth: Int,
nearbyBlocks: List<BlockState>,
slice: WorldSlice
) : AreaSpawningContext(cause, world, position, light, canSeeSky, influences, height, nearbyBlocks, slice) {
) : AreaSpawningContext(cause, world, position, light, skyLight, canSeeSky, influences, height, nearbyBlocks, slice) {
val fluid = slice.getBlockState(position.x, position.y, position.z).fluidState
override fun isSafeSpace(world: ServerWorld, pos: BlockPos, state: BlockState) = state.fluidState.fluid == fluid.fluid
@@ -45,6 +45,8 @@ interface AreaSpawningContextCalculator<O : AreaSpawningContext> : SpawningConte
= input.slice.horizontalSpace(input.position.x + offsetX, input.position.y + offsetY, input.position.z + offsetZ, condition, maximum)
fun getLight(input: AreaSpawningInput, elseLight: Int = 0): Int
= input.slice.getLight(input.position.x, input.position.y + 1, input.position.z, elseLight)
fun getSkyLight(input: AreaSpawningInput, elseLight: Int = 0): Int
= input.slice.getSkyLight(input.position.x, input.position.y + 1, input.position.z, elseLight)
fun getCanSeeSky(input: AreaSpawningInput): Boolean = input.slice.canSeeSky(input.position.x, input.position.y + 1, input.position.z)
fun getSkySpaceAbove(input: AreaSpawningInput): Int = input.slice.skySpaceAbove(input.position.x, input.position.y, input.position.z)
fun getNearbyBlocks(
@@ -59,6 +59,7 @@ object GroundedSpawningContextCalculator : FlooredSpawningContextCalculator<Grou
world = input.world,
position = input.position.toImmutable(),
light = getLight(input),
skyLight = getSkyLight(input),
canSeeSky = getCanSeeSky(input),
influences = input.spawner.copyInfluences(),
height = getHeight(input, surroundingCondition, config.maxVerticalSpace, offsetY = 1),
@@ -85,6 +86,7 @@ object SeafloorSpawningContextCalculator : FlooredSpawningContextCalculator<Seaf
world = input.world,
position = input.position.toImmutable(),
light = getLight(input),
skyLight = getSkyLight(input),
canSeeSky = getCanSeeSky(input),
influences = input.spawner.copyInfluences(),
height = getHeight(input, surroundingCondition, config.maxVerticalSpace, offsetY = 1),
@@ -111,6 +113,7 @@ object LavafloorSpawningContextCalculator : FlooredSpawningContextCalculator<Lav
world = input.world,
position = input.position.toImmutable(),
light = getLight(input),
skyLight = getSkyLight(input),
canSeeSky = getCanSeeSky(input),
influences = input.spawner.copyInfluences(),
height = getHeight(input, surroundingCondition, config.maxVerticalSpace, offsetY = 1),
@@ -138,6 +141,7 @@ object SurfaceSpawningContextCalculator : FlooredSpawningContextCalculator<Surfa
world = input.world,
position = input.position.toImmutable(),
light = getLight(input),
skyLight = getSkyLight(input),
canSeeSky = getCanSeeSky(input),
influences = input.spawner.copyInfluences(),
height = getHeight(input, surroundingCondition, config.maxVerticalSpace / 2, offsetY = 1),
@@ -45,6 +45,7 @@ object SubmergedSpawningContextCalculator : AreaSpawningContextCalculator<Submer
world = input.world,
position = input.position.toImmutable(),
light = getLight(input),
skyLight = getSkyLight(input),
canSeeSky = getCanSeeSky(input),
influences = input.spawner.copyInfluences(),
height = getHeight(input, fluidCondition, ceil(config.maxVerticalSpace / 2F)),

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