Compare commits

..
373 Commits
Author SHA1 Message Date
Plastered_Crab 071f05337c Scale tab in Implementation GUI moves test wool in X direction based on hitbox size of pokemon to prevent overlap 2026-03-02 15:47:59 -08:00
Plastered_Crab e9d274fbfd Scale tab in Implementation GUI renders test wool block nicely 2026-03-02 15:23:45 -08:00
Plastered_Crab 5709527bf2 Merge branch 'main' into ta-daaa 2026-03-02 13:17:58 -08:00
Polymeta e6d2430405 Merge branch 'BWG-tag-updates' into 'main'
Fixes to BWG compat.

See merge request cable-mc/cobblemon!2172
2026-03-02 09:42:03 +00:00
Veraxiel 6c425a43c6 Fixes to BWG compat. 2026-03-01 22:37:30 -05:00
Polymeta a505bad554 [skip-ci] tidy up changelog 2026-02-27 10:56:57 +00:00
Polymeta e27e5a1d92 Merge branch 'ai-switch-fix' into 'main'
Stop the constant switching from AI NPC Trainers

See merge request cable-mc/cobblemon!2128
2026-02-27 10:55:00 +00:00
Hiroku 5e0357101d Merge branch 'feat/fishing-spawner-factory' into 'main'
PokeSnack and Fishing Spawner factories

See merge request cable-mc/cobblemon!2136
2026-02-27 02:11:53 +00:00
Andy 5420f7419f re-run licenseFormat 2026-02-26 19:14:03 -05:00
Andy 43ed2d3c7d local backmerge 2026-02-26 19:12:17 -05:00
Andy 93500f59ed Remove changelog lines from backmerge and run licenseFormat 2026-02-26 19:10:45 -05:00
Polymeta 08912fd53f Merge branch '#1945-brewing-stand-crash' into 'main'
#1945 Brewing Stand Shift Click Crash NeoForge 1.7.3 [1.21.1]

See merge request cable-mc/cobblemon!2163
2026-02-27 00:08:36 +00:00
CyrusandPolymeta 92c8fc0afc #1945 Brewing Stand Shift Click Crash NeoForge 1.7.3 [1.21.1] 2026-02-27 00:08:36 +00:00
Polymeta fae6bdb782 Merge branch 'main' into 'main'
Move BYG compat to Biomes We've Gone and Nether Descent

See merge request cable-mc/cobblemon!2149
2026-02-26 22:52:33 +00:00
J.T. McQuiggandPolymeta bba0100542 Move BYG compat to Biomes We've Gone and Nether Descent 2026-02-26 22:52:33 +00:00
Andy f9b66de742 Add fishing spawner factory to register influences to 2026-02-26 15:54:09 +00:00
Andy 3d0f1c826a Merge branch 'main' into feat/fishing-spawner-factory
update with cobblemon head
2026-02-26 10:52:48 -05:00
Andy 2a59add285 Merge branch cobblemon:main into main 2026-02-26 15:50:16 +00:00
Polymeta 0b83128aa0 Merge branch 'main' into 'main'
Fixes brushing for neoforge

Closes #1939

See merge request cable-mc/cobblemon!2154
2026-02-26 15:43:03 +00:00
Polymeta e2b04ff770 Merge branch 'ufo-fixes-and-improvements' into 'main'
UFO Fixes and Improvements

See merge request cable-mc/cobblemon!2156
2026-02-26 15:29:38 +00:00
Jackson BowesandPolymeta 4dabe50d43 UFO Fixes and Improvements 2026-02-26 15:29:37 +00:00
Hugin Juliansson Zachariasen 3dd0795b88 Merge branch cobblemon:main into main 2026-02-26 14:14:56 +00:00
Polymeta 70f1a8207f fix a apricorn bonemeal crash
Signed-off-by: Polymeta <40173118+Polymeta@users.noreply.github.com>
2026-02-26 12:17:32 +00:00
Polymeta 3ac18cce6e Merge branch 'main' into 'main'
Berry Growth Performance Optimization

See merge request cable-mc/cobblemon!2142
2026-02-26 12:15:32 +00:00
Polymeta aa0a0672d0 Merge branch 'show-my-pokemon-exp-gain' into 'main'
Party Overlay EXP display and evoltion unlocked Sound

See merge request cable-mc/cobblemon!2140
2026-02-26 11:59:48 +00:00
GertimoshkaandPolymeta ec2958400b Party Overlay EXP display and evoltion unlocked Sound 2026-02-26 11:59:48 +00:00
Polymeta fcb6bea78b Merge branch 'selecting-starters-in-style' into 'main'
The Cooler Starter Selection GUI

See merge request cable-mc/cobblemon!2164
2026-02-26 11:58:31 +00:00
GertimoshkaandPolymeta 5a76a39b77 The Cooler Starter Selection GUI 2026-02-26 11:58:31 +00:00
Jackson Bowes b5a4acfb7a Merge branch 'weight-influenced-collision' into 'main'
Weight influenced collision

See merge request cable-mc/cobblemon!2158
2026-02-26 01:49:56 -06:00
Jackson Bowes 1248230e67 Merge branch 'pasture-wander' into 'main'
No more pastured mons despawning

See merge request cable-mc/cobblemon!2155
2026-02-26 01:47:17 -06:00
Jackson Bowes 096db6cdcd No more pastured mons despawning 2026-02-26 01:47:16 -06:00
Jackson Bowes 72e416b9c7 Merge branch 'sub-drifting-fix' into 'main'
Submarine bug fixes

See merge request cable-mc/cobblemon!2157
2026-02-26 01:44:58 -06:00
Polymeta 9e8e80965b Merge branch 'fix/missing-botanypots-entries' into 'main'
Updated Botany Pots integration

See merge request cable-mc/cobblemon!2166
2026-02-26 07:41:03 +00:00
GitoidoandPolymeta 2325b436b1 Updated Botany Pots integration 2026-02-26 07:41:02 +00:00
Jackson Bowes 57421a2884 Merge branch 'scrolling_textures' into 'main'
Scrolling Texture Layer

See merge request cable-mc/cobblemon!2168
2026-02-25 21:54:47 -06:00
jackowes 4fdd3eba8e - changelog entry 2026-02-25 20:24:29 -06:00
jackowes e6efe800c0 - Clean up mixin
- add changelog entry
2026-02-25 19:45:52 -06:00
Polymeta 95aa99e18c Merge branch 'fix/particle-disapearing' into 'main'
fix: adapting the boundingBox to the visual if it's a beam it should have a...

See merge request cable-mc/cobblemon!2167
2026-02-26 01:16:09 +00:00
TerrainwaxandPolymeta 270484e745 fix: adapting the boundingBox to the visual if it's a beam it should have a... 2026-02-26 01:16:09 +00:00
Polymeta 719addf633 Merge branch 'molang-or-dishonor' into 'main'
Added `has_chosen_starter` & `get_starter_uuid` as available Molang functions

See merge request cable-mc/cobblemon!2159
2026-02-25 23:05:54 +00:00
Polymeta 31e386871f Merge branch 'little-dose-of-molang' into 'main'
Enchanting Molang

See merge request cable-mc/cobblemon!2162
2026-02-25 23:00:15 +00:00
Tyzillion bfd7e596d0 changelog 2026-02-25 17:52:39 -05:00
Tyzillion 643545d54c Added the ability to set a layer in the resolver as a scrolling texture. 2026-02-25 16:41:50 -05:00
Tyzillion fcb017f980 New Molang functions to check if an item is enchanted or has a certain enchantment. 2026-02-23 08:48:51 -05:00
Plastered_Crab bc9f28811d Implementation Tab Animation option improvements 2026-02-19 13:43:41 -08:00
Plastered_Crab ff9eb60cd3 Implementation Tab Animation option improvements 2026-02-19 12:39:39 -08:00
Spicy dd52da7c42 oops 2026-02-18 20:57:23 -06:00
Spicy ff45def0e8 Added has_chosen_starter & get_starter_uuid as available Molang functions 2026-02-18 20:42:40 -06:00
Plastered_Crab de0b53e529 Implementation tabs updated. Walk Speed tab blocks rendering 2026-02-18 16:15:05 -08:00
jackowes f078584e56 - Add weight influenced collision 2026-02-18 15:24:43 -06:00
jackowes a11382b5a1 - Braking now works on Submarine (whoops).
- Strafing now has the same friction as forward movement (funny whoops).
- Submarine's surfacewater animations now play.
- Submarine camera no longer freaks out when looking up or down on the surface.
2026-02-17 20:28:55 -06:00
Plastered_Crab 56ecbfe3c0 Move tab testing 2026-02-16 15:45:35 -08:00
Plastered_Crab 62f03c536d Polishing up of the General Tab 2026-02-16 12:02:54 -08:00
Plastered_Crab 2fa03b6013 Adjust position of elements 2026-02-16 08:40:53 -08:00
Plastered_Crab 59af4053a1 Held Item Item Slot Searching 2026-02-15 22:09:33 -08:00
Plastered_Crab 1aba8c52b6 Held Item Item Slot Renders now 2026-02-15 21:11:23 -08:00
Plastered_Crab 6a386937c8 Held Item Item Slot 2026-02-15 20:01:58 -08:00
Plastered_Crab 00132f6428 Cosmetic Item Slot 2026-02-15 19:10:55 -08:00
Plastered_Crab 7fe222422b Cosmetic Item filtering 2026-02-15 18:37:11 -08:00
Plastered_Crab 812f389231 Cosmetic Item fixes 2026-02-15 18:08:17 -08:00
Paul d1b8094539 Validate party positions of traded Pokémon upon trading 2026-02-16 11:23:24 +10:00
Paul b8d79af911 Migrate to a more unique tag name for data and config on scriptable entities, closes #1869 2026-02-16 10:57:11 +10:00
Plastered_Crab 24acddf750 Aspects Tab adjustments 2026-02-15 16:22:51 -08:00
Plastered_Crab 1d696c58be Abra kadabra 2026-02-15 10:59:27 -08:00
Paul ef4fbecad6 Merge remote-tracking branch 'origin/1.8.0' into 1.8.0 2026-02-14 14:30:41 +10:00
Paul 96075ed34a Merge remote-tracking branch 'origin/main' into 1.8.0 2026-02-14 14:30:11 +10:00
Hugin Juliansson Zachariasen 155b4b2182 Added changelog doc 2026-02-13 17:50:46 +00:00
Faering666 690ed845b2 Fixes brushing for neoforge 2026-02-13 15:55:51 +01:00
Hiroku a7198fd324 Merge branch 'fossil_crash' into 'main'
Adjust fossil creation

Closes #1801

See merge request cable-mc/cobblemon!2150
2026-02-08 01:16:45 +00:00
aeroeng15 bc69ce91f3 Changelog 2026-02-07 16:00:00 -07:00
aeroeng15 1de1d8cdc3 Adjust ordering of party modification 2026-02-07 15:26:36 -07:00
Konoha 1f8171dd94 Experimental Hanging fix 2026-02-03 13:51:41 -05:00
Hiroku 087bf75500 Merge branch 'party-selection-toast' into 'main'
Party Selection Tutorial Toasts

See merge request cable-mc/cobblemon!2148
2026-02-02 05:58:58 +00:00
CeejayandHiroku bac435ba7b Party Selection Tutorial Toasts 2026-02-02 05:58:58 +00:00
Hiroku 74a6106eb6 Merge branch 'snack-stack-fix' into 'main'
Fixes odd stacking behavior with the poke_bait item.

See merge request cable-mc/cobblemon!2143
2026-02-01 03:29:20 +00:00
Neovitalism 5ec993ad3c Update CHANGELOG.md 2026-01-31 21:13:10 -06:00
Paul 73a03d90da Resnapshot 2026-01-31 13:22:11 +10:00
Paul e6fda6137e Teeny tiny changelog [skip-ci] 2026-01-31 10:47:13 +10:00
Paul afae39acc8 Missed a bit of changelog [skip-ci] 2026-01-31 09:21:40 +10:00
Paul 37264aff0f Changelog stuff and no snapshot 2026-01-31 09:17:43 +10:00
Paul 2b60e6de77 Merge remote-tracking branch 'origin/lang-updates' 2026-01-31 09:12:27 +10:00
Polymeta 3c2bf0e2b3 Merge branch 'cobblemon-structure' into '1.8.0'
Slippy can Cook now!

See merge request cable-mc/cobblemon!2144
2026-01-30 09:45:31 +00:00
AramandPolymeta ac695b1092 Slippy can Cook now! 2026-01-30 09:45:31 +00:00
Hiroku 4f29e7457c Merge branch 'feature/riding-scrape' into 'main'
scrape riding data and fix script

See merge request cable-mc/cobblemon!2141
2026-01-30 09:43:44 +00:00
Polymeta 04a6ab31f4 rescrape data
Signed-off-by: Polymeta <40173118+Polymeta@users.noreply.github.com>
2026-01-30 09:26:22 +00:00
Hiroku a2cdc847dd Merge branch 'packet-sync-error-fix' into 'main'
Fixed packet sync issue with pokemon interactions, added "chance" requirement type

Closes #1933 and #1938

See merge request cable-mc/cobblemon!2147
2026-01-30 03:04:14 +00:00
阿鱼andWeblate 0bca678f56 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (9061 of 9061 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/zh_Hans/
2026-01-30 02:59:44 +00:00
Paul 067c3607aa Tweak /pctake to check the PC's box count and use that for constraints 2026-01-30 12:20:17 +10:00
Hiroku 823c1f6444 Merge branch 'main' into 'main'
Fixes PcTake not respecting defaultBoxCount

See merge request cable-mc/cobblemon!2146
2026-01-30 02:18:38 +00:00
Paul bfc00635cd Fixed packet sync issue with pokemon interactions, added "chance" requirement type 2026-01-30 12:16:01 +10:00
Hiroku b2e5b85ac5 Merge branch 'Custom-Ball-Resources-updated' into 'main'
updated ball texture locations missing from last update

See merge request cable-mc/cobblemon!2145
2026-01-30 00:24:49 +00:00
阿鱼andWeblate 2c27476954 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 99.7% (9034 of 9061 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/zh_Hans/
2026-01-29 13:40:10 +00:00
Auristite aab78d84fc Fixes PcTake not respecting defaultBoxCount
Command is also missing lang option for "cobblemon.command.pctake.removed" (Removing Pokémon from self)
2026-01-29 04:46:25 +00:00
Zack the GhastandWeblate cb632c2a65 Translated using Weblate (Portuguese (Portugal))
Currently translated at 67.9% (6154 of 9061 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/pt_PT/
2026-01-29 01:28:38 +00:00
Dragonwhisper92 8d219f1338 updated ball texture locations 2026-01-28 23:45:08 +00:00
Zack the GhastandWeblate 1e6a4ed984 Translated using Weblate (Portuguese (Portugal))
Currently translated at 67.7% (6143 of 9061 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/pt_PT/
2026-01-28 21:10:25 +00:00
geumuandWeblate 64240c31fc Translated using Weblate (Korean)
Currently translated at 100.0% (9061 of 9061 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/ko/
2026-01-28 17:35:35 +00:00
Zack the GhastandWeblate d2222c3858 Translated using Weblate (Portuguese (Portugal))
Currently translated at 67.6% (6129 of 9061 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/pt_PT/
2026-01-28 14:44:02 +00:00
geumuandWeblate c7f31c3e14 Translated using Weblate (Korean)
Currently translated at 100.0% (9061 of 9061 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/ko/
2026-01-28 14:44:01 +00:00
Zack the GhastandWeblate 740e846b2d Translated using Weblate (Portuguese (Portugal))
Currently translated at 67.5% (6125 of 9061 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/pt_PT/
2026-01-28 08:26:35 +00:00
Neovitalism 246d00aa3f Fixes odd stacking behavior with the poke_bait item. 2026-01-27 21:45:05 -06:00
Zack the GhastandWeblate 06f9d60595 Translated using Weblate (Portuguese (Portugal))
Currently translated at 67.5% (6123 of 9061 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/pt_PT/
2026-01-27 04:12:54 +00:00
Konoha b3ed47fbca Adjust thresholds and scoring 2026-01-26 15:00:50 -05:00
Loopiwc 3a6ad70b76 fix: Use scheduleTick in randomTick to avoid tick scheduler NPE
- Schedule growth to next tick instead of direct setBlock in randomTick
- Add hasScheduledTick check to prevent duplicate scheduling
- Add IS_ROOTED guard in tick() handler
2026-01-27 03:35:11 +08:00
Loopiwc 8120270bf8 perf: Replace BlockEntityTicker with Random Tick + time compensation for Berry growth
- Remove per-tick BlockEntityTicker to reduce server load
- Add processTick() method with gameTime-based compensation
- Track lastTickTime in NBT for accurate growth calculation
- Berry growth timing remains accurate via elapsed time batching
2026-01-26 16:30:43 +08:00
Zack the GhastandWeblate d54439ce14 Translated using Weblate (Portuguese (Portugal))
Currently translated at 67.3% (6103 of 9061 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/pt_PT/
2026-01-26 02:31:37 +00:00
TeggyandWeblate 32ee4bb72a Translated using Weblate (Spanish)
Currently translated at 84.3% (7644 of 9061 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/es/
2026-01-25 13:02:37 +00:00
Polymeta e7d2a46cc0 Bumping snapshot version 2026-01-25 06:57:31 +00:00
YasitoandWeblate 3ee94ec076 Translated using Weblate (French)
Currently translated at 100.0% (9061 of 9061 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/fr/
2026-01-25 03:06:53 +00:00
YasitoandWeblate 589293abc4 Translated using Weblate (French (Canada))
Currently translated at 100.0% (9061 of 9061 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/fr_CA/
2026-01-25 03:06:49 +00:00
Paul 279865cc7c Resnaps your shot 2026-01-25 11:53:29 +10:00
Paul b597b149c3 Snapnot 2026-01-25 10:18:32 +10:00
Paul b7f592f2a8 Relocate mongodb packages 2026-01-25 10:18:02 +10:00
Paul 70e17c22e7 Merge remote-tracking branch 'origin/lang-updates' 2026-01-25 10:17:49 +10:00
YasitoandWeblate 51b18ca0f6 Translated using Weblate (French)
Currently translated at 99.6% (9027 of 9061 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/fr/
2026-01-25 00:16:58 +00:00
YasitoandWeblate a83f243a3b Translated using Weblate (French (Canada))
Currently translated at 99.9% (9059 of 9061 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/fr_CA/
2026-01-25 00:16:55 +00:00
Weblate f5b088c708 Update translation files
Updated by "Remove blank strings" add-on in Weblate.

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/
2026-01-25 00:14:04 +00:00
YasitoandWeblate dc454cbb68 Translated using Weblate (French)
Currently translated at 99.5% (9022 of 9061 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/fr/
2026-01-25 00:13:56 +00:00
YasitoandWeblate 3b99e38da2 Translated using Weblate (French (Canada))
Currently translated at 99.9% (9057 of 9061 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/fr_CA/
2026-01-25 00:13:54 +00:00
Paul 483af57964 Merge remote-tracking branch 'origin/lang-updates' 2026-01-25 10:12:48 +10:00
Dmytro BunnuaandWeblate a941bdddf3 Translated using Weblate (Ukrainian)
Currently translated at 76.9% (6971 of 9061 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/uk/
2026-01-24 18:24:12 +00:00
TeggyandWeblate 246ba4a93b Translated using Weblate (Spanish)
Currently translated at 83.9% (7611 of 9061 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/es/
2026-01-24 18:24:09 +00:00
Paul 3347c084ed More changelog [skip-ci] 2026-01-24 22:42:58 +10:00
Paul 8175cee454 More translations 2026-01-24 22:11:15 +10:00
Paul 37d54053a5 Merge remote-tracking branch 'origin/lang-updates' 2026-01-24 22:10:10 +10:00
Dmytro BunnuaandWeblate b8846bd74c Translated using Weblate (Ukrainian)
Currently translated at 76.8% (6966 of 9061 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/uk/
2026-01-24 11:47:21 +00:00
Paul 1716e135c4 Changelog [skip-ci] 2026-01-24 21:45:14 +10:00
Paul 0ac804cfcb Cleanup 2026-01-24 21:20:50 +10:00
Hiroku aecc132814 Merge branch 'pokeballUIResourcePathChange' into 'main'
ball_icon resource location changes

See merge request cable-mc/cobblemon!2113
2026-01-24 11:13:26 +00:00
Hiroku 8b47876dff Merge branch 'Add-Plaques-to-Village-Pokecenters' into 'main'
Adding Plaques to Village Pokecenters

See merge request cable-mc/cobblemon!2139
2026-01-24 09:27:56 +00:00
Slippy ffc108953a Adding Plaques to Village Pokecenters 2026-01-24 01:51:33 -06:00
Paul 0a106174fe Changelog cleanup [skip-ci] 2026-01-24 15:59:27 +10:00
Paul 90210bee3c Fixed cottonee cries being inconsistent due to not having appropriate pose type coverage 2026-01-24 15:13:08 +10:00
Paul 8603cd4ad0 Merge remote-tracking branch 'origin/main' into Expression-stuffs 2026-01-24 13:56:14 +10:00
Hiroku 7b2c6827c2 Merge branch 'Expression-stuffs' into 'main'
Expression stuffs

See merge request cable-mc/cobblemon!2138
2026-01-24 03:55:02 +00:00
Paul 902b4a6d21 Fixed croagunk and toxicroak playing cry animations without the sound 2026-01-24 13:54:41 +10:00
Hiroku a847cb5926 Merge branch 'fix-plain-aprijuice-prefix' into 'main'
Fix Aprijuice 'Plain' prefix

See merge request cable-mc/cobblemon!2137
2026-01-24 03:46:05 +00:00
Paul 050c6f5adc Merge remote-tracking branch 'origin/Expression-stuffs' into Expression-stuffs 2026-01-24 13:41:23 +10:00
Paul fb95fb3cf7 Various cry corrections from implementation 2026-01-24 13:41:11 +10:00
Carmendar d507367411 Bird stamina changes. 2026-01-23 21:30:43 -06:00
Paul faa19cebcb Fixed perma zero stamina on horses when landing from bird 2026-01-24 13:16:38 +10:00
Paul aced374367 Fixed birds falling out of the sky and not gliding all chill like 2026-01-24 12:40:04 +10:00
Paul d424a6f1d3 Fixed stamina stat flowing to crazy negative from bird sometimes 2026-01-24 11:58:25 +10:00
Carmendar 71bb1c32de stamina expression changes for Bird and Hover. Changes to Mantine riding. 2026-01-23 18:56:17 -06:00
Carmendar f726fcedb9 Merge branch 'main' into implement_pokemon 2026-01-23 18:09:48 -06:00
Weblate 77344ccc2f Update translation files
Updated by "Remove blank strings" add-on in Weblate.

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/
2026-01-23 17:29:44 +00:00
Dmytro BunnuaandWeblate 90bc16be90 Translated using Weblate (Ukrainian)
Currently translated at 76.8% (6960 of 9061 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/uk/
2026-01-23 17:29:37 +00:00
Gustavo PuerariandWeblate d1b743a01f Translated using Weblate (Portuguese (Brazil))
Currently translated at 98.3% (8908 of 9061 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/pt_BR/
2026-01-23 17:29:33 +00:00
TeggyandWeblate aed651c0a0 Translated using Weblate (Spanish)
Currently translated at 83.9% (7608 of 9061 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/es/
2026-01-23 17:29:28 +00:00
Faintful 4c477e1675 Add changelog 2026-01-23 17:36:05 +01:00
Faintful d1cdc6789c Handle case for LOW quality Aprijuice in getName() for proper 'Plain' prefix 2026-01-23 17:33:04 +01:00
Andy 70fe1682b0 remove whitespace in pokesnack block entity 2026-01-23 10:49:24 -05:00
Andy 9058bde326 remove whitespace from changelog 2026-01-23 10:41:52 -05:00
Andy bf425efd40 Merge branch 'feat/snack-spawner-factory' into 'main'
Added PokeSnackSpawnerFactory so influences can be registered to pokesnacks

See merge request ppVon/cobblemon!1
2026-01-23 15:39:21 +00:00
geumuandWeblate cd3127b983 Translated using Weblate (Korean)
Currently translated at 100.0% (9061 of 9061 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/ko/
2026-01-23 13:22:11 +00:00
Watuneni iteiteandWeblate 68f5eff048 Translated using Weblate (Japanese)
Currently translated at 100.0% (9061 of 9061 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/ja/
2026-01-23 13:22:06 +00:00
Andy cebff87656 update changelog 2026-01-23 03:49:09 -05:00
Andy d24fb13877 Add fishing spawner factory to register influences to 2026-01-23 03:47:34 -05:00
Paul c3d2918a2b Fixed a crash when joining a server and a player is riding nearby 2026-01-23 17:49:57 +10:00
Andy 1d82df464a Added PokeSnackSpawnerFactory so influences can be registered to pokesnacks 2026-01-23 02:19:02 -05:00
Paul 0432525c06 Throh resize 2026-01-23 17:04:45 +10:00
Paul a60f27e282 Fixed implemented flag missing from the new 1.7.2 pokemon, subtle size changes 2026-01-23 17:04:14 +10:00
Test 5f0182cb7e fix type asset 2026-01-23 01:48:49 -05:00
Paul 4a3ae9407b Translation changelog [skip-ci] 2026-01-23 16:44:32 +10:00
Paul 766c2838d2 Merge remote-tracking branch 'origin/lang-updates' 2026-01-23 14:34:19 +10:00
Hiroku 4cb95589b4 Merge branch 'more-fixes' into 'main'
More fixes

See merge request cable-mc/cobblemon!2134
2026-01-23 04:30:49 +00:00
Hiroku a8d3c2dd52 Merge branch '1.7.2-spawns' into 'main'
Added spawns. Fixed spawns. Updated tags.

Closes #1896

See merge request cable-mc/cobblemon!2131
2026-01-23 04:13:07 +00:00
Test cb5d7b6ad7 rm unused 2026-01-22 23:05:38 -05:00
Test c7dcc64595 sync repo assets 2026-01-22 23:00:10 -05:00
Paul 6573e08da7 Fix for packet handling to ensure all packets are handled on main and without extra delays on Fabric, closes #1903 2026-01-23 13:37:36 +10:00
Paul cd695ade4a Apparently I put more changelog in than was meant to be there 2026-01-23 13:22:37 +10:00
Paul 55cb413cfc Merge remote-tracking branch 'origin/main' into 1.7.2-spawns 2026-01-23 13:11:50 +10:00
Paul 4f1bf7fcbb Changelog for spawns [skip-ci] 2026-01-23 13:11:42 +10:00
Test 154ee80ead fix some block issues 2026-01-22 21:32:51 -05:00
Test 1c9f9bb198 Merge branch 'main' of https://gitlab.com/cable-mc/cobblemon 2026-01-22 20:38:08 -05:00
Test 6836343f11 ride summary 2026-01-22 20:37:46 -05:00
RedGenesectNinja aa0d1cd943 Updated changelog 2026-01-22 14:44:46 -06:00
Hiroku 798f1da8b3 Merge branch 'main' into 'main'
Issue 1926: Make SpawnBaitInfluence apply all effects correctly

See merge request cable-mc/cobblemon!2130
2026-01-22 13:44:44 +00:00
Andy d98efb52b6 Add changelog line and extend author tag 2026-01-22 08:38:13 -05:00
Polymeta f450d9d2d6 Merge branch 'fix-bucket-reuse' into '1.8.0'
Fixed multi-spawns in a single pass using the same bucket for all of them

See merge request cable-mc/cobblemon!2104
2026-01-22 13:21:39 +00:00
Kenji_64 2f27a03f08 Alolan Raichu can look around in the menu now (yay) 2026-01-22 13:36:19 +01:00
Kenji_64 e33025b1fa Fixed the weird eye clipping on Dragapult (fr this time) 2026-01-22 13:36:00 +01:00
Kenji_64 ade2481f42 Treecko line has their cries back 2026-01-22 13:35:39 +01:00
Paul 0752ab3cac Fixed woopsies in changelog 2026-01-22 22:23:01 +10:00
Hiroku 576e2301ce Merge branch 'open-actor-classes' into 'main'
Mark the actor classes as open so they can be extended.

See merge request cable-mc/cobblemon!2129
2026-01-22 12:19:06 +00:00
Polymeta a568d45d75 [skip-ci] tidy up changelog take two 2026-01-22 09:58:38 +00:00
Hiroku bc19a7e4c1 Merge branch 'decor-split' into 'main'
Decor split

See merge request cable-mc/cobblemon!2127
2026-01-22 09:42:35 +00:00
Polymeta 616e438f17 [skip-ci] tidy up changelog 2026-01-22 09:40:47 +00:00
Polymeta 9bb11c46d5 Merge branch 'implement_pokemon' into 'main'
Implement pokemon

Closes #1921 and #1800

See merge request cable-mc/cobblemon!2063
2026-01-22 09:28:25 +00:00
Carmendar 5f470bb703 Honchkrow and Mantine camera fixes. 2026-01-21 23:25:53 -06:00
Andy 276f13cea5 1926: Re-add affectWeight comment 2026-01-22 00:08:34 -05:00
Andy ac069687f1 1926: Changed SpawnBaitInfluence to apply all bait effects properly in affectWeight 2026-01-22 00:07:14 -05:00
Deltric f248c22eed Fix initialPos being able to change and changelog 2026-01-21 22:54:53 -06:00
RedGenesectNinja 65a5687f92 Fixed Dusknoir's stomach mouth lips glowing while it sleeps 2026-01-21 22:27:11 -06:00
Deltric ea50fa534b Mark the actor classes as open so they can be extended. 2026-01-21 21:35:03 -06:00
RedGenesectNinja 4bd3c4af58 Updated changelog 2026-01-21 21:20:16 -06:00
RedGenesectNinja 283d80f7ed Implemented Croagunk and Toxicroak's animations 2026-01-21 21:19:22 -06:00
Veraxiel 0238ca80f0 Added spawns. Fixed spawns. Updated tags. 2026-01-21 18:53:40 -05:00
RedGenesectNinja d24c5fe874 Fixed a mistake I made with file placement 2026-01-21 15:32:14 -06:00
RedGenesectNinja e65e21f2ff Fixed Chimecho's cry not playing a sound 2026-01-21 15:21:02 -06:00
Carmendar e1d417718f Added Flygon jump and Mantine ride anims with temp ride stats. 2026-01-21 02:25:05 -06:00
Polymeta d4308b0a4f Merge branch 'fix-battle-memory-leak' into 'main'
Fixed memory leak from battles not being cleaned up after ending.

See merge request cable-mc/cobblemon!2075
2026-01-21 08:09:44 +00:00
Konoha 2a1d1e4474 fix: AI constant switching 2026-01-20 21:09:30 -05:00
Test bc0d530484 loisence 2026-01-20 19:19:53 -05:00
Jerzykv 56650418d2 Implemented Throh and Sawk 2026-01-20 20:32:21 +01:00
Jerzykv 0543b84d34 The battle idle should probably play the battle idle animation 2026-01-20 19:57:45 +01:00
Jerzykv 1f50687a59 Re-added Honchkrow's driving license 2026-01-20 19:53:25 +01:00
Polymeta ed04faf0d8 Merge branch 'dispenser-fix' into 'main'
Resolved Dispenser Behaviors not working

See merge request cable-mc/cobblemon!2118
2026-01-20 14:46:55 +00:00
AramandPolymeta 1ed020f3e0 Resolved Dispenser Behaviors not working 2026-01-20 14:46:54 +00:00
Polymeta 7e385d8c94 Merge branch 'default-offest' into 'main'
[FEAT] Add `default_seat` option to seat offset posers

See merge request cable-mc/cobblemon!1999
2026-01-20 14:46:44 +00:00
Polymeta ee509b5438 Merge branch 'molang-inventory-and-move-utility' into 'main'
molang additions: Move struct accessor and player inventory utils

See merge request cable-mc/cobblemon!2103
2026-01-20 14:46:34 +00:00
Jerzykv ac9394131c Implemented Litleo and Pyroar - Changelog 2026-01-20 12:01:09 +01:00
Jerzykv d058a306a7 Implemented Litleo and Pyroar 2026-01-20 11:58:48 +01:00
Jerzykv b9be0c3fcb Swirlix and Slurpuff cry fixes 2026-01-20 10:14:16 +01:00
Jerzykv b59b46568a Swirlix and Slurpuff poser changes 2026-01-20 10:14:11 +01:00
Jerzykv 408cbc8c49 Slurpuff and Aromatisse scale changes 2026-01-20 10:13:55 +01:00
Test 1537816132 log of change 2026-01-20 00:56:36 -05:00
Test 1705639950 loot 2026-01-20 00:50:04 -05:00
Test ce32541dd6 Merge branch 'main' of https://gitlab.com/cable-mc/cobblemon into decor-split 2026-01-19 23:45:28 -05:00
Test 3ffea4f4dd split items 2026-01-19 23:44:20 -05:00
Hiroku fe35a63769 Merge branch 'complex-movesets' into '1.8.0'
Complex movesets, parties, and pools

See merge request cable-mc/cobblemon!2086
2026-01-19 04:09:56 +00:00
Hiroku f942d7c34a Merge branch 'misc-additions-fixes' into 'main'
Couple of misc API additions and bug fixes.

See merge request cable-mc/cobblemon!2125
2026-01-19 02:16:09 +00:00
Deltric 0f1ada4624 Pass in pnx to the event 2026-01-18 18:52:27 -06:00
Deltric b4ee4629bf Couple of misc API additions and bug fixes. 2026-01-18 17:57:28 -06:00
Paul d0b64e2d82 Respect the BYPASSES_INVULNERABILITY damage tag 2026-01-18 22:12:25 +10:00
Jerzykv a8ce3c2175 Fixed Wishiwashi's School Form, Fixes #1921 2026-01-18 12:39:16 +01:00
Jerzykv 80ae127379 Implemented Spritzee and Aromatisse. Smells good. 2026-01-18 12:36:48 +01:00
Jerzykv bd3a9fb3af Implemented Swirlix and Slurpuff. How sweet! 2026-01-18 11:28:15 +01:00
Instrafe d0eaccb81b Fixed Ferroseed and Ferrothorn's posers not identifying a root bone (woops) 2026-01-17 12:12:08 -05:00
Paul 1ed2042283 Fixed /calculateseatpositions expecting no underscore when actually we always use an underscore 2026-01-17 22:32:57 +10:00
Deltric 0b531d967e Merge remote-tracking branch 'origin/fix-battle-memory-leak' into fix-battle-memory-leak
# Conflicts:
#	common/src/main/resources/data/cobblemon/showdown.zip
2026-01-17 03:42:38 -06:00
Deltric b0d1aec9ab Update showdown 2026-01-17 03:42:21 -06:00
Deltric f4d47098b5 Fixed memory leak from battles not being cleaned up after ending. 2026-01-17 03:42:08 -06:00
Instrafe 1989b8aa92 Implemented remodels for Ferroseed and Ferrothorn 2026-01-16 17:06:45 -05:00
Carmendar e290fe9c75 Modified Hover expressions and buffs/nerfs for hover mounts. 2026-01-15 21:23:34 -06:00
Jerzykv 06a50cfeeb Changelog for the cottons 2026-01-15 11:12:17 +01:00
Jerzykv 00888c8ad5 Implemented Cottonee and Whimsicott remodels 2026-01-15 11:11:44 +01:00
RedGenesectNinja 3963e83717 Implemented Ducklett and Swanna's cries with placeholder animations 2026-01-12 01:04:46 -06:00
Konoha 7893e365da yolo: drop item on give_item if inventory is full & sneak in a fix for active_dialogue 2026-01-11 18:50:52 -05:00
Hiroku b6a7051b2c Fixed galarian weezing blink crash, closes #1800 2026-01-11 04:28:37 +00:00
Jerzykv 2cb1cf2f83 tiny fix on Togekiss 2026-01-10 13:36:40 +01:00
阿鱼andWeblate f13a4e0e24 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (9022 of 9022 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/zh_Hans/
2026-01-08 18:45:37 +00:00
Dragonwhisper92 17e1bbd6a1 oops changelog extra '-' removed 2026-01-07 20:00:26 +00:00
Dragonwhisper92 c36ff0a0fe ball_icon resource location changes
Changed the resource location of pokeball icons in the gui to use the balls namespace instead of cobblemon, allowing mods to properly use their own name space for these textures
2026-01-07 19:57:36 +00:00
Jerzykv 8dbb350230 minor fix to apricorn textures 2026-01-05 21:56:02 +01:00
Jerzykv 52f9ffb1f6 fixed Politoed's drop again. thanks scraper 2026-01-05 12:23:07 +01:00
LucasandWeblate 030195e3ff Translated using Weblate (French)
Currently translated at 100.0% (9022 of 9022 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/fr/
2026-01-03 08:52:44 +00:00
YasitoandWeblate d21a52ae68 Translated using Weblate (French)
Currently translated at 100.0% (9022 of 9022 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/fr/
2026-01-03 08:52:43 +00:00
YasitoandWeblate 3c1f1dbacb Translated using Weblate (French (Canada))
Currently translated at 100.0% (9022 of 9022 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/fr_CA/
2026-01-03 08:52:42 +00:00
LucasandWeblate 787c4851ff Translated using Weblate (French)
Currently translated at 99.9% (9021 of 9022 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/fr/
2026-01-02 21:02:21 +00:00
YasitoandWeblate bf6e7fafd3 Translated using Weblate (French)
Currently translated at 99.9% (9021 of 9022 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/fr/
2026-01-02 21:02:20 +00:00
LucasandWeblate ea6df764c0 Translated using Weblate (French)
Currently translated at 99.9% (9020 of 9022 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/fr/
2026-01-02 21:01:41 +00:00
YasitoandWeblate f242de272d Translated using Weblate (French)
Currently translated at 99.9% (9020 of 9022 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/fr/
2026-01-02 21:01:41 +00:00
LucasandWeblate 5232e2e9bc Translated using Weblate (French)
Currently translated at 99.9% (9019 of 9022 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/fr/
2026-01-02 21:01:09 +00:00
YasitoandWeblate ca35898243 Translated using Weblate (French)
Currently translated at 99.9% (9019 of 9022 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/fr/
2026-01-02 21:01:08 +00:00
LucasandWeblate 869457d235 Translated using Weblate (French)
Currently translated at 99.9% (9018 of 9022 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/fr/
2026-01-02 21:00:52 +00:00
YasitoandWeblate 6736c8160b Translated using Weblate (French)
Currently translated at 99.9% (9018 of 9022 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/fr/
2026-01-02 21:00:51 +00:00
LucasandWeblate 243c50550d Translated using Weblate (French)
Currently translated at 99.9% (9017 of 9022 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/fr/
2026-01-02 21:00:37 +00:00
YasitoandWeblate fe7d3ef23a Translated using Weblate (French)
Currently translated at 99.9% (9017 of 9022 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/fr/
2026-01-02 21:00:36 +00:00
LucasandWeblate 57ad77fc39 Translated using Weblate (French)
Currently translated at 99.9% (9016 of 9022 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/fr/
2026-01-02 21:00:10 +00:00
LucasandWeblate d70e7bd1b3 Translated using Weblate (French)
Currently translated at 99.9% (9015 of 9022 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/fr/
2026-01-02 20:59:34 +00:00
YasitoandWeblate 254cc931ea Translated using Weblate (French)
Currently translated at 99.9% (9015 of 9022 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/fr/
2026-01-02 20:59:34 +00:00
LucasandWeblate 01fe5cffe8 Translated using Weblate (French)
Currently translated at 99.9% (9014 of 9022 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/fr/
2026-01-02 20:59:19 +00:00
YasitoandWeblate 3e18995a37 Translated using Weblate (French)
Currently translated at 99.9% (9014 of 9022 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/fr/
2026-01-02 20:59:18 +00:00
YasitoandWeblate ff161c9c9b Translated using Weblate (French)
Currently translated at 99.9% (9013 of 9022 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/fr/
2026-01-02 20:58:36 +00:00
LucasandWeblate 6b7b4f326d Translated using Weblate (French)
Currently translated at 99.9% (9013 of 9022 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/fr/
2026-01-02 20:58:35 +00:00
LucasandWeblate f50f7dec29 Translated using Weblate (French)
Currently translated at 99.8% (9012 of 9022 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/fr/
2026-01-02 20:58:17 +00:00
YasitoandWeblate a5def20c58 Translated using Weblate (French)
Currently translated at 99.8% (9012 of 9022 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/fr/
2026-01-02 20:58:16 +00:00
YasitoandWeblate b23204f9c9 Translated using Weblate (French)
Currently translated at 99.8% (9011 of 9022 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/fr/
2026-01-02 20:57:51 +00:00
LucasandWeblate 4972de0aaa Translated using Weblate (French)
Currently translated at 99.8% (9011 of 9022 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/fr/
2026-01-02 20:57:50 +00:00
LucasandWeblate 58a1f3d7b4 Translated using Weblate (French)
Currently translated at 99.8% (9010 of 9022 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/fr/
2026-01-02 20:57:33 +00:00
YasitoandWeblate f516edb858 Translated using Weblate (French)
Currently translated at 99.8% (9010 of 9022 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/fr/
2026-01-02 20:57:32 +00:00
LucasandWeblate 161aa952fa Translated using Weblate (French)
Currently translated at 99.8% (9008 of 9022 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/fr/
2026-01-02 20:55:43 +00:00
YasitoandWeblate 3b26a13ad6 Translated using Weblate (French)
Currently translated at 99.8% (9008 of 9022 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/fr/
2026-01-02 20:55:43 +00:00
LucasandWeblate 014189217a Translated using Weblate (French)
Currently translated at 99.8% (9007 of 9022 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/fr/
2026-01-02 20:55:29 +00:00
YasitoandWeblate 978debb40c Translated using Weblate (French)
Currently translated at 99.8% (9007 of 9022 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/fr/
2026-01-02 20:55:28 +00:00
LucasandWeblate 5be707811e Translated using Weblate (French)
Currently translated at 99.8% (9006 of 9022 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/fr/
2026-01-02 20:55:13 +00:00
YasitoandWeblate ac44a98f8a Translated using Weblate (French)
Currently translated at 99.8% (9006 of 9022 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/fr/
2026-01-02 20:55:12 +00:00
LucasandWeblate 03ecc2ae8d Translated using Weblate (French)
Currently translated at 99.8% (9005 of 9022 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/fr/
2026-01-02 20:54:13 +00:00
YasitoandWeblate 1518379107 Translated using Weblate (French)
Currently translated at 99.8% (9005 of 9022 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/fr/
2026-01-02 20:54:12 +00:00
YasitoandWeblate a58c8c59e1 Translated using Weblate (French)
Currently translated at 99.8% (9004 of 9022 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/fr/
2026-01-02 20:53:58 +00:00
LucasandWeblate 37959b5048 Translated using Weblate (French)
Currently translated at 99.8% (9004 of 9022 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/fr/
2026-01-02 20:53:58 +00:00
YasitoandWeblate cbcc9fc6f1 Translated using Weblate (French (Canada))
Currently translated at 99.7% (9002 of 9022 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/fr_CA/
2026-01-02 20:53:57 +00:00
YasitoandWeblate d236aaa7da Translated using Weblate (French)
Currently translated at 99.7% (9000 of 9022 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/fr/
2026-01-02 20:50:35 +00:00
LucasandWeblate a2cd5a671c Translated using Weblate (French)
Currently translated at 99.7% (9000 of 9022 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/fr/
2026-01-02 20:50:35 +00:00
LucasandWeblate 1d6a45bf4d Translated using Weblate (French)
Currently translated at 99.7% (8998 of 9022 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/fr/
2026-01-02 20:49:59 +00:00
YasitoandWeblate 5bfe703ed7 Translated using Weblate (French)
Currently translated at 99.7% (8998 of 9022 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/fr/
2026-01-02 20:49:58 +00:00
YasitoandWeblate fc8485388e Translated using Weblate (French)
Currently translated at 99.7% (8997 of 9022 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/fr/
2026-01-02 20:45:38 +00:00
LucasandWeblate a5593b3131 Translated using Weblate (French)
Currently translated at 99.7% (8997 of 9022 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/fr/
2026-01-02 20:45:38 +00:00
YasitoandWeblate 9541bf3267 Translated using Weblate (French (Canada))
Currently translated at 99.6% (8991 of 9022 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/fr_CA/
2026-01-02 20:45:37 +00:00
LucasandWeblate 1037fe0a0e Translated using Weblate (French)
Currently translated at 99.6% (8989 of 9022 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/fr/
2026-01-02 20:38:19 +00:00
YasitoandWeblate a6eea3198a Translated using Weblate (French)
Currently translated at 99.6% (8989 of 9022 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/fr/
2026-01-02 20:38:19 +00:00
YasitoandWeblate b28e2313a8 Translated using Weblate (French (Canada))
Currently translated at 99.6% (8988 of 9022 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/fr_CA/
2026-01-02 20:38:19 +00:00
LucasandWeblate 0f0b4e6c86 Translated using Weblate (French)
Currently translated at 99.6% (8988 of 9022 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/fr/
2026-01-02 20:37:45 +00:00
YasitoandWeblate e033467054 Translated using Weblate (French)
Currently translated at 99.6% (8988 of 9022 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/fr/
2026-01-02 20:37:45 +00:00
YasitoandWeblate 0f092bf6bf Translated using Weblate (French (Canada))
Currently translated at 99.6% (8987 of 9022 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/fr_CA/
2026-01-02 20:37:44 +00:00
LucasandWeblate 66ba762360 Translated using Weblate (French)
Currently translated at 99.6% (8987 of 9022 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/fr/
2026-01-02 20:37:01 +00:00
YasitoandWeblate c7c11838a0 Translated using Weblate (French)
Currently translated at 99.6% (8987 of 9022 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/fr/
2026-01-02 20:37:01 +00:00
YasitoandWeblate 301d80fabe Translated using Weblate (French (Canada))
Currently translated at 99.6% (8986 of 9022 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/fr_CA/
2026-01-02 20:37:00 +00:00
Paul 95d238ada0 Fixed multi-spawns in a single pass using the same bucket for all of them 2026-01-02 22:38:46 +10:00
Konoha fade5502d9 molang additions: Move struct accessor and player inventory utils 2026-01-01 15:31:40 -05:00
Test fc720916fb wall block properties 2025-12-31 00:24:39 -05:00
Jerzykv ce55035408 changelog 2025-12-30 14:46:38 +01:00
Jerzykv d4665ddaeb implemented Falinks remodel 2025-12-30 14:44:46 +01:00
Jerzykv 4375c6f667 fixed Revavroom's hitbox. Who implemented this guy (it was me) 2025-12-30 14:43:24 +01:00
Test e5699c1cdc plaques, policies 2025-12-22 01:34:10 -05:00
RedGenesectNinja f4a7c6e873 Implemented the remodels for Chingling and Chimecho 2025-12-21 22:40:17 -06:00
geumuandWeblate 3bef1dad4a Translated using Weblate (Korean)
Currently translated at 100.0% (9022 of 9022 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/ko/
2025-12-20 19:34:20 +00:00
geumuandWeblate da50ee59cf Translated using Weblate (Korean)
Currently translated at 100.0% (9022 of 9022 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/ko/
2025-12-20 14:40:56 +00:00
arvid6andWeblate 6e8985d97e Translated using Weblate (Spanish)
Currently translated at 84.2% (7599 of 9022 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/es/
2025-12-19 08:15:16 +00:00
geumuandWeblate 19c4c0d50d Translated using Weblate (Korean)
Currently translated at 100.0% (9022 of 9022 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/ko/
2025-12-19 08:15:15 +00:00
阿鱼andWeblate b23110950e Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (9022 of 9022 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/zh_Hans/
2025-12-19 08:15:14 +00:00
Watuneni iteiteandWeblate 60c213c44b Translated using Weblate (Japanese)
Currently translated at 100.0% (9022 of 9022 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/ja/
2025-12-19 08:15:13 +00:00
geumuandWeblate 3df8dea71b Translated using Weblate (Korean)
Currently translated at 100.0% (9022 of 9022 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/ko/
2025-12-18 17:09:19 +00:00
geumuandWeblate 3cca50b7cc Translated using Weblate (Korean)
Currently translated at 100.0% (9022 of 9022 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/ko/
2025-12-18 07:49:53 +00:00
geumuandWeblate 1ff5622694 Translated using Weblate (Korean)
Currently translated at 100.0% (9022 of 9022 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/ko/
2025-12-18 06:01:40 +00:00
Alexis SalgueiroandWeblate 411f388bd3 Translated using Weblate (French)
Currently translated at 99.5% (8984 of 9022 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/fr/
2025-12-18 00:21:32 +00:00
geumuandWeblate 5b8d35604a Translated using Weblate (Korean)
Currently translated at 100.0% (9022 of 9022 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/ko/
2025-12-18 00:21:30 +00:00
geumuandWeblate 619d002bc4 Translated using Weblate (Korean)
Currently translated at 100.0% (9022 of 9022 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/ko/
2025-12-17 07:19:25 +00:00
geumuandWeblate 7049656f64 Translated using Weblate (Korean)
Currently translated at 100.0% (9022 of 9022 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/ko/
2025-12-16 06:33:05 +00:00
geumuandWeblate e6e7c2982d Translated using Weblate (Korean)
Currently translated at 100.0% (9022 of 9022 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/ko/
2025-12-15 12:47:01 +00:00
Paul aafdb7688a Added more molang expressions to a bunch of composed pool properties, fixed some bugs 2025-12-15 14:22:59 +10:00
Paul 73b53f9702 Added egg move selector 2025-12-15 12:07:06 +10:00
Paul 33317a57c7 more doco changes [skip-ci] 2025-12-14 20:33:34 +10:00
Paul 72d8f26cdb Change silly default example weight to the actual default weight 2025-12-14 20:27:30 +10:00
Paul aea1afe145 Rearrange doco 2025-12-14 20:26:21 +10:00
Paul 0fec45b7ea Added npcAspects condition for party pool entries 2025-12-14 20:24:52 +10:00
Paul af98b823aa Documentation 2025-12-14 20:13:04 +10:00
Paul 07d9da2ca9 Added last_suitable_offensive move selector, added alpha moveset builder 2025-12-14 17:29:47 +10:00
Paul c2c86b2ef1 Stack all the cobblemon:move_weights.json from any datapacks onto one big map, like tags 2025-12-14 17:05:58 +10:00
Watuneni iteiteandWeblate 82686b0511 Translated using Weblate (Japanese)
Currently translated at 99.4% (8976 of 9022 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/ja/
2025-12-12 03:20:38 +00:00
JPAKx4 f4eca30163 Fix merge issues 2025-12-11 10:40:53 -06:00
arvid6andWeblate 2814183012 Translated using Weblate (Spanish)
Currently translated at 84.2% (7597 of 9022 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/es/
2025-12-11 16:38:11 +00:00
JPAKx4 bbc3c2a8d6 Merge branch 'main' into default-offest
# Conflicts:
#	common/src/main/kotlin/com/cobblemon/mod/common/client/render/camera/MountedCameraRenderer.kt
2025-12-11 10:27:50 -06:00
geumuandWeblate 7eeb7feeae Translated using Weblate (Korean)
Currently translated at 100.0% (9022 of 9022 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/ko/
2025-12-11 06:27:41 +00:00
geumuandWeblate b2f850c1c8 Translated using Weblate (Korean)
Currently translated at 100.0% (9022 of 9022 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/ko/
2025-12-10 15:57:39 +00:00
Nico MerenqandWeblate 23db346070 Translated using Weblate (Russian)
Currently translated at 77.7% (7012 of 9022 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/ru/
2025-12-09 19:49:13 +00:00
geumuandWeblate d3b7d739bb Translated using Weblate (Korean)
Currently translated at 100.0% (9022 of 9022 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/ko/
2025-12-09 19:49:11 +00:00
geumuandWeblate eb6c134f4b Translated using Weblate (Korean)
Currently translated at 100.0% (9022 of 9022 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/ko/
2025-12-08 10:48:16 +00:00
Paul 22733e7117 Added more advanced moveset and party construction for NPCs 2025-12-08 19:31:48 +10:00
geumuandWeblate aa0b8d88e8 Translated using Weblate (Korean)
Currently translated at 100.0% (9022 of 9022 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/ko/
2025-12-07 12:09:09 +00:00
Deltric 3cf9425247 Fixed memory leak from battles not being cleaned up after ending. 2025-12-06 01:35:53 -06:00
Carmendar b5578e72bd Merge branch 'main' into implement_pokemon 2025-12-05 01:30:51 -06:00
Carmendar 3aea0909a4 Merge branch 'main' into implement_pokemon 2025-12-05 01:27:25 -06:00
TeggyandWeblate 5adef3336e Translated using Weblate (Spanish)
Currently translated at 84.2% (7597 of 9022 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/es/
2025-12-05 06:23:53 +00:00
geumuandWeblate 1a96b418bc Translated using Weblate (Korean)
Currently translated at 100.0% (9022 of 9022 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/ko/
2025-12-05 06:23:51 +00:00
geumuandWeblate e373e86b60 Translated using Weblate (Korean)
Currently translated at 100.0% (9022 of 9022 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/ko/
2025-12-04 15:33:38 +00:00
geumuandWeblate 6f3035184c Translated using Weblate (Korean)
Currently translated at 100.0% (9022 of 9022 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/ko/
2025-12-04 09:30:13 +00:00
Jerzykv 7ae8b1957c fixed Arcanine's texture having a line 2025-12-04 10:27:42 +01:00
geumuandWeblate 824b9718ee Translated using Weblate (Korean)
Currently translated at 100.0% (9022 of 9022 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/ko/
2025-12-04 08:07:32 +00:00
geumuandWeblate ef43f6c087 Translated using Weblate (Korean)
Currently translated at 100.0% (9022 of 9022 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/ko/
2025-12-03 21:23:55 +00:00
geumuandWeblate c8a70caf79 Translated using Weblate (Korean)
Currently translated at 100.0% (9022 of 9022 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/ko/
2025-12-03 16:30:22 +00:00
geumuandWeblate ba11758e1f Translated using Weblate (Korean)
Currently translated at 100.0% (9022 of 9022 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/ko/
2025-12-03 12:53:16 +00:00
geumuandWeblate f0412d6b1d Translated using Weblate (Korean)
Currently translated at 100.0% (9022 of 9022 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/ko/
2025-12-03 10:05:08 +00:00
Jerzykv f5f87ce1a3 fixed Dewgong swimming in battle 2025-12-03 06:57:40 +01:00
Jerzykv f28b269734 fixed Camerupt jumping in battle 2025-12-03 06:57:31 +01:00
Jerzykv d545efd843 adjusted Tinkaton & Tinkatuff profile scaling 2025-12-03 06:57:07 +01:00
Zack the GhastandWeblate f8682c2123 Translated using Weblate (Portuguese (Brazil))
Currently translated at 98.2% (8866 of 9022 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/pt_BR/
2025-12-02 05:47:12 +00:00
geumuandWeblate f62e31a1eb Translated using Weblate (Korean)
Currently translated at 100.0% (9022 of 9022 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/ko/
2025-12-02 05:46:50 +00:00
Watuneni iteiteandWeblate ea623b08a6 Translated using Weblate (Japanese)
Currently translated at 99.4% (8971 of 9022 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/ja/
2025-12-02 05:46:48 +00:00
geumuandWeblate ce3d5a413c Translated using Weblate (Korean)
Currently translated at 95.8% (8650 of 9022 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/ko/
2025-12-01 13:03:30 +00:00
geumuandWeblate d23fd6e23c Translated using Weblate (Korean)
Currently translated at 84.1% (7595 of 9022 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/ko/
2025-12-01 05:33:07 +00:00
geumuandWeblate 59395a254d Translated using Weblate (Korean)
Currently translated at 81.2% (7328 of 9022 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/ko/
2025-11-30 20:59:27 +00:00
geumuandWeblate 5d7c6c8d6f Translated using Weblate (Korean)
Currently translated at 80.6% (7276 of 9022 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/ko/
2025-11-30 08:10:30 +00:00
violet 6529293d21 Merge remote-tracking branch 'origin/implement_pokemon' into implement_pokemon 2025-11-29 02:44:47 -05:00
violet a1fce624ea something was forgotten in the changelog... 2025-11-29 02:44:34 -05:00
geumuandWeblate b7773f7471 Translated using Weblate (Korean)
Currently translated at 79.1% (7144 of 9022 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/ko/
2025-11-28 23:27:54 +00:00
geumuandWeblate f927e47bfe Translated using Weblate (Korean)
Currently translated at 77.9% (7030 of 9022 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/ko/
2025-11-28 15:25:08 +00:00
Watuneni iteiteandWeblate 48a37b2018 Translated using Weblate (Japanese)
Currently translated at 99.2% (8953 of 9022 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/ja/
2025-11-28 15:25:07 +00:00
阿鱼andWeblate f6b2da6ed6 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (9022 of 9022 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/zh_Hans/
2025-11-27 11:09:47 +00:00
Watuneni iteiteandWeblate 275779b20e Translated using Weblate (Japanese)
Currently translated at 99.2% (8953 of 9022 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/ja/
2025-11-26 22:24:14 +00:00
阿鱼andWeblate 2102f8ff88 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 99.6% (8991 of 9022 strings)

Translation: Cobblemon/Mod
Translate-URL: http://lang.cobblemon.com/projects/cobblemon/mod/zh_Hans/
2025-11-26 15:42:52 +00:00
JPAKx4 8f462aab40 Add default_seat option to seat offset posers, and remove shouldRotate as it's not needed for positioning the camera. 2025-11-18 00:56:40 -06:00
1403 changed files with 62905 additions and 9616 deletions
+20
View File
@@ -0,0 +1,20 @@
# Changelog
## [1.8.0 (MONTH Xth, 2026)](#1-8-0)
### Additions
- Added a new `cobblemon:structure`, which is a feature without any restrictions allowing the Builders to place certain structures in much more specific manner.
### Changes
### Fixes
- Fixed rare Pokémon being far too likely to spawn multiple times in a single spawn cycle. The dev told me that the exact bug is too complicated to explain.
### Developer
- Tweaked the spawning selector interface to take a bucket function rather than a bucket directly.
### Molang & Datapacks
### Particles
### Localization
- Updated translations for:
+16
View File
@@ -0,0 +1,16 @@
### Additions
### Changes
- Wild Pokémon now reliably have at least one offensive move, if they can have offensive moves at that level.
### Fixes
### Developer
### Molang & Datapacks
- Added `moveset_builders` datapack folder for different styles of movesets.
- Added `party_pools` datapack folder for defining groups of Pokémon for the purposes of complex NPC party definitions.
- Added `party_compositions` datapack folder for arranging parties on NPCs that rely on party pools.
- Added `composed_pool` NPC party provider type which combines a party pool with a party composition to create more complex NPC parties.
### Particles
+37 -64
View File
@@ -1,78 +1,51 @@
# Changelog
## [1.7.2 (MONTH Xth, YEAR)](#1-7-2)
## [1.7.4 (MONTH Xth, 2026)](#1-7-4)
### Additions
- Added riding statistics: `Distance by Pokémon on Land`, `Distance by Pokémon in Air` and `Distance by Pokémon in Liquid`.
- Added the Partner Mark, which party Pokémon have a very small chance to earn as the player walks, provided they have enough friendship.
- Added trades for Saccharine Saplings, Hearty Grains, Chipped Pot, and Masterpiece Teacup to the Wandering Trader.
- Added brewing recipe for Throat Spray.
- Added new effects
- Mental Restoration: Reduces "Time Since Last Rest" statistic, which controls Insomnia, by half a minute per second per effect level
- Negative Effect Cleanse: Removes all negative effects
- Effect Cleanse: Removes all effects
- Added more seasonings for sinister tea
- Mental Herb - Mental Restoration I for 10 seconds
- White Herb - Negative Effect Cleanse
- Milk - Effect Cleanse
- Moomoo Milk - Effect Cleanse
- Added `label` as an alternate key to the `tag` property.
- Added Saccharine wood furniture for Adorn.
- Party Overlay Exp Gained Animation will now display the amount of EXP the Pokémon gained
- Added a toast to notify players of how they can scroll through their party. Did you know you can hold R and scroll instead of using arrow keys??!
- Added new layer property that makes a layer scroll in a direction. "scrolling": {"speedU": 0.1, "speedV": 0.1}
- Added missing crops to Botany Pots integration
### New rideable Pokémon
### Pokémon Added
### Model updates for the following Pokémon
### Animation updates for the following Pokémon
### Changes
- Ride sounds have been separated into stereo for passengers and mono for other players. Riding will now sound more spacious.
- Added a new config option, `Enable In-Flight Dismounting` (default: off), which lets you dismount while riding a Pokémon in the air.
- Battle AI now uses a smarter threshold for switching, reducing unnecessary switches.
- AI will always use the most damaging move when at low HP and when it is not switching, improving endgame decision-making.
- Added support for optional message variants in battle activate instructions for more context-specific battle text.
- Example: `this.add('-activate', pokemon, 'ability: example', '[msg]message1');` will parse to lang key `cobblemon.battle.activate.example.message1`
- Restructured Botany Pots integration folder structure
- Decrease default pastured mon wander radius to 32.
- Factor in the weight of pokemon when calculating pushing forces between hitboxes.
- Remade the Starter Selection Screen with new assets
- Refactored berry trees to be less impactful on TPS (more performant)
### Fixes
- Fixed an issue in the OmniPathNodeMaker/Navigation that prevented Combees from pathing into and out of Saccharine leaves.
- Fixed orientation not getting reset after crashing while flying and getting back on the Pokémon.
- Fixed Furfrou not being trimmable on NeoForge.
- Fixed shiny Pokémon not respecting the silent flag on spawn.
- Fixed honey from Saccharine Leaves being harvestable at less than the max age.
- Items given from interacting with Saccharine Leaves are placed in the active hotbar slot if possible.
- Fix all Pokémon being saved to chunks and never despawning.
- Fixed possible error on world generation when Combees are placed in naturally generated bee nests.
- Fixed PokeSnacks crashing if there was no available spawn.
- Fixed Pokémon spawn influences not being specific to regional forms
- Fixed crashing when viewing another player in spectator mode
- Fixed missing apricorn textures for Adorn blocks
- Fixed crashing when riding due to malformed json file, instead resetting it
- Fixed mochi items consuming two items at a time
- Fix item interaction sometimes not working properly when playing on servers.
- Fixed Soothe Bell not being properly tagged as a held item.
- Fixed Mint Leaves not being usable for filling the Resurrection Machine.
- Added Saccharine Boats and Saccharine Boat with Chests to relevant boat tags.
- Fixed the `run_script` Molang function to not fail if the environment's context is null.
- Fixed issue #1917
- Fixed the movesets of certain Pokémon being incorrectly sanitized upon reload.
- Fixed the ordering of Aprijuice's riding stat boosts to always have the same order.
- Fixed the Molang functions `date_local_time`, `date_of`, `date_is_after` to use the correct date format.
- Fixed the bottom half of pasture blocks having an incorrect hit-box when facing north or south.
- Fixed Galarian Mr. Mime incorrectly being rideable.
- Fixed gimmicks not being usable in double / triple battles
- Fixed gimmick buttons showing when already used in the same turn in double / triple battles
- Fixed Apricorn block model rotation for counters/sinks/cupboards/drawers to match that of most recent version of Adorn.
- Fixed Fresh Start Mochi EV reset not syncing health changes properly.
- Fixed requirements such as `biomeCondition` crashing the game when used to define Pokémon interactions.
- Fixed Pokémon interactions not playing sound effects when the volume was not specified.
- Fixed Pokémon interaction cooldowns taking longer than intended when the Pokémon was in the player’s party.
- Fixed Pokémon interactions occasionally crashing the game when spamming an interaction with a 0 cooldown.
- Fixed Pokémon fullness decreasing more than intended when the Pokémon was pastured.
- Fixed crashing when sending a Pokémon out after editing its form
- Fixed Super Potion recipes incorrectly using Hondew Berry instead of Aguav Berry.
- Fixes https://gitlab.com/cable-mc/cobblemon/-/issues/1943
- Fix occasional crash on retrieving revived fossils
- Fixed a compatibility issue with World Game Rules which caused some log spam in specific cases.
- Fixed improper validation of Pokémon when performing a trade.
- Fixed issue where particle like beam can disappear when you don't see the beginning of the beam or you look away
- Fixes https://gitlab.com/cable-mc/cobblemon/-/issues/1943
- Fix occasional crash on retrieving revived fossils
- Fix brushing not working on Neoforge
- [Various Submarine Ride Fixes](https://gitlab.com/cable-mc/cobblemon/-/merge_requests/2157)
- Fix Pastured mons despawning and running away.
- Fix Apricorn trees crashing when other mods bonemeal it
- [Various UFO Ride Improvements](https://gitlab.com/cable-mc/cobblemon/-/merge_requests/2156)
- Fixed NeoForge brewing stand unexpectedly crashing users when shift clicking items within it's menu
- Fixed NPCs switching pokemon very often during battles
### Developer
- Changed the `owner` parameter in the `OwnerQueryRequirement` interface from `ServerPlayer` to `Player`. This method is now also called on the client to verify whether a Pokémon interaction succeeded, so make sure to update your implementations to handle both server and client contexts.
- Added `PokeSnackSpawnerFactory` which allows influence registration on PokeSnack encounters
- Added `FishingSpawnerFactory` which allows influence registration on fishing encounters
### Molang & Datapacks
- Ride sounds can now be set as exclusive to passengers
- Ride sounds no longer play when submerged unless specified with a new setting
- Exception handling has been added to `run_molang`, resolving some crashes caused by malformed MoLang expressions.
### Particles
- q.item.is_enchanted()
- q.item.has_enchantment(minecraft:sharpness, 3)
- Added `has_chosen_starter` & `get_starter_uuid` as available Molang functions
### Localization
- Updated translations for:
+137
View File
@@ -0,0 +1,137 @@
# Changelog
## [1.7.2 (January 25th, 2026)](#1-7-2)
### Additions
- Added Saccharine wood furniture for Adorn.
- Added the Partner Mark, which party Pokémon have a very small chance to earn as the player walks, provided they have enough friendship.
- Added decorative block models for existing items: Potion, Super Potion, Hyper Potion, Max Potion, Full Restore, Antidote, Awakening, Burn Heal, Ice Heal, Paralyze Heal, Full Heal, Ether, Elixir, Max Ether, Max Elixir, X Accuracy, X Attack, X Defence, X Special Attack, X Special Defence, X Speed, Dire Hit, Guard Spec, Weakness Policy, Blunder Policy, Cleanse Tag, and Spell Tag.
- Added decorative sign blocks called Plaques.
- Added ride style labels to ride stats in Pokédex, as well as ride style icons in the summary GUI.
- Added more seasonings for sinister tea:
- Mental Herb - Mental Restoration I for 10 seconds, which staves off Insomnia.
- White Herb - Removes negative effects.
- Milk, Moomoo Milk - Removes effects.
- Added dispenser support for:
- Applying a Honey Bottle to Saccharine Logs.
- Washing honey off of Saccharine Slathered Logs.
- Applying and removing honey on Saccharine Leaves.
- Added riding statistics: `Distance by Pokémon on Land`, `Distance by Pokémon in Air` and `Distance by Pokémon in Liquid`.
### New rideable Pokémon
- Honchkrow
- Mantine
### Pokémon Added
#### Gen 5
- Throh
- Sawk
#### Gen 6
- Litleo
- Pyroar
- Spritzee
- Aromatisse
- Swirlix
- Slurpuff
### Model updates for the following Pokémon
- Falinks
- Cottonee
- Whimsicott
- Ferroseed
- Ferrothorn
- Chingling
- Chimecho
### Animation updates for the following Pokémon
- Mantine (ride animations)
- Flygon (ride jump animation)
- Honchkrow (ride animations)
- Croagunk
- Toxicroak
### Changes
- Added a new config option, `Enable In-Flight Dismounting` (default: off), which lets you dismount while riding a Pokémon in the air. This is the textbook definition of caveat emptor.
- Ride sounds have been separated into stereo for passengers and mono for other players. Riding will now sound more spacious.
- Battle AI now uses a smarter threshold for switching, reducing unnecessary switches.
- AI will always use the most damaging move when at low HP and when it is not switching, improving endgame decision-making.
- Items given from interacting with Saccharine Leaves are placed in the active hotbar slot if possible.
- Added `label` as an alternate key to the `tag` property.
### Fixes
- Fixed crashing when viewing another player in spectator mode. Some said this was reason to release this update a month ago. They were probably right.
- Fixed crashing when sending a Pokémon out after editing its form.
- Fixed all Pokémon being saved to chunks and never despawning even when they should be.
- Fixed Poké Snacks crashing if there was no available spawn.
- Fixed Poké Snack / Bait effects so that EV Yield, Type, and Egg Group filters now all apply together when weighting spawns. And you thought you were going crazy.
- Fixed Furfrou not being trimmable on NeoForge specifically.
- Fixed honey from Saccharine Leaves being harvestable at less than the max age.
- Fixed possible error on world generation when Combee are placed in naturally generated bee nests.
- Fixed Galarian Weezing crashing the world if it decides to blink the wrong way. The same could happen to you!
- Fixed Galarian Mr. Mime incorrectly being rideable. Some would argue that regular Mr. Mime shouldn't be rideable, but that would make them wrong.
- Fixed missing apricorn textures for Adorn blocks.
- Fixed Apricorn block model rotation for counters/sinks/cupboards/drawers to match that of most recent version of Adorn.
- Fixed item interaction sometimes not working properly when playing on servers.
- Fixed Mint Leaves not being usable for filling the Resurrection Machine.
- Fixed Super Potion recipes incorrectly using Hondew Berry instead of Aguav Berry. They look similar, to be fair.
- Fixed Wishiwashi not schooling properly.
- Fixed battle item duplication issue. How did it work? Wouldn't you like to know, weather boy.
- Fixed the ordering of Aprijuice's riding stat boosts so they always have the same order.
- Fixed the movesets of certain Pokémon being incorrectly sanitized upon reload, causing some forms to keep losing moves.
- Fixed selected leading Pokémon in battle not being used when levels are set.
- Fixed the bottom half of pasture blocks having an incorrect hit-box when facing north or south.
- Fixed gimmicks not being usable in double and triple battles.
- Fixed gimmick buttons showing when already used in the same turn in double and triple battles.
- Fixed mochi items consuming two items at a time.
- Fixed Fresh Start Mochi's EV reset not syncing health changes properly.
- Fixed Pokémon spawn influences not being specific to regional forms.
- Fixed memory leak from battles not being cleaned up after ending.
- Fixed orientation not getting reset after crashing while flying and getting back on the Pokémon.
- Fixed shiny Pokémon not respecting the `silent` flag on spawn.
- Fixed 'Plain' prefix not being applied to all low-quality Aprijuice.
- Fixed Pokémon interactions not playing sound effects when the volume was not specified.
- Fixed Pokémon interaction cooldowns taking longer than intended when the Pokémon was in the player’s party.
- Fixed Pokémon interactions occasionally crashing the game when spamming an interaction with a 0 cooldown.
- Fixed Pokémon fullness decreasing more than intended when the Pokémon was pastured.
- Fixed Scraggy line, Milcery line, and Morpeko spawning on unnatural blocks.
- Fixed invulnerability-bypassed damage being resisted by invulnerable NPC entities.
- Fixed Fabric network packets not being handled immediately, fixing incompatibilities with Supplementaries, Prometheus, Sleep Tight, and others.
- Fixed killer not being set early enough on a wild Pokémon entity from `WinInstruction`.
- Fixed requirements such as `biomeCondition` crashing the game when used to define Pokémon interactions.
- Fixed an issue that prevented registering custom dispenser behaviours (no longer overrides vanilla behaviour).
- Fixed an issue navigation that prevented Combee from pathing into and out of Saccharine Leaves.
- Added Saccharine Boats and Saccharine Boat with Chests to relevant boat tags.
- Fixed Soothe Bell not being properly tagged as a held item.
- Fixed `/calculateseatpositions` expecting a locator format that even we don't use. It needs an underscore after "seat".
- Fixed the `run_script` Molang function to not fail if the environment's context is null.
- Fixed the Molang functions `date_local_time`, `date_of`, `date_is_after` to use the correct date format.
### Developer
- Changed the `owner` parameter in the `OwnerQueryRequirement` interface from `ServerPlayer` to `Player`. This method is now also called on the client to verify whether a Pokémon interaction succeeded, so make sure to update your implementations to handle both server and client contexts.
- Added the `pnx` to the `BattleFaintedEvent` and `FormeChangeEvent`.
- Added register methods for custom instructions to `ShowdownInterpreter`.
- Changed callback operations in `BattlePokemon` to allow multiple callbacks and be mutable.
- Added `display_name`, `description`, and `max_pp` functions to the `MoveTemplate` struct.
- Changed the implementations of `AIBattleActor` to be open classes to allow extension.
- Changed the resource location of Poké Ball icons in the GUI to use the balls namespace instead of Cobblemon's, allowing mods to properly use their own namespace for these textures.
### Molang & Datapacks
- Ride sounds can now be set as exclusive to passengers.
- Ride sounds no longer play when submerged unless specified with a new setting.
- Exception handling has been added to `run_molang`, resolving some crashes caused by malformed MoLang expressions.
- Added the `create_itemstack`, `has_inventory_space`, `set_inventory_slot`, and `give_item` MoLang functions for item and inventory utility.
- Added the `get_move_from_id` MoLang function for general move info queries without requiring a Moveset object to access.
- Added support for optional message variants in battle activate instructions for more context-specific battle text.
- Example: `this.add('-activate', pokemon, 'ability: example', '[msg]message1');` will parse to lang key `cobblemon.battle.activate.example.message1`.
### Localization
- Updated translations for:
- French
- Canadian French
- Simplified Chinese
- Ukrainian
- Brazilian Portuguese
- Spanish
- Korean
- Japanese
+22
View File
@@ -0,0 +1,22 @@
# Changelog
## [1.7.3 (January 31st, 2026)](#1-7-3)
### Fixes
- Fixed mounted Pokémon not playing sounds.
- Fixed players failing to join servers randomly.
- Fixed some Pokémon having no stamina for flying.
- Fixed `/pctake` not respecting the actual size of the PC.
### Developer
- Poké Ball GUI textures now respect the ball's namespace, enabling proper texture loading for custom balls from other mods.
### Molang & Datapacks
- Added a `chance` requirement type for Pokémon interactions.
### Localization
- Updated translations for:
- French
- Canadian French
- Korean
- Portuguese
- Simplified Chinese
- Spanish
@@ -15,6 +15,8 @@ import com.cobblemon.mod.common.api.events.CobblemonEvents;
import com.cobblemon.mod.common.api.events.item.LeftoversCreatedEvent;
import com.cobblemon.mod.common.api.orientation.OrientationController;
import com.cobblemon.mod.common.api.pokemon.PokemonSpecies;
import com.cobblemon.mod.common.api.riding.RidingStyle;
import com.cobblemon.mod.common.api.riding.behaviour.types.air.HoverBehaviour;
import com.cobblemon.mod.common.api.storage.party.PartyStore;
import com.cobblemon.mod.common.api.storage.party.PlayerPartyStore;
import com.cobblemon.mod.common.api.tags.CobblemonItemTags;
@@ -59,6 +61,7 @@ import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@@ -169,6 +172,32 @@ public abstract class PlayerMixin extends LivingEntity implements ScannableEntit
}
}
@Redirect(
method = "getDestroySpeed",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/world/entity/player/Player;onGround()Z"
)
)
private boolean cobblemon$considerHoverOnGround(Player player) {
// If riding a Hover Mount, return true to bypass the 5x slowdown
if (player.getVehicle() instanceof PokemonEntity vehicle) {
var ridingController = vehicle.getRidingController();
if (ridingController == null) player.onGround();
var activeContext = ridingController.getContext();
if (activeContext == null) player.onGround();
if (activeContext.getStyle() == RidingStyle.AIR &&
activeContext.getBehaviour().equals(HoverBehaviour.Companion.getKEY())) {
return true;
}
}
// Otherwise, return the actual value
return player.onGround();
}
@Inject(
method = "eat",
at = @At(
@@ -33,7 +33,7 @@ public class SimpleBlockFeatureMixin {
if (!(blockState.getBlock() instanceof HeartyGrainsBlock)) {
return;
}
if (blockState.getValue(HeartyGrainsBlock.AGE) <= HeartyGrainsBlock.AGE_AFTER_HARVEST) {
if (blockState.getValue(HeartyGrainsBlock.Companion.getAGE()) <= HeartyGrainsBlock.AGE_AFTER_HARVEST) {
return; //block is too young to be double
}
if (!worldGenLevel.isEmptyBlock(blockPos.above())) {
@@ -43,4 +43,4 @@ public class SimpleBlockFeatureMixin {
DoublePlantBlock.placeAt(worldGenLevel, blockState, blockPos, Block.UPDATE_CLIENTS);
cir.setReturnValue(true);
}
}
}
@@ -0,0 +1,26 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.mixin.accessor;
import net.minecraft.world.item.Item;
import net.minecraft.core.dispenser.DispenseItemBehavior;
import net.minecraft.world.level.block.DispenserBlock;
import java.util.Map;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
@Mixin(DispenserBlock.class)
public interface DispenserBlockAccessor {
@Accessor("DISPENSER_REGISTRY")
static Map<Item, DispenseItemBehavior> getItemBehaviors() {
throw new AssertionError();
}
}
@@ -35,6 +35,7 @@ import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import com.cobblemon.mod.common.client.gui.party.PartyTutorialToasts;
import static com.google.common.primitives.Floats.min;
import static net.minecraft.util.Mth.lerp;
@@ -85,11 +86,13 @@ public abstract class MouseHandlerMixin {
CobblemonClient.INSTANCE.getStorage().shiftSelected(false);
ci.cancel();
PartySendBinding.INSTANCE.actioned();
PartyTutorialToasts.INSTANCE.onHoldKeyScrollSwitchedSlot();
} else if (i < 0) {
accumulatedScrollY -= i;
CobblemonClient.INSTANCE.getStorage().shiftSelected(true);
ci.cancel();
PartySendBinding.INSTANCE.actioned();
PartyTutorialToasts.INSTANCE.onHoldKeyScrollSwitchedSlot();
}
}
}
@@ -310,7 +313,7 @@ public abstract class MouseHandlerMixin {
var playerRotater = (RidePassenger)player;
playerRotater.cobblemon$setRideXRot(playerRotater.cobblemon$getRideXRot() + f);
playerRotater.cobblemon$setRideYRot(playerRotater.cobblemon$getRideYRot() + g);
playerRotater.cobblemon$setRideXRot(Mth.clamp(playerRotater.cobblemon$getRideXRot(), -90.0F, 90.0F));
playerRotater.cobblemon$setRideXRot(Mth.clamp(playerRotater.cobblemon$getRideXRot(), -89.0F, 89.0F));
playerRotater.cobblemon$setRideYRot(Mth.clamp(playerRotater.cobblemon$getRideYRot(), -105.0F, 105.0F));
if (player.getVehicle() != null) {
player.getVehicle().onPassengerTurned(player);
@@ -14,9 +14,14 @@ import com.cobblemon.mod.common.entity.pokemon.PokemonEntity;
import com.cobblemon.mod.common.pokemon.Pokemon;
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
import com.llamalad7.mixinextras.sugar.Local;
import com.llamalad7.mixinextras.sugar.Share;
import com.llamalad7.mixinextras.sugar.ref.LocalBooleanRef;
import com.llamalad7.mixinextras.sugar.ref.LocalFloatRef;
import net.minecraft.client.player.LocalPlayer;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.util.Mth;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.Level;
@@ -89,4 +94,61 @@ public abstract class EntityMixin {
cir.setReturnValue(customEyePos);
}
@WrapOperation(
method = "push(Lnet/minecraft/world/entity/Entity;)V",
at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;push(DDD)V", ordinal = 0)
)
public void cobblemon$customPusherLogic(Entity pusher, double x, double y, double z,
Operation<Void> original,
@Local(argsOnly = true) Entity pushee,
@Local(name = "e") double e, @Local(name = "d") double d,
@Share("pusherIsPlayerOrPokemon") LocalBooleanRef pusherIsPlayerOrPokemon,
@Share("pusheeIsPlayerOrPokemon") LocalBooleanRef pusheeIsPlayerOrPokemon,
@Share("pusheeReceivedForce")LocalFloatRef pusheeReceivedForce) {
pusherIsPlayerOrPokemon.set(pusher instanceof PokemonEntity || pusher instanceof Player);
pusheeIsPlayerOrPokemon.set(pushee instanceof PokemonEntity || pushee instanceof Player);
if (!pusheeIsPlayerOrPokemon.get() || !pusherIsPlayerOrPokemon.get()) {
original.call(pusher, x, y, z);
return;
}
/**********************************************
* Custom portion of the code:
* Handle collisions with weight in mind. Use
* the weight value of pokemon to determine
* which side gets what portion of the total
* force.
*********************************************/
// Weights in hectograms
// Check to see if the pusher or pushee is a player. 200ish pounds. Steve's like a 6'6 miner
var pusherWeight = pusher instanceof PokemonEntity pusherPokemon ? pusherPokemon.getPokemon().getSpecies().getWeight() : 900F;
var pusheeWeight = pushee instanceof PokemonEntity pusheePokemon ? pusheePokemon.getPokemon().getSpecies().getWeight() : 900F;
// Calculate the portion of force received for both entities. Bigger receives less from the
// collision than the smaller one.
var totalWeight = pusherWeight + pusheeWeight;
var pusherReceivedForce = pusheeWeight / totalWeight * 2F;
pusheeReceivedForce.set((pusherWeight / totalWeight) * 2F);
original.call(pusher, -d * pusherReceivedForce, 0.0, -e * pusherReceivedForce);
}
@WrapOperation(
method = "push(Lnet/minecraft/world/entity/Entity;)V",
at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;push(DDD)V", ordinal = 1)
)
public void cobblemon$customPusheeLogic(Entity pusher, double x, double y, double z, Operation<Void> original,
@Local(name = "e") double e, @Local(name = "d") double d,
@Share("pusherIsPlayerOrPokemon") LocalBooleanRef pusherIsPlayerOrPokemon,
@Share("pusheeIsPlayerOrPokemon") LocalBooleanRef pusheeIsPlayerOrPokemon,
@Share("pusheeReceivedForce")LocalFloatRef pusheeReceivedForce) {
if (!pusheeIsPlayerOrPokemon.get() || !pusherIsPlayerOrPokemon.get()) {
original.call(pusher, x, y, z);
return;
}
original.call(pusher, d * pusheeReceivedForce.get(), 0.0, e * pusheeReceivedForce.get());
}
}
@@ -65,10 +65,14 @@ import com.cobblemon.mod.common.api.storage.player.adapter.PlayerDataMongoBacken
import com.cobblemon.mod.common.api.storage.player.factory.CachedPlayerDataStoreFactory
import com.cobblemon.mod.common.api.tags.CobblemonEntityTypeTags
import com.cobblemon.mod.common.api.tags.CobblemonItemTags
import com.cobblemon.mod.common.battles.*
import com.cobblemon.mod.common.battles.BagItems
import com.cobblemon.mod.common.battles.BattleFormat
import com.cobblemon.mod.common.battles.BattleRegistry
import com.cobblemon.mod.common.battles.BattleSide
import com.cobblemon.mod.common.battles.ShowdownThread
import com.cobblemon.mod.common.battles.actor.PokemonBattleActor
import com.cobblemon.mod.common.battles.pokemon.BattlePokemon
import com.cobblemon.mod.common.block.DispenserBehaviorRegistry
import com.cobblemon.mod.common.block.dispenser.DispenserBehaviorRegistry
import com.cobblemon.mod.common.client.CobblemonPack
import com.cobblemon.mod.common.command.argument.*
import com.cobblemon.mod.common.config.CobblemonConfig
@@ -76,7 +80,12 @@ import com.cobblemon.mod.common.config.LastChangedVersion
import com.cobblemon.mod.common.config.constraint.IntConstraint
import com.cobblemon.mod.common.config.starter.StarterConfig
import com.cobblemon.mod.common.data.CobblemonDataProvider
import com.cobblemon.mod.common.events.*
import com.cobblemon.mod.common.events.AdvancementHandler
import com.cobblemon.mod.common.events.CallbackHandler
import com.cobblemon.mod.common.events.EntityCallbackHandler
import com.cobblemon.mod.common.events.PokedexHandler
import com.cobblemon.mod.common.events.ServerTickHandler
import com.cobblemon.mod.common.events.StatHandler
import com.cobblemon.mod.common.net.messages.client.settings.ServerSettingsPacket
import com.cobblemon.mod.common.permission.LaxPermissionValidator
import com.cobblemon.mod.common.platform.events.PlatformEvents
@@ -90,11 +99,23 @@ import com.cobblemon.mod.common.pokemon.feature.SlowpokeTailRegrowthSpeciesFeatu
import com.cobblemon.mod.common.pokemon.feature.SlowpokeTailRegrowthSpeciesFeatureProvider
import com.cobblemon.mod.common.pokemon.feature.TagSeasonResolver
import com.cobblemon.mod.common.pokemon.helditem.CobblemonHeldItemManager
import com.cobblemon.mod.common.pokemon.properties.*
import com.cobblemon.mod.common.pokemon.properties.AspectPropertyType
import com.cobblemon.mod.common.pokemon.properties.BattleCloneProperty
import com.cobblemon.mod.common.pokemon.properties.FreezeFrameProperty
import com.cobblemon.mod.common.pokemon.properties.HiddenAbilityPropertyType
import com.cobblemon.mod.common.pokemon.properties.LabelProperty
import com.cobblemon.mod.common.pokemon.properties.NoAIProperty
import com.cobblemon.mod.common.pokemon.properties.UnaspectPropertyType
import com.cobblemon.mod.common.pokemon.properties.UncatchableProperty
import com.cobblemon.mod.common.pokemon.stat.CobblemonStatProvider
import com.cobblemon.mod.common.starter.CobblemonStarterHandler
import com.cobblemon.mod.common.util.*
import com.cobblemon.mod.common.util.DataKeys
import com.cobblemon.mod.common.util.cobblemonResource
import com.cobblemon.mod.common.util.ifDedicatedServer
import com.cobblemon.mod.common.util.isLaterVersion
import com.cobblemon.mod.common.util.party
import com.cobblemon.mod.common.util.requestWallpapers
import com.cobblemon.mod.common.util.server
import com.cobblemon.mod.common.world.feature.CobblemonPlacedFeatures
import com.cobblemon.mod.common.world.feature.ore.CobblemonOrePlacedFeatures
import com.cobblemon.mod.common.world.gamerules.CobblemonGameRules
@@ -102,6 +123,17 @@ import com.mongodb.ConnectionString
import com.mongodb.MongoClientSettings
import com.mongodb.client.MongoClient
import com.mongodb.client.MongoClients
import java.io.File
import java.io.FileReader
import java.io.FileWriter
import java.io.PrintWriter
import java.util.UUID
import java.util.concurrent.TimeUnit
import kotlin.math.roundToInt
import kotlin.properties.Delegates
import kotlin.reflect.full.memberProperties
import kotlin.reflect.jvm.isAccessible
import kotlin.reflect.jvm.javaField
import net.minecraft.client.Minecraft
import net.minecraft.commands.synchronization.SingletonArgumentInfo
import net.minecraft.resources.ResourceKey
@@ -114,17 +146,6 @@ import net.minecraft.world.level.Level
import net.minecraft.world.level.storage.LevelResource
import org.apache.logging.log4j.LogManager
import org.apache.logging.log4j.Logger
import java.io.File
import java.io.FileReader
import java.io.FileWriter
import java.io.PrintWriter
import java.util.*
import java.util.concurrent.TimeUnit
import kotlin.math.roundToInt
import kotlin.properties.Delegates
import kotlin.reflect.full.memberProperties
import kotlin.reflect.jvm.isAccessible
import kotlin.reflect.jvm.javaField
object Cobblemon {
const val MODID = CobblemonBuildDetails.MOD_ID
@@ -164,8 +185,8 @@ object Cobblemon {
val statistics: CobblemonStats = CobblemonStats
@JvmField
val builtinPacks = listOf<CobblemonPack>(
@JvmStatic
val builtinPacks = listOf(
CobblemonPack(id = "adorncompatibility", name = "Adorn Compatibility", packType = PackType.CLIENT_RESOURCES, activationBehaviour = ResourcePackActivationBehaviour.ALWAYS_ENABLED, neededMods = setOf("adorn")),
CobblemonPack(id = "gyaradosjump", name = "Gyarados Jump Patterns", packType = PackType.CLIENT_RESOURCES, activationBehaviour = ResourcePackActivationBehaviour.DEFAULT_ENABLED),
CobblemonPack(id = "regionbiasforms", name = "Region Bias Forms", packType = PackType.CLIENT_RESOURCES, activationBehaviour = ResourcePackActivationBehaviour.DEFAULT_ENABLED),
@@ -451,7 +472,7 @@ object Cobblemon {
server()?.getLevel(dimension)
} else {
val mc = Minecraft.getInstance()
return mc.singleplayerServer?.getLevel(dimension) ?: mc.level
mc.singleplayerServer?.getLevel(dimension) ?: mc.level
}
}
@@ -569,4 +590,4 @@ object Cobblemon {
this.implementation.registerCommandArgument(cobblemonResource("model_part"), ModelPartArgumentType::class, SingletonArgumentInfo.contextFree(ModelPartArgumentType::modelPart))
}
}
}
@@ -9,6 +9,7 @@
package com.cobblemon.mod.common
import com.cobblemon.mod.common.api.apricorn.Apricorn
import com.cobblemon.mod.common.api.pokemon.stats.Stats
import com.cobblemon.mod.common.block.*
import com.cobblemon.mod.common.block.campfirepot.CampfireBlock
import com.cobblemon.mod.common.block.LecternBlock
@@ -41,11 +42,11 @@ import net.minecraft.world.level.block.state.BlockBehaviour
import net.minecraft.world.level.block.state.BlockState
import net.minecraft.world.level.block.state.properties.BlockSetType
import net.minecraft.world.level.block.state.properties.BlockStateProperties
import net.minecraft.world.level.block.state.properties.BlockStateProperties.LIT
import net.minecraft.world.level.block.state.properties.NoteBlockInstrument
import net.minecraft.world.level.block.state.properties.WoodType
import net.minecraft.world.level.material.MapColor
import net.minecraft.world.level.material.PushReaction
import net.minecraft.world.phys.shapes.Shapes
@Suppress("SameParameterValue", "HasPlatformType", "MemberVisibilityCanBePrivate", "unused")
object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<Block>>, Block>() {
@@ -243,9 +244,9 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
val REVIVAL_HERB = this.create("revival_herb", RevivalHerbBlock(BlockBehaviour.Properties.of().pushReaction(PushReaction.DESTROY).mapColor(MapColor.PLANT).ignitedByLava().noCollission().instabreak().sound(CobblemonSounds.REVIVAL_HERB_SOUNDS)))
@JvmField
val POKE_CAKE = this.create("poke_cake", PokeSnackBlock(BlockBehaviour.Properties.of().forceSolidOn().strength(0.5F).sound(SoundType.WOOL).pushReaction(PushReaction.DESTROY).lightLevel { if (it.getValue(LIT)) 3 else 0 }, false))
val POKE_CAKE = this.create("poke_cake", PokeSnackBlock(BlockBehaviour.Properties.of().forceSolidOn().strength(0.5F).sound(SoundType.WOOL).pushReaction(PushReaction.DESTROY).lightLevel { if (it.getValue(BlockStateProperties.LIT)) 3 else 0 }, false))
@JvmField
val POKE_SNACK = this.create("poke_snack", PokeSnackBlock(BlockBehaviour.Properties.of().forceSolidOn().strength(0.5F).sound(SoundType.WOOL).pushReaction(PushReaction.DESTROY).lightLevel { if (it.getValue(LIT)) 3 else 0 }, true))
val POKE_SNACK = this.create("poke_snack", PokeSnackBlock(BlockBehaviour.Properties.of().forceSolidOn().strength(0.5F).sound(SoundType.WOOL).pushReaction(PushReaction.DESTROY).lightLevel { if (it.getValue(BlockStateProperties.LIT)) 3 else 0 }, true))
@JvmField
val TUMBLESTONE_CLUSTER = tumblestoneBlock("tumblestone_cluster", GrowableStoneBlock.STAGE_3, 7, 3, null)
@@ -477,6 +478,99 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
@JvmField
val GIMMIGHOUL_CHEST = create("gimmighoul_chest", GildedChestBlock(BlockBehaviour.Properties.ofFullCopy(Blocks.CHEST).noOcclusion().sound(CobblemonSounds.GILDED_CHEST_SOUNDS), GildedChestBlock.Type.FAKE))
@JvmField
val WHITE_PLAQUE = create("white_plaque", PlaqueBlock(BlockBehaviour.Properties.of().sound(SoundType.METAL).mapColor(MapColor.METAL).noOcclusion().pushReaction(PushReaction.DESTROY).strength(5.0F)))
@JvmField
val LIGHT_GRAY_PLAQUE = create("light_gray_plaque", PlaqueBlock(BlockBehaviour.Properties.of().sound(SoundType.METAL).mapColor(MapColor.METAL).noOcclusion().pushReaction(PushReaction.DESTROY).strength(5.0F)))
@JvmField
val GRAY_PLAQUE = create("gray_plaque", PlaqueBlock(BlockBehaviour.Properties.of().sound(SoundType.METAL).mapColor(MapColor.METAL).noOcclusion().pushReaction(PushReaction.DESTROY).strength(5.0F)))
@JvmField
val BLACK_PLAQUE = create("black_plaque", PlaqueBlock(BlockBehaviour.Properties.of().sound(SoundType.METAL).mapColor(MapColor.METAL).noOcclusion().pushReaction(PushReaction.DESTROY).strength(5.0F)))
@JvmField
val BROWN_PLAQUE = create("brown_plaque", PlaqueBlock(BlockBehaviour.Properties.of().sound(SoundType.METAL).mapColor(MapColor.METAL).noOcclusion().pushReaction(PushReaction.DESTROY).strength(5.0F)))
@JvmField
val RED_PLAQUE = create("red_plaque", PlaqueBlock(BlockBehaviour.Properties.of().sound(SoundType.METAL).mapColor(MapColor.METAL).noOcclusion().pushReaction(PushReaction.DESTROY).strength(5.0F)))
@JvmField
val ORANGE_PLAQUE = create("orange_plaque", PlaqueBlock(BlockBehaviour.Properties.of().sound(SoundType.METAL).mapColor(MapColor.METAL).noOcclusion().pushReaction(PushReaction.DESTROY).strength(5.0F)))
@JvmField
val YELLOW_PLAQUE = create("yellow_plaque", PlaqueBlock(BlockBehaviour.Properties.of().sound(SoundType.METAL).mapColor(MapColor.METAL).noOcclusion().pushReaction(PushReaction.DESTROY).strength(5.0F)))
@JvmField
val LIME_PLAQUE = create("lime_plaque", PlaqueBlock(BlockBehaviour.Properties.of().sound(SoundType.METAL).mapColor(MapColor.METAL).noOcclusion().pushReaction(PushReaction.DESTROY).strength(5.0F)))
@JvmField
val GREEN_PLAQUE = create("green_plaque", PlaqueBlock(BlockBehaviour.Properties.of().sound(SoundType.METAL).mapColor(MapColor.METAL).noOcclusion().pushReaction(PushReaction.DESTROY).strength(5.0F)))
@JvmField
val CYAN_PLAQUE = create("cyan_plaque", PlaqueBlock(BlockBehaviour.Properties.of().sound(SoundType.METAL).mapColor(MapColor.METAL).noOcclusion().pushReaction(PushReaction.DESTROY).strength(5.0F)))
@JvmField
val LIGHT_BLUE_PLAQUE = create("light_blue_plaque", PlaqueBlock(BlockBehaviour.Properties.of().sound(SoundType.METAL).mapColor(MapColor.METAL).noOcclusion().pushReaction(PushReaction.DESTROY).strength(5.0F)))
@JvmField
val BLUE_PLAQUE = create("blue_plaque", PlaqueBlock(BlockBehaviour.Properties.of().sound(SoundType.METAL).mapColor(MapColor.METAL).noOcclusion().pushReaction(PushReaction.DESTROY).strength(5.0F)))
@JvmField
val PURPLE_PLAQUE = create("purple_plaque", PlaqueBlock(BlockBehaviour.Properties.of().sound(SoundType.METAL).mapColor(MapColor.METAL).noOcclusion().pushReaction(PushReaction.DESTROY).strength(5.0F)))
@JvmField
val MAGENTA_PLAQUE = create("magenta_plaque", PlaqueBlock(BlockBehaviour.Properties.of().sound(SoundType.METAL).mapColor(MapColor.METAL).noOcclusion().pushReaction(PushReaction.DESTROY).strength(5.0F)))
@JvmField
val PINK_PLAQUE = create("pink_plaque", PlaqueBlock(BlockBehaviour.Properties.of().sound(SoundType.METAL).mapColor(MapColor.METAL).noOcclusion().pushReaction(PushReaction.DESTROY).strength(5.0F)))
@JvmField
val CLEANSE_TAG = create("cleanse_tag", WallAttachedStackableItemBlock(BlockBehaviour.Properties.of().sound(SoundType.WOOD).mapColor(MapColor.NONE).pushReaction(PushReaction.DESTROY).noOcclusion().noCollission(), WallAttachedStackableItemBlock.WallStackableItemBlockType.TAG))
@JvmField
val SPELL_TAG = create("spell_tag", WallAttachedStackableItemBlock(BlockBehaviour.Properties.of().sound(SoundType.WOOD).mapColor(MapColor.NONE).pushReaction(PushReaction.DESTROY).noOcclusion().noCollission(), WallAttachedStackableItemBlock.WallStackableItemBlockType.TAG))
@JvmField
val BLUNDER_POLICY = create("blunder_policy", WallAttachedDirectionalShapeBlock(BlockBehaviour.Properties.of().sound(SoundType.CANDLE).mapColor(MapColor.NONE).noOcclusion().noCollission(), 14, 12, 1))
@JvmField
val WEAKNESS_POLICY = create("weakness_policy", WallAttachedDirectionalShapeBlock(BlockBehaviour.Properties.of().sound(SoundType.CANDLE).mapColor(MapColor.NONE).noOcclusion().noCollission(), 14, 12, 1))
@JvmField
val FULL_HEAL = create("full_heal", StackableItemBlock(BlockBehaviour.Properties.of().sound(SoundType.CANDLE).mapColor(MapColor.NONE).noOcclusion(), StackableItemBlock.StackableItemBlockType.STATUS_RESTORE))
@JvmField
val ANTIDOTE = create("antidote", StackableItemBlock(BlockBehaviour.Properties.of().sound(SoundType.CANDLE).mapColor(MapColor.NONE).noOcclusion(), StackableItemBlock.StackableItemBlockType.STATUS_RESTORE))
@JvmField
val AWAKENING = create("awakening", StackableItemBlock(BlockBehaviour.Properties.of().sound(SoundType.CANDLE).mapColor(MapColor.NONE).noOcclusion(), StackableItemBlock.StackableItemBlockType.STATUS_RESTORE))
@JvmField
val BURN_HEAL = create("burn_heal", StackableItemBlock(BlockBehaviour.Properties.of().sound(SoundType.CANDLE).mapColor(MapColor.NONE).noOcclusion(), StackableItemBlock.StackableItemBlockType.STATUS_RESTORE))
@JvmField
val ICE_HEAL = create("ice_heal", StackableItemBlock(BlockBehaviour.Properties.of().sound(SoundType.CANDLE).mapColor(MapColor.NONE).noOcclusion(), StackableItemBlock.StackableItemBlockType.STATUS_RESTORE))
@JvmField
val PARALYZE_HEAL = create("paralyze_heal", StackableItemBlock(BlockBehaviour.Properties.of().sound(SoundType.CANDLE).mapColor(MapColor.NONE).noOcclusion(), StackableItemBlock.StackableItemBlockType.STATUS_RESTORE))
@JvmField
val ETHER = create("ether", StackableItemBlock(BlockBehaviour.Properties.of().sound(SoundType.CANDLE).mapColor(MapColor.NONE).noOcclusion(), StackableItemBlock.StackableItemBlockType.ETHER))
@JvmField
val MAX_ETHER = create("max_ether", StackableItemBlock(BlockBehaviour.Properties.of().sound(SoundType.CANDLE).mapColor(MapColor.NONE).noOcclusion(), StackableItemBlock.StackableItemBlockType.ETHER))
@JvmField
val ELIXIR = create("elixir", StackableItemBlock(BlockBehaviour.Properties.of().sound(SoundType.CANDLE).mapColor(MapColor.NONE).noOcclusion(), StackableItemBlock.StackableItemBlockType.ETHER))
@JvmField
val MAX_ELIXIR = create("max_elixir", StackableItemBlock(BlockBehaviour.Properties.of().sound(SoundType.CANDLE).mapColor(MapColor.NONE).noOcclusion(), StackableItemBlock.StackableItemBlockType.ETHER))
@JvmField
val POTION = create("potion", StackableItemBlock(BlockBehaviour.Properties.of().sound(SoundType.CANDLE).mapColor(MapColor.NONE).noOcclusion(), StackableItemBlock.StackableItemBlockType.POTION))
@JvmField
val SUPER_POTION = create("super_potion", StackableItemBlock(BlockBehaviour.Properties.of().sound(SoundType.CANDLE).mapColor(MapColor.NONE).noOcclusion(), StackableItemBlock.StackableItemBlockType.POTION))
@JvmField
val HYPER_POTION = create("hyper_potion", StackableItemBlock(BlockBehaviour.Properties.of().sound(SoundType.CANDLE).mapColor(MapColor.NONE).noOcclusion(), StackableItemBlock.StackableItemBlockType.POTION))
@JvmField
val MAX_POTION = create("max_potion", StackableItemBlock(BlockBehaviour.Properties.of().sound(SoundType.CANDLE).mapColor(MapColor.NONE).noOcclusion(), StackableItemBlock.StackableItemBlockType.MAX_POTION))
@JvmField
val FULL_RESTORE = create("full_restore", StackableItemBlock(BlockBehaviour.Properties.of().sound(SoundType.CANDLE).mapColor(MapColor.NONE).noOcclusion(), StackableItemBlock.StackableItemBlockType.MAX_POTION))
@JvmField
val DIRE_HIT = create("dire_hit", StackableItemBlock(BlockBehaviour.Properties.of().sound(SoundType.CANDLE).mapColor(MapColor.NONE).noOcclusion(), StackableItemBlock.StackableItemBlockType.BATTLE_ITEM))
@JvmField
val GUARD_SPEC = create("guard_spec", StackableItemBlock(BlockBehaviour.Properties.of().sound(SoundType.CANDLE).mapColor(MapColor.NONE).noOcclusion(), StackableItemBlock.StackableItemBlockType.BATTLE_ITEM))
@JvmField
val X_ACCURACY = create("x_${Stats.ACCURACY.identifier.path}", StackableItemBlock(BlockBehaviour.Properties.of().sound(SoundType.CANDLE).mapColor(MapColor.NONE).noOcclusion(), StackableItemBlock.StackableItemBlockType.BATTLE_ITEM))
@JvmField
val X_ATTACK = create("x_${Stats.ATTACK.identifier.path}", StackableItemBlock(BlockBehaviour.Properties.of().sound(SoundType.CANDLE).mapColor(MapColor.NONE).noOcclusion(), StackableItemBlock.StackableItemBlockType.BATTLE_ITEM))
@JvmField
val X_DEFENSE = create("x_${Stats.DEFENCE.identifier.path}", StackableItemBlock(BlockBehaviour.Properties.of().sound(SoundType.CANDLE).mapColor(MapColor.NONE).noOcclusion(), StackableItemBlock.StackableItemBlockType.BATTLE_ITEM))
@JvmField
val X_SP_ATK = create("x_${Stats.SPECIAL_ATTACK.identifier.path}", StackableItemBlock(BlockBehaviour.Properties.of().sound(SoundType.CANDLE).mapColor(MapColor.NONE).noOcclusion(), StackableItemBlock.StackableItemBlockType.BATTLE_ITEM))
@JvmField
val X_SP_DEF = create("x_${Stats.SPECIAL_DEFENCE.identifier.path}", StackableItemBlock(BlockBehaviour.Properties.of().sound(SoundType.CANDLE).mapColor(MapColor.NONE).noOcclusion(), StackableItemBlock.StackableItemBlockType.BATTLE_ITEM))
@JvmField
val X_SPEED = create("x_${Stats.SPEED.identifier.path}", StackableItemBlock(BlockBehaviour.Properties.of().sound(SoundType.CANDLE).mapColor(MapColor.NONE).noOcclusion(), StackableItemBlock.StackableItemBlockType.BATTLE_ITEM))
@JvmField
val MONITOR = create("monitor", MonitorBlock(BlockBehaviour.Properties.of().mapColor(MapColor.METAL).sound(SoundType.METAL).pushReaction(PushReaction.BLOCK).requiresCorrectToolForDrops().strength(5.0F, 6.0F).lightLevel { if (it.getValue(MonitorBlock.SCREEN) != MonitorBlock.MonitorScreen.OFF) 13 else 0 }))
@JvmField
@@ -74,6 +74,8 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
@JvmField
val NPC_EDITOR = create("npc_editor", CobblemonItem(Item.Properties().stacksTo(1)))
@JvmField
val POKEEDIT_WAND = create("pokeedit_wand", PokeEditWandItem())
@JvmField
val pokeBalls = mutableListOf<PokeBallItem>()
@@ -507,6 +509,23 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
@JvmField val SCROLL_OF_DARKNESS = noSettingsItem("scroll_of_darkness")
@JvmField val SCROLL_OF_WATERS = noSettingsItem("scroll_of_waters")
@JvmField val WHITE_PLAQUE = blockItem("white_plaque", CobblemonBlocks.WHITE_PLAQUE)
@JvmField val LIGHT_GRAY_PLAQUE = blockItem("light_gray_plaque", CobblemonBlocks.LIGHT_GRAY_PLAQUE)
@JvmField val GRAY_PLAQUE = blockItem("gray_plaque", CobblemonBlocks.GRAY_PLAQUE)
@JvmField val BLACK_PLAQUE = blockItem("black_plaque", CobblemonBlocks.BLACK_PLAQUE)
@JvmField val BROWN_PLAQUE = blockItem("brown_plaque", CobblemonBlocks.BROWN_PLAQUE)
@JvmField val RED_PLAQUE = blockItem("red_plaque", CobblemonBlocks.RED_PLAQUE)
@JvmField val ORANGE_PLAQUE = blockItem("orange_plaque", CobblemonBlocks.ORANGE_PLAQUE)
@JvmField val YELLOW_PLAQUE = blockItem("yellow_plaque", CobblemonBlocks.YELLOW_PLAQUE)
@JvmField val LIME_PLAQUE = blockItem("lime_plaque", CobblemonBlocks.LIME_PLAQUE)
@JvmField val GREEN_PLAQUE = blockItem("green_plaque", CobblemonBlocks.GREEN_PLAQUE)
@JvmField val CYAN_PLAQUE = blockItem("cyan_plaque", CobblemonBlocks.CYAN_PLAQUE)
@JvmField val LIGHT_BLUE_PLAQUE = blockItem("light_blue_plaque", CobblemonBlocks.LIGHT_BLUE_PLAQUE)
@JvmField val BLUE_PLAQUE = blockItem("blue_plaque", CobblemonBlocks.BLUE_PLAQUE)
@JvmField val PURPLE_PLAQUE = blockItem("purple_plaque", CobblemonBlocks.PURPLE_PLAQUE)
@JvmField val MAGENTA_PLAQUE = blockItem("magenta_plaque", CobblemonBlocks.MAGENTA_PLAQUE)
@JvmField val PINK_PLAQUE = blockItem("pink_plaque", CobblemonBlocks.PINK_PLAQUE)
private val berries = mutableMapOf<ResourceLocation, BerryItem>()
// Plants
@JvmField val CHERI_BERRY = berryItem("cheri", StatusCuringBerryItem(CobblemonBlocks.CHERI_BERRY, Statuses.PARALYSIS))
@@ -699,15 +718,15 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
val MOOMOO_MILK = create("moomoo_milk", MoomooMilk(Item.Properties().craftRemainder(Items.GLASS_BOTTLE).stacksTo((16))))
@JvmField
val POTION = create("potion", PotionItem(PotionType.POTION))
val POTION = create("potion", PotionItem(PotionType.POTION, CobblemonBlocks.POTION))
@JvmField
val SUPER_POTION = create("super_potion", PotionItem(PotionType.SUPER_POTION))
val SUPER_POTION = create("super_potion", PotionItem(PotionType.SUPER_POTION, CobblemonBlocks.SUPER_POTION))
@JvmField
val HYPER_POTION = create("hyper_potion", PotionItem(PotionType.HYPER_POTION))
val HYPER_POTION = create("hyper_potion", PotionItem(PotionType.HYPER_POTION, CobblemonBlocks.HYPER_POTION))
@JvmField
val MAX_POTION = create("max_potion", PotionItem(PotionType.MAX_POTION))
val MAX_POTION = create("max_potion", PotionItem(PotionType.MAX_POTION, CobblemonBlocks.MAX_POTION))
@JvmField
val FULL_RESTORE = create("full_restore", PotionItem(PotionType.FULL_RESTORE))
val FULL_RESTORE = create("full_restore", PotionItem(PotionType.FULL_RESTORE, CobblemonBlocks.FULL_RESTORE))
@JvmField
val HEAL_POWDER = create("heal_powder", HealPowderItem())
@@ -792,28 +811,27 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
@JvmField
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))
@JvmField val X_DEFENSE = create("x_${Stats.DEFENCE.identifier.path}", XStatItem(Stats.DEFENCE))
@JvmField val X_SP_ATK = create("x_${Stats.SPECIAL_ATTACK.identifier.path}", XStatItem(Stats.SPECIAL_ATTACK))
@JvmField val X_SP_DEF = create("x_${Stats.SPECIAL_DEFENCE.identifier.path}", XStatItem(Stats.SPECIAL_DEFENCE))
@JvmField val X_SPEED = create("x_${Stats.SPEED.identifier.path}", XStatItem(Stats.SPEED))
@JvmField val X_ACCURACY = create("x_${Stats.ACCURACY.identifier.path}", XStatItem(Stats.ACCURACY, block = CobblemonBlocks.X_ACCURACY))
@JvmField val X_ATTACK = create("x_${Stats.ATTACK.identifier.path}", XStatItem(Stats.ATTACK, block = CobblemonBlocks.X_ATTACK))
@JvmField val X_DEFENSE = create("x_${Stats.DEFENCE.identifier.path}", XStatItem(Stats.DEFENCE, block = CobblemonBlocks.X_DEFENSE))
@JvmField val X_SP_ATK = create("x_${Stats.SPECIAL_ATTACK.identifier.path}", XStatItem(Stats.SPECIAL_ATTACK, block = CobblemonBlocks.X_SP_ATK))
@JvmField val X_SP_DEF = create("x_${Stats.SPECIAL_DEFENCE.identifier.path}", XStatItem(Stats.SPECIAL_DEFENCE, block = CobblemonBlocks.X_SP_DEF))
@JvmField val X_SPEED = create("x_${Stats.SPEED.identifier.path}", XStatItem(Stats.SPEED, block = CobblemonBlocks.X_SPEED))
@JvmField val DIRE_HIT = create("dire_hit", DireHitItem())
@JvmField val GUARD_SPEC = create("guard_spec", GuardSpecItem())
@JvmField val DIRE_HIT = create("dire_hit", DireHitItem(CobblemonBlocks.DIRE_HIT))
@JvmField val GUARD_SPEC = create("guard_spec", GuardSpecItem(CobblemonBlocks.GUARD_SPEC))
@JvmField val BURN_HEAL = create("burn_heal", StatusCureItem("item.cobblemon.burn_heal", Statuses.BURN))
@JvmField val PARALYZE_HEAL = create("paralyze_heal", StatusCureItem("item.cobblemon.paralyze_heal", Statuses.PARALYSIS))
@JvmField val ICE_HEAL = create("ice_heal", StatusCureItem("item.cobblemon.ice_heal", Statuses.FROZEN))
@JvmField val ANTIDOTE = create("antidote", StatusCureItem("item.cobblemon.antidote", Statuses.POISON, Statuses.POISON_BADLY))
@JvmField val AWAKENING = create("awakening", StatusCureItem("item.cobblemon.awakening", Statuses.SLEEP))
@JvmField val FULL_HEAL = create("full_heal", StatusCureItem("item.cobblemon.full_heal", block = CobblemonBlocks.FULL_HEAL))
@JvmField val ANTIDOTE = create("antidote", StatusCureItem("item.cobblemon.antidote", Statuses.POISON, Statuses.POISON_BADLY, block = CobblemonBlocks.ANTIDOTE))
@JvmField val AWAKENING = create("awakening", StatusCureItem("item.cobblemon.awakening", Statuses.SLEEP, block = CobblemonBlocks.AWAKENING))
@JvmField val BURN_HEAL = create("burn_heal", StatusCureItem("item.cobblemon.burn_heal", Statuses.BURN, block = CobblemonBlocks.BURN_HEAL))
@JvmField val ICE_HEAL = create("ice_heal", StatusCureItem("item.cobblemon.ice_heal", Statuses.FROZEN, block = CobblemonBlocks.ICE_HEAL))
@JvmField val PARALYZE_HEAL = create("paralyze_heal", StatusCureItem("item.cobblemon.paralyze_heal", Statuses.PARALYSIS, block = CobblemonBlocks.PARALYZE_HEAL))
@JvmField val FULL_HEAL = create("full_heal", StatusCureItem("item.cobblemon.full_heal"))
@JvmField val ETHER = create("ether", EtherItem(max = false))
@JvmField val MAX_ETHER = create("max_ether", EtherItem(max = true))
@JvmField val ELIXIR = create("elixir", ElixirItem(max = false))
@JvmField val MAX_ELIXIR = create("max_elixir", ElixirItem(max = true))
@JvmField val ETHER = create("ether", EtherItem(max = false, CobblemonBlocks.ETHER))
@JvmField val MAX_ETHER = create("max_ether", EtherItem(max = true, CobblemonBlocks.MAX_ETHER))
@JvmField val ELIXIR = create("elixir", ElixirItem(max = false, CobblemonBlocks.ELIXIR))
@JvmField val MAX_ELIXIR = create("max_elixir", ElixirItem(max = true, CobblemonBlocks.MAX_ELIXIR))
@JvmField
val ABILITY_CAPSULE = this.create("ability_capsule", AbilityChangeItem(AbilityChanger.COMMON_ABILITY))
@@ -922,7 +940,7 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
@JvmField
val BLACK_SLUDGE = heldItem("black_sludge")
@JvmField
val BLUNDER_POLICY = heldItem("blunder_policy")
val BLUNDER_POLICY = itemNameBlockItem("blunder_policy", CobblemonBlocks.BLUNDER_POLICY)
@JvmField
val CELL_BATTERY = heldItem("cell_battery")
@JvmField
@@ -930,7 +948,7 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
@JvmField
val CHOICE_SCARF = heldItem("choice_scarf")
@JvmField
val CLEANSE_TAG = heldItem("cleanse_tag")
val CLEANSE_TAG = itemNameBlockItem("cleanse_tag", CobblemonBlocks.CLEANSE_TAG)
@JvmField
val CLEAR_AMULET = heldItem("clear_amulet")
@JvmField
@@ -1038,7 +1056,7 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
@JvmField
val SOFT_SAND = heldItem("soft_sand")
@JvmField
val SPELL_TAG = heldItem("spell_tag")
val SPELL_TAG = itemNameBlockItem("spell_tag", CobblemonBlocks.SPELL_TAG)
@JvmField
val SMOKE_BALL = heldItem("smoke_ball")
@JvmField
@@ -1056,7 +1074,7 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
@JvmField
val UTILITY_UMBRELLA = heldItem("utility_umbrella")
@JvmField
val WEAKNESS_POLICY = heldItem("weakness_policy")
val WEAKNESS_POLICY = itemNameBlockItem("weakness_policy", CobblemonBlocks.WEAKNESS_POLICY)
@JvmField
val WIDE_LENS = heldItem("wide_lens")
@JvmField
@@ -1553,6 +1571,7 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
}
}
)
private fun heldItem(name: String, item: Item, remappedName: String? = null) = create(
name = name,
entry = item.also {
@@ -0,0 +1,55 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common
import com.cobblemon.mod.common.api.data.JsonDataRegistry
import com.cobblemon.mod.common.api.moves.MoveSelector
import com.cobblemon.mod.common.api.moves.MovesetBuilder
import com.cobblemon.mod.common.api.reactive.SimpleObservable
import com.cobblemon.mod.common.util.adapters.IdentifierAdapter
import com.cobblemon.mod.common.util.adapters.MovesetBuilderAdapter
import com.cobblemon.mod.common.util.adapters.StringToObjectAdapter
import com.cobblemon.mod.common.util.cobblemonResource
import com.google.gson.Gson
import com.google.gson.GsonBuilder
import com.google.gson.reflect.TypeToken
import net.minecraft.resources.ResourceLocation
import net.minecraft.server.level.ServerPlayer
import net.minecraft.server.packs.PackType
object CobblemonMovesetBuilders : JsonDataRegistry<MovesetBuilder> {
override val gson: Gson = GsonBuilder()
.setPrettyPrinting()
.registerTypeAdapter(ResourceLocation::class.java, IdentifierAdapter)
.registerTypeAdapter(MovesetBuilder::class.java, MovesetBuilderAdapter)
.registerTypeAdapter(MoveSelector::class.java, StringToObjectAdapter(MoveSelector.selectors))
.create()
override val typeToken = TypeToken.get(MovesetBuilder::class.java)
override val resourcePath = "moveset_builders"
override val id: ResourceLocation = cobblemonResource("moveset_builders")
override val type = PackType.SERVER_DATA
override val observable = SimpleObservable<CobblemonMovesetBuilders>()
val movesetBuilders = mutableMapOf<ResourceLocation, MovesetBuilder>()
fun getOrThrow(id: ResourceLocation): MovesetBuilder {
return movesetBuilders[id]
?: throw IllegalArgumentException("Unknown MovesetBuilder id: $id")
}
override fun sync(player: ServerPlayer) { /* These don't sync. But what if they did? Nah probably shouldn't sync. */ }
override fun reload(data: Map<ResourceLocation, MovesetBuilder>) {
movesetBuilders.clear()
data.forEach { (id, value) -> value.id = id }
movesetBuilders.putAll(data)
observable.emit(this)
}
}
@@ -21,12 +21,15 @@ import com.cobblemon.mod.common.client.net.callback.partymove.OpenPartyMoveCallb
import com.cobblemon.mod.common.client.net.cooking.ToggleCookingPotLidHandler
import com.cobblemon.mod.common.client.net.data.CobblemonMechanicsSyncHandler
import com.cobblemon.mod.common.client.net.data.DataRegistrySyncPacketHandler
import com.cobblemon.mod.common.client.net.data.PokemonInteractionsSyncHandler
import com.cobblemon.mod.common.client.net.data.RideSettingsSyncHandler
import com.cobblemon.mod.common.client.net.debug.OpenRidingStatsDebugGUIHandler
import com.cobblemon.mod.common.client.net.dialogue.DialogueClosedHandler
import com.cobblemon.mod.common.client.net.dialogue.DialogueOpenedHandler
import com.cobblemon.mod.common.client.net.effect.*
import com.cobblemon.mod.common.client.net.effect.PokeSnackBlockParticlesHandler
import com.cobblemon.mod.common.client.net.effect.RunPosableMoLangHandler
import com.cobblemon.mod.common.client.net.effect.SaccharineLogBlockParticlesHandler
import com.cobblemon.mod.common.client.net.effect.SpawnSnowstormEntityParticleHandler
import com.cobblemon.mod.common.client.net.effect.SpawnSnowstormParticleHandler
import com.cobblemon.mod.common.client.net.gui.ExpGainedDataPacketHandler
import com.cobblemon.mod.common.client.net.gui.InteractPokemonUIPacketHandler
import com.cobblemon.mod.common.client.net.gui.PokedexUIPacketHandler
@@ -34,7 +37,11 @@ import com.cobblemon.mod.common.client.net.gui.SummaryUIPacketHandler
import com.cobblemon.mod.common.client.net.npc.CloseNPCEditorHandler
import com.cobblemon.mod.common.client.net.npc.OpenNPCEditorHandler
import com.cobblemon.mod.common.client.net.orientation.ClientboundUpdateOrientationHandler
import com.cobblemon.mod.common.client.net.pasture.*
import com.cobblemon.mod.common.client.net.pasture.ClosePastureHandler
import com.cobblemon.mod.common.client.net.pasture.OpenPastureHandler
import com.cobblemon.mod.common.client.net.pasture.PokemonPasturedHandler
import com.cobblemon.mod.common.client.net.pasture.PokemonUnpasturedHandler
import com.cobblemon.mod.common.client.net.pasture.UpdatePastureConflictFlagHandler
import com.cobblemon.mod.common.client.net.pokedex.ServerConfirmedRegisterHandler
import com.cobblemon.mod.common.client.net.pokemon.update.ClientboundUpdateRidingStateHandler
import com.cobblemon.mod.common.client.net.pokemon.update.PokemonUpdatePacketHandler
@@ -52,7 +59,14 @@ import com.cobblemon.mod.common.client.net.storage.party.SetPartyPokemonHandler
import com.cobblemon.mod.common.client.net.storage.party.SetPartyReferenceHandler
import com.cobblemon.mod.common.client.net.storage.pc.*
import com.cobblemon.mod.common.client.net.toast.ToastPacketHandler
import com.cobblemon.mod.common.client.net.trade.*
import com.cobblemon.mod.common.client.net.trade.TradeAcceptanceChangedHandler
import com.cobblemon.mod.common.client.net.trade.TradeCancelledHandler
import com.cobblemon.mod.common.client.net.trade.TradeCompletedHandler
import com.cobblemon.mod.common.client.net.trade.TradeOfferExpiredHandler
import com.cobblemon.mod.common.client.net.trade.TradeOfferNotificationHandler
import com.cobblemon.mod.common.client.net.trade.TradeProcessStartedHandler
import com.cobblemon.mod.common.client.net.trade.TradeStartedHandler
import com.cobblemon.mod.common.client.net.trade.TradeUpdatedHandler
import com.cobblemon.mod.common.net.PacketRegisterInfo
import com.cobblemon.mod.common.net.messages.client.CalculateSeatPositionsPacket
import com.cobblemon.mod.common.net.messages.client.OpenBehaviourEditorPacket
@@ -69,12 +83,20 @@ import com.cobblemon.mod.common.net.messages.client.data.*
import com.cobblemon.mod.common.net.messages.client.debug.RequestOpenRidingStatsDebugGUIPacket
import com.cobblemon.mod.common.net.messages.client.dialogue.DialogueClosedPacket
import com.cobblemon.mod.common.net.messages.client.dialogue.DialogueOpenedPacket
import com.cobblemon.mod.common.net.messages.client.effect.*
import com.cobblemon.mod.common.net.messages.client.effect.PokeSnackBlockParticlesPacket
import com.cobblemon.mod.common.net.messages.client.effect.RunPosableMoLangPacket
import com.cobblemon.mod.common.net.messages.client.effect.SaccharineLogBlockParticlesPacket
import com.cobblemon.mod.common.net.messages.client.effect.SpawnSnowstormEntityParticlePacket
import com.cobblemon.mod.common.net.messages.client.effect.SpawnSnowstormParticlePacket
import com.cobblemon.mod.common.net.messages.client.npc.CloseNPCEditorPacket
import com.cobblemon.mod.common.net.messages.client.npc.OpenNPCEditorPacket
import com.cobblemon.mod.common.net.messages.client.orientation.ClientboundUpdateDriverInputPacket
import com.cobblemon.mod.common.net.messages.client.orientation.ClientboundUpdateOrientationPacket
import com.cobblemon.mod.common.net.messages.client.pasture.*
import com.cobblemon.mod.common.net.messages.client.pasture.ClosePasturePacket
import com.cobblemon.mod.common.net.messages.client.pasture.OpenPasturePacket
import com.cobblemon.mod.common.net.messages.client.pasture.PokemonPasturedPacket
import com.cobblemon.mod.common.net.messages.client.pasture.PokemonUnpasturedPacket
import com.cobblemon.mod.common.net.messages.client.pasture.UpdatePastureConflictFlagPacket
import com.cobblemon.mod.common.net.messages.client.pokedex.ServerConfirmedRegisterPacket
import com.cobblemon.mod.common.net.messages.client.pokemon.update.*
import com.cobblemon.mod.common.net.messages.client.pokemon.update.evolution.AddEvolutionPacket
@@ -94,19 +116,37 @@ import com.cobblemon.mod.common.net.messages.client.storage.party.InitializePart
import com.cobblemon.mod.common.net.messages.client.storage.party.MoveClientPartyPokemonPacket
import com.cobblemon.mod.common.net.messages.client.storage.party.SetPartyPokemonPacket
import com.cobblemon.mod.common.net.messages.client.storage.party.SetPartyReferencePacket
import com.cobblemon.mod.common.net.messages.client.storage.pc.*
import com.cobblemon.mod.common.net.messages.client.storage.pc.ClosePCPacket
import com.cobblemon.mod.common.net.messages.client.storage.pc.InitializePCPacket
import com.cobblemon.mod.common.net.messages.client.storage.pc.MoveClientPCPokemonPacket
import com.cobblemon.mod.common.net.messages.client.storage.pc.OpenPCPacket
import com.cobblemon.mod.common.net.messages.client.storage.pc.RenamePCBoxPacket
import com.cobblemon.mod.common.net.messages.client.storage.pc.SetPCBoxPacket
import com.cobblemon.mod.common.net.messages.client.storage.pc.SetPCPokemonPacket
import com.cobblemon.mod.common.net.messages.client.storage.pc.wallpaper.ChangePCBoxWallpaperPacket
import com.cobblemon.mod.common.net.messages.client.storage.pc.wallpaper.RequestPCBoxWallpapersPacket
import com.cobblemon.mod.common.net.messages.client.storage.pc.wallpaper.SetPCBoxWallpapersPacket
import com.cobblemon.mod.common.net.messages.client.storage.pc.wallpaper.UnlockPCBoxWallpaperPacket
import com.cobblemon.mod.common.net.messages.client.toast.ToastPacket
import com.cobblemon.mod.common.net.messages.client.trade.*
import com.cobblemon.mod.common.net.messages.client.trade.TradeAcceptanceChangedPacket
import com.cobblemon.mod.common.net.messages.client.trade.TradeCancelledPacket
import com.cobblemon.mod.common.net.messages.client.trade.TradeCompletedPacket
import com.cobblemon.mod.common.net.messages.client.trade.TradeOfferExpiredPacket
import com.cobblemon.mod.common.net.messages.client.trade.TradeOfferNotificationPacket
import com.cobblemon.mod.common.net.messages.client.trade.TradeProcessStartedPacket
import com.cobblemon.mod.common.net.messages.client.trade.TradeStartedPacket
import com.cobblemon.mod.common.net.messages.client.trade.TradeUpdatedPacket
import com.cobblemon.mod.common.net.messages.client.ui.ExpGainedDataPacket
import com.cobblemon.mod.common.net.messages.client.ui.InteractPokemonUIPacket
import com.cobblemon.mod.common.net.messages.client.ui.PokedexUIPacket
import com.cobblemon.mod.common.net.messages.client.ui.SummaryUIPacket
import com.cobblemon.mod.common.net.messages.server.*
import com.cobblemon.mod.common.net.messages.server.battle.*
import com.cobblemon.mod.common.net.messages.server.battle.BattleSelectActionsPacket
import com.cobblemon.mod.common.net.messages.server.battle.BattleTeamLeavePacket
import com.cobblemon.mod.common.net.messages.server.battle.BattleTeamRequestPacket
import com.cobblemon.mod.common.net.messages.server.battle.BattleTeamResponsePacket
import com.cobblemon.mod.common.net.messages.server.battle.RemoveSpectatorPacket
import com.cobblemon.mod.common.net.messages.server.battle.SpectateBattlePacket
import com.cobblemon.mod.common.net.messages.server.behaviour.DamageOnCollisionPacket
import com.cobblemon.mod.common.net.messages.server.behaviour.SetEntityBehaviourPacket
import com.cobblemon.mod.common.net.messages.server.block.AdjustBlockEntityViewerCountPacket
@@ -130,8 +170,13 @@ import com.cobblemon.mod.common.net.messages.server.pasture.UnpastureAllPokemonP
import com.cobblemon.mod.common.net.messages.server.pasture.UnpasturePokemonPacket
import com.cobblemon.mod.common.net.messages.server.pokedex.scanner.FinishScanningPacket
import com.cobblemon.mod.common.net.messages.server.pokedex.scanner.StartScanningPacket
import com.cobblemon.mod.common.net.messages.server.pokeedit.PokeEditActionPacket
import com.cobblemon.mod.common.net.messages.server.pokemon.interact.InteractPokemonPacket
import com.cobblemon.mod.common.net.messages.server.pokemon.update.*
import com.cobblemon.mod.common.net.messages.server.pokemon.update.ServerboundUpdateRidingStatePacket
import com.cobblemon.mod.common.net.messages.server.pokemon.update.SetActiveMarkPacket
import com.cobblemon.mod.common.net.messages.server.pokemon.update.SetItemHiddenPacket
import com.cobblemon.mod.common.net.messages.server.pokemon.update.SetMarkingsPacket
import com.cobblemon.mod.common.net.messages.server.pokemon.update.SetNicknamePacket
import com.cobblemon.mod.common.net.messages.server.pokemon.update.evolution.AcceptEvolutionPacket
import com.cobblemon.mod.common.net.messages.server.riding.DismountPokemonPacket
import com.cobblemon.mod.common.net.messages.server.riding.ServerboundUpdateDriverInputPacket
@@ -139,14 +184,25 @@ import com.cobblemon.mod.common.net.messages.server.riding.ServerboundUpdateRide
import com.cobblemon.mod.common.net.messages.server.starter.RequestStarterScreenPacket
import com.cobblemon.mod.common.net.messages.server.storage.SwapPCPartyPokemonPacket
import com.cobblemon.mod.common.net.messages.server.storage.party.MovePartyPokemonPacket
import com.cobblemon.mod.common.net.messages.server.storage.party.PartyTutorialPacket
import com.cobblemon.mod.common.net.messages.server.storage.party.ReleasePartyPokemonPacket
import com.cobblemon.mod.common.net.messages.server.storage.party.SwapPartyPokemonPacket
import com.cobblemon.mod.common.net.messages.server.storage.pc.*
import com.cobblemon.mod.common.net.messages.server.trade.*
import com.cobblemon.mod.common.net.messages.server.trade.AcceptTradeRequestPacket
import com.cobblemon.mod.common.net.messages.server.trade.CancelTradePacket
import com.cobblemon.mod.common.net.messages.server.trade.ChangeTradeAcceptancePacket
import com.cobblemon.mod.common.net.messages.server.trade.OfferTradePacket
import com.cobblemon.mod.common.net.messages.server.trade.PerformTradePacket
import com.cobblemon.mod.common.net.messages.server.trade.UpdateTradeOfferPacket
import com.cobblemon.mod.common.net.serverhandling.ChallengeHandler
import com.cobblemon.mod.common.net.serverhandling.ChallengeResponseHandler
import com.cobblemon.mod.common.net.serverhandling.RequestInteractionsHandler
import com.cobblemon.mod.common.net.serverhandling.battle.*
import com.cobblemon.mod.common.net.serverhandling.battle.BattleSelectActionsHandler
import com.cobblemon.mod.common.net.serverhandling.battle.RemoveSpectatorHandler
import com.cobblemon.mod.common.net.serverhandling.battle.SpectateBattleHandler
import com.cobblemon.mod.common.net.serverhandling.battle.TeamLeaveHandler
import com.cobblemon.mod.common.net.serverhandling.battle.TeamRequestHandler
import com.cobblemon.mod.common.net.serverhandling.battle.TeamRequestResponseHandler
import com.cobblemon.mod.common.net.serverhandling.behaviour.DamageOnCollisionPacketHandler
import com.cobblemon.mod.common.net.serverhandling.behaviour.SetEntityBehaviourHandler
import com.cobblemon.mod.common.net.serverhandling.block.AdjustBlockEntityViewerCountHandler
@@ -165,14 +221,20 @@ import com.cobblemon.mod.common.net.serverhandling.dialogue.InputToDialogueHandl
import com.cobblemon.mod.common.net.serverhandling.evolution.AcceptEvolutionHandler
import com.cobblemon.mod.common.net.serverhandling.npc.SaveNPCHandler
import com.cobblemon.mod.common.net.serverhandling.orientation.ServerboundUpdateOrientationHandler
import com.cobblemon.mod.common.net.serverhandling.storage.party.PartyTutorialPacketHandler
import com.cobblemon.mod.common.net.serverhandling.pasture.PasturePokemonHandler
import com.cobblemon.mod.common.net.serverhandling.pasture.SetPastureConflictHandler
import com.cobblemon.mod.common.net.serverhandling.pasture.UnpastureAllPokemonHandler
import com.cobblemon.mod.common.net.serverhandling.pasture.UnpasturePokemonHandler
import com.cobblemon.mod.common.net.serverhandling.pokedex.scanner.FinishScanningHandler
import com.cobblemon.mod.common.net.serverhandling.pokedex.scanner.StartScanningHandler
import com.cobblemon.mod.common.net.serverhandling.pokeedit.PokeEditActionHandler
import com.cobblemon.mod.common.net.serverhandling.pokemon.interact.InteractPokemonHandler
import com.cobblemon.mod.common.net.serverhandling.pokemon.update.*
import com.cobblemon.mod.common.net.serverhandling.pokemon.update.ServerboundUpdateRidingStateHandler
import com.cobblemon.mod.common.net.serverhandling.pokemon.update.SetActiveMarkHandler
import com.cobblemon.mod.common.net.serverhandling.pokemon.update.SetItemHiddenHandler
import com.cobblemon.mod.common.net.serverhandling.pokemon.update.SetMarkingsHandler
import com.cobblemon.mod.common.net.serverhandling.pokemon.update.SetNicknameHandler
import com.cobblemon.mod.common.net.serverhandling.riding.DismountPokemonPacketHandler
import com.cobblemon.mod.common.net.serverhandling.riding.DriverInputPacketHandler
import com.cobblemon.mod.common.net.serverhandling.riding.ServerboundUpdateRiderRotationHandler
@@ -186,7 +248,12 @@ import com.cobblemon.mod.common.net.serverhandling.storage.party.MovePartyPokemo
import com.cobblemon.mod.common.net.serverhandling.storage.party.ReleasePCPokemonHandler
import com.cobblemon.mod.common.net.serverhandling.storage.party.SwapPartyPokemonHandler
import com.cobblemon.mod.common.net.serverhandling.storage.pc.*
import com.cobblemon.mod.common.net.serverhandling.trade.*
import com.cobblemon.mod.common.net.serverhandling.trade.AcceptTradeRequestHandler
import com.cobblemon.mod.common.net.serverhandling.trade.CancelTradeHandler
import com.cobblemon.mod.common.net.serverhandling.trade.ChangeTradeAcceptanceHandler
import com.cobblemon.mod.common.net.serverhandling.trade.OfferTradeHandler
import com.cobblemon.mod.common.net.serverhandling.trade.PerformTradeHandler
import com.cobblemon.mod.common.net.serverhandling.trade.UpdateTradeOfferHandler
import com.cobblemon.mod.common.util.server
import net.minecraft.server.level.ServerPlayer
@@ -332,7 +399,7 @@ object CobblemonNetwork {
// Data registries
list.add(PacketRegisterInfo(AbilityRegistrySyncPacket.ID, AbilityRegistrySyncPacket::decode, DataRegistrySyncPacketHandler()))
list.add(PacketRegisterInfo(CobblemonMechanicsSyncPacket.ID, CobblemonMechanicsSyncPacket::decode, CobblemonMechanicsSyncHandler))
list.add(PacketRegisterInfo(PokemonInteractionsSyncPacket.ID, PokemonInteractionsSyncPacket::decode, PokemonInteractionsSyncHandler))
list.add(PacketRegisterInfo(PokemonInteractionsSyncPacket.ID, PokemonInteractionsSyncPacket::decode, DataRegistrySyncPacketHandler()))
list.add(PacketRegisterInfo(MovesRegistrySyncPacket.ID, MovesRegistrySyncPacket::decode, DataRegistrySyncPacketHandler()))
list.add(PacketRegisterInfo(BerryRegistrySyncPacket.ID, BerryRegistrySyncPacket::decode, DataRegistrySyncPacketHandler()))
list.add(PacketRegisterInfo(SpeciesRegistrySyncPacket.ID, SpeciesRegistrySyncPacket::decode, DataRegistrySyncPacketHandler()))
@@ -460,7 +527,7 @@ object CobblemonNetwork {
list.add(PacketRegisterInfo(ReleasePCPokemonPacket.ID, ReleasePCPokemonPacket::decode, ReleasePCPokemonHandler))
list.add(PacketRegisterInfo(UnlinkPlayerFromPCPacket.ID, UnlinkPlayerFromPCPacket::decode, UnlinkPlayerFromPCHandler))
list.add(PacketRegisterInfo(RequestRenamePCBoxPacket.Companion.ID, RequestRenamePCBoxPacket.Companion::decode, RequestRenamePCBoxHandler))
list.add(PacketRegisterInfo(RequestRenamePCBoxPacket.ID, RequestRenamePCBoxPacket::decode, RequestRenamePCBoxHandler))
list.add(PacketRegisterInfo(PCBoxWallpapersPacket.ID, PCBoxWallpapersPacket::decode, PCBoxWallpapersHandler))
list.add(PacketRegisterInfo(RequestChangePCBoxWallpaperPacket.ID, RequestChangePCBoxWallpaperPacket::decode, RequestChangePCBoxWallpaperHandler))
list.add(PacketRegisterInfo(MarkPCBoxWallpapersSeenPacket.ID, MarkPCBoxWallpapersSeenPacket::decode, MarkPCBoxWallpapersSeenHandler))
@@ -496,6 +563,9 @@ object CobblemonNetwork {
list.add(PacketRegisterInfo(StartScanningPacket.ID, StartScanningPacket::decode, StartScanningHandler))
list.add(PacketRegisterInfo(FinishScanningPacket.ID, FinishScanningPacket::decode, FinishScanningHandler))
// PokeEdit actions
list.add(PacketRegisterInfo(PokeEditActionPacket.ID, PokeEditActionPacket::decode, PokeEditActionHandler))
// Pasture
list.add(PacketRegisterInfo(PasturePokemonPacket.ID, PasturePokemonPacket::decode, PasturePokemonHandler))
list.add(PacketRegisterInfo(UnpasturePokemonPacket.ID, UnpasturePokemonPacket::decode, UnpasturePokemonHandler))
@@ -518,6 +588,9 @@ object CobblemonNetwork {
list.add(PacketRegisterInfo(PartyPokemonMoveSelectedPacket.ID, PartyPokemonMoveSelectedPacket::decode, PartyPokemonMoveSelectedHandler))
list.add(PacketRegisterInfo(PartyMoveSelectCancelledPacket.ID, PartyMoveSelectCancelledPacket::decode, PartyMoveSelectCancelledHandler))
//Party move tutorial toasts packets
list.add(PacketRegisterInfo(PartyTutorialPacket.ID, PartyTutorialPacket::decode, PartyTutorialPacketHandler))
// Dialogue packets
list.add(PacketRegisterInfo(EscapeDialoguePacket.ID, EscapeDialoguePacket::decode, EscapeDialogueHandler))
list.add(PacketRegisterInfo(InputToDialoguePacket.ID, InputToDialoguePacket::decode, InputToDialogueHandler))
@@ -551,4 +624,4 @@ object CobblemonNetwork {
fun sendPacketToPlayer(player: ServerPlayer, packet: NetworkPacket<*>) {
Cobblemon.implementation.networkManager.sendPacketToPlayer(player, packet)
}
}
}
@@ -0,0 +1,47 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common
import com.cobblemon.mod.common.api.data.JsonDataRegistry
import com.cobblemon.mod.common.api.npc.PartyComposition
import com.cobblemon.mod.common.api.reactive.SimpleObservable
import com.cobblemon.mod.common.util.adapters.IdentifierAdapter
import com.cobblemon.mod.common.util.cobblemonResource
import com.google.gson.Gson
import com.google.gson.GsonBuilder
import com.google.gson.reflect.TypeToken
import net.minecraft.resources.ResourceLocation
import net.minecraft.server.level.ServerPlayer
import net.minecraft.server.packs.PackType
object CobblemonPartyCompositions : JsonDataRegistry<PartyComposition> {
override val id: ResourceLocation = cobblemonResource("party_compositions")
override val type = PackType.SERVER_DATA
override val typeToken: TypeToken<PartyComposition> = TypeToken.get(PartyComposition::class.java)
override val resourcePath: String = "party_compositions"
override val observable = SimpleObservable<CobblemonPartyCompositions>()
override val gson: Gson = GsonBuilder()
.registerTypeAdapter(ResourceLocation::class.java, IdentifierAdapter)
.setPrettyPrinting()
.create()
val partyCompositions = mutableMapOf<ResourceLocation, PartyComposition>()
override fun sync(player: ServerPlayer) {
// probably worth syncing which exist, yeah. the deeper details probably not. I'll get to this eventually.
}
override fun reload(data: Map<ResourceLocation, PartyComposition>) {
data.entries.forEach { it.value.id = it.key }
partyCompositions.clear()
partyCompositions.putAll(data)
observable.emit(this)
Cobblemon.LOGGER.info("Loaded ${data.size} party compositions.")
}
}
@@ -0,0 +1,60 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common
import com.cobblemon.mod.common.api.data.JsonDataRegistry
import com.cobblemon.mod.common.api.molang.ExpressionLike
import com.cobblemon.mod.common.api.moves.MovesetBuilder
import com.cobblemon.mod.common.api.npc.PartyPool
import com.cobblemon.mod.common.api.pokemon.PokemonProperties
import com.cobblemon.mod.common.api.reactive.SimpleObservable
import com.cobblemon.mod.common.util.ScriptableIntRange
import com.cobblemon.mod.common.util.adapters.ExpressionLikeAdapter
import com.cobblemon.mod.common.util.adapters.IdentifierAdapter
import com.cobblemon.mod.common.util.adapters.IntRangeAdapter
import com.cobblemon.mod.common.util.adapters.MovesetBuilderReferenceAdapter
import com.cobblemon.mod.common.util.adapters.PokemonPropertiesAdapter
import com.cobblemon.mod.common.util.adapters.ScriptableIntRangeAdapter
import com.cobblemon.mod.common.util.cobblemonResource
import com.google.gson.Gson
import com.google.gson.GsonBuilder
import com.google.gson.reflect.TypeToken
import net.minecraft.resources.ResourceLocation
import net.minecraft.server.level.ServerPlayer
import net.minecraft.server.packs.PackType
object CobblemonPartyPools : JsonDataRegistry<PartyPool> {
override val id: ResourceLocation = cobblemonResource("party_pools")
override val type = PackType.SERVER_DATA
override val typeToken: TypeToken<PartyPool> = TypeToken.get(PartyPool::class.java)
override val resourcePath: String = "party_pools"
override val observable = SimpleObservable<CobblemonPartyPools>()
override val gson: Gson = GsonBuilder()
.registerTypeAdapter(ResourceLocation::class.java, IdentifierAdapter)
.registerTypeAdapter(PokemonProperties::class.java, PokemonPropertiesAdapter(saveLong = false))
.registerTypeAdapter(IntRange::class.java, IntRangeAdapter)
.registerTypeAdapter(ScriptableIntRange::class.java, ScriptableIntRangeAdapter)
.registerTypeAdapter(MovesetBuilder::class.java, MovesetBuilderReferenceAdapter)
.registerTypeAdapter(ExpressionLike::class.java, ExpressionLikeAdapter)
.setPrettyPrinting()
.create()
val partyPools = mutableMapOf<ResourceLocation, PartyPool>()
override fun sync(player: ServerPlayer) {
// probably worth syncing. Knowing the details might help exploit the server? lot of effort for little though.
}
override fun reload(data: Map<ResourceLocation, PartyPool>) {
data.entries.forEach { it.value.id = it.key }
partyPools.clear()
partyPools.putAll(data)
observable.emit(this)
}
}
@@ -23,7 +23,6 @@ class AspectCriterion(
): SimpleCriterionCondition<MutableMap<ResourceLocation, MutableSet<String>>>(playerCtx) {
companion object {
@JvmField
val CODEC: Codec<AspectCriterion> = RecordCodecBuilder.create { it.group(
//All three of these codecs used to use Codecs.createStrictOptionalFieldCodec, that no longer exists
ContextAwarePredicate.CODEC.optionalFieldOf("player").forGetter(AspectCriterion::playerCtx),
@@ -36,4 +35,4 @@ class AspectCriterion(
val caughtAspects = context.getOrDefault(species, mutableSetOf())
return this.aspects.all { it in caughtAspects }
}
}
}
@@ -25,7 +25,6 @@ class BattleCountableCriterion(
): CountableCriterion<BattleCountableContext>(playerCtx, count) {
companion object {
@JvmField
val CODEC: Codec<BattleCountableCriterion> = RecordCodecBuilder.create { it.group(
ContextAwarePredicate.CODEC.optionalFieldOf("player").forGetter(BattleCountableCriterion::playerCtx),
Codec.STRING.listOf().optionalFieldOf("battle_types", listOf("any")).forGetter(BattleCountableCriterion::battleTypes),
@@ -25,7 +25,6 @@ class CastPokeRodCriterionCondition(
): SimpleCriterionCondition<CastPokeRodContext>(playerCtx) {
companion object {
@JvmField
val CODEC: Codec<CastPokeRodCriterionCondition> = RecordCodecBuilder.create { it.group(
EntityPredicate.ADVANCEMENT_CODEC.optionalFieldOf("player").forGetter(CastPokeRodCriterionCondition::playerCtx),
Codec.STRING.optionalFieldOf("baitId", "empty_bait").forGetter(CastPokeRodCriterionCondition::baitId)
@@ -35,4 +34,4 @@ class CastPokeRodCriterionCondition(
override fun matches(player: ServerPlayer, context: CastPokeRodContext): Boolean {
return (context.baitId == this.baitId.asIdentifierDefaultingNamespace() || this.baitId == "empty_bait")
}
}
}
@@ -31,7 +31,6 @@ class CaughtPokemonCriterion(
): CountableCriterion<CountablePokemonTypeContext>(playerCtx, count) {
companion object {
@JvmField
val CODEC: Codec<CaughtPokemonCriterion> = RecordCodecBuilder.create { it.group(
EntityPredicate.ADVANCEMENT_CODEC.optionalFieldOf("player").forGetter(CaughtPokemonCriterion::playerCtx),
Codec.STRING.optionalFieldOf("type", "any").forGetter(CaughtPokemonCriterion::type),
@@ -43,4 +42,4 @@ class CaughtPokemonCriterion(
override fun matches(player: ServerPlayer, context: CountablePokemonTypeContext): Boolean {
return super.matches(player, context) && (context.type == type || type == "any")// && (context.species == species || species == "any")
}
}
}
@@ -23,7 +23,6 @@ open class CountableCriterion<T : CountableContext>(
): SimpleCriterionCondition<T>(playerCtx) {
companion object {
@JvmField
val CODEC: Codec<CountableCriterion<CountableContext>> = RecordCodecBuilder.create { it.group(
EntityPredicate.ADVANCEMENT_CODEC.optionalFieldOf("player").forGetter(CountableCriterion<CountableContext>::playerCtx),
Codec.INT.optionalFieldOf("count", 0).forGetter(CountableCriterion<CountableContext>::count)
@@ -26,7 +26,6 @@ class EvolvePokemonCriterion(
): CountableCriterion<EvolvePokemonContext>(playerCtx, count) {
companion object {
@JvmField
val CODEC: Codec<EvolvePokemonCriterion> = RecordCodecBuilder.create { it.group(
ContextAwarePredicate.CODEC.optionalFieldOf("player").forGetter(EvolvePokemonCriterion::playerCtx),
Codec.STRING.optionalFieldOf("species", "any").forGetter(EvolvePokemonCriterion::species),
@@ -25,7 +25,6 @@ class LevelUpCriterion(
): SimpleCriterionCondition<LevelUpContext>(playerCtx) {
companion object {
@JvmField
val CODEC: Codec<LevelUpCriterion> = RecordCodecBuilder.create { it.group(
EntityPredicate.ADVANCEMENT_CODEC.optionalFieldOf("player").forGetter(LevelUpCriterion::playerCtx),
Codec.INT.optionalFieldOf("level", 0).forGetter(LevelUpCriterion::level),
@@ -43,4 +42,4 @@ class LevelUpCriterion(
return level == context.level && evolutionCheck == evolved
}
}
}
@@ -24,7 +24,6 @@ class PartyCheckCriterion(
): SimpleCriterionCondition<PlayerPartyStore>(playerCtx) {
companion object {
@JvmField
val CODEC: Codec<PartyCheckCriterion> = RecordCodecBuilder.create { it.group(
EntityPredicate.ADVANCEMENT_CODEC.optionalFieldOf("player").forGetter(PartyCheckCriterion::playerCtx),
ResourceLocation.CODEC.listOf().optionalFieldOf("party", listOf()).forGetter(PartyCheckCriterion::party)
@@ -48,4 +47,4 @@ class PartyCheckCriterion(
}
return matches.containsAll(party) && matches.size == party.size
}
}
}
@@ -23,7 +23,6 @@ class PlantTumblestoneCriterion(
): SimpleCriterionCondition<PlantTumblestoneContext>(playerCtx) {
companion object {
@JvmField
val CODEC: Codec<PlantTumblestoneCriterion> = RecordCodecBuilder.create { it.group(
ContextAwarePredicate.CODEC.optionalFieldOf("player").forGetter(PlantTumblestoneCriterion::playerCtx)
).apply(it, ::PlantTumblestoneCriterion) }
@@ -24,7 +24,6 @@ class PokemonCriterion(
): SimpleCriterionCondition<Pokemon>(playerCtx) {
companion object {
@JvmField
val CODEC: Codec<PokemonCriterion> = RecordCodecBuilder.create { it.group(
EntityPredicate.ADVANCEMENT_CODEC.optionalFieldOf("player").forGetter(PokemonCriterion::playerCtx),
Codec.STRING.optionalFieldOf("species", "any").forGetter(PokemonCriterion::species),
@@ -36,4 +35,4 @@ class PokemonCriterion(
var speciesCheck = (species.equals(context.species.resourceIdentifier.path) || species.equals(context.species.resourceIdentifier.toString())) || species.equals("any")
return speciesCheck && properties.matches(context)
}
}
}
@@ -25,7 +25,6 @@ class PokemonInteractCriterion(
val item: String
): SimpleCriterionCondition<PokemonInteractContext>(playerCtx) {
companion object {
@JvmField
val CODEC: Codec<PokemonInteractCriterion> = RecordCodecBuilder.create { it.group(
EntityPredicate.ADVANCEMENT_CODEC.optionalFieldOf("player").forGetter(PokemonInteractCriterion::playerCtx),
Codec.STRING.optionalFieldOf("species", "any").forGetter(PokemonInteractCriterion::species),
@@ -36,4 +35,4 @@ class PokemonInteractCriterion(
override fun matches(player: ServerPlayer, context: PokemonInteractContext): Boolean {
return (context.species == this.species.asIdentifierDefaultingNamespace() || this.species == "any") && (context.item == this.item.asIdentifierDefaultingNamespace() || this.item == "any")
}
}
}
@@ -26,7 +26,6 @@ class ReelInPokemonCriterionCondition(
) : SimpleCriterionCondition<ReelInPokemonContext>(playerCtx) {
companion object {
@JvmField
val CODEC: Codec<ReelInPokemonCriterionCondition> = RecordCodecBuilder.create { it.group(
EntityPredicate.ADVANCEMENT_CODEC.optionalFieldOf("player").forGetter { it.playerCtx },
Codec.STRING.optionalFieldOf("species", "any").forGetter { it.species },
@@ -38,4 +37,4 @@ class ReelInPokemonCriterionCondition(
return (context.species == this.species.asIdentifierDefaultingNamespace() || this.species == "any")
&& (context.baitId == this.baitId.asIdentifierDefaultingNamespace() || this.baitId == "any" || this.baitId == "empty_bait")
}
}
}
@@ -28,7 +28,6 @@ class TradePokemonCriterion(
): SimpleCriterionCondition<TradePokemonContext>(playerCtx) {
companion object {
@JvmField
val CODEC: Codec<TradePokemonCriterion> = RecordCodecBuilder.create { it.group(
EntityPredicate.ADVANCEMENT_CODEC.optionalFieldOf("player").forGetter(TradePokemonCriterion::playerCtx),
Codec.STRING.optionalFieldOf("traded", "any").forGetter(TradePokemonCriterion::traded),
@@ -18,7 +18,7 @@ import net.minecraft.resources.ResourceKey
object CobblemonEntitySubPredicates : PlatformRegistry<Registry<MapCodec<out EntitySubPredicate>>, ResourceKey<Registry<MapCodec<out EntitySubPredicate>>>, MapCodec<out EntitySubPredicate>>() {
@JvmField
@JvmStatic
val POKE_POBBER = this.create("poke_bobber", FishingBobberPredicate.CODEC)
override val registry: Registry<MapCodec<out EntitySubPredicate>> = BuiltInRegistries.ENTITY_SUB_PREDICATE_TYPE
@@ -24,7 +24,7 @@ class FishingBobberPredicate(val inOpenWater: Boolean) : EntitySubPredicate {
return (entity as? PokeRodFishingBobberEntity)?.inOpenWater == this.inOpenWater
}
companion object {
@JvmField
@JvmStatic
val CODEC: MapCodec<FishingBobberPredicate> = RecordCodecBuilder.mapCodec { instance ->
instance.group(
Codec.BOOL.fieldOf("in_open_water").forGetter(FishingBobberPredicate::inOpenWater)
@@ -22,7 +22,7 @@ enum class Priority : StringRepresentable {
companion object {
@JvmField
@JvmStatic
val CODEC: Codec<Priority> = StringRepresentable.fromEnum(Priority::values)
}
@@ -104,7 +104,7 @@ open class Ability internal constructor(var template: AbilityTemplate, forced: B
companion object {
@JvmField
@JvmStatic
val CODEC: Codec<Ability> = RecordCodecBuilder.create {
it.group(
AbilityTemplate.CODEC.fieldOf(DataKeys.POKEMON_ABILITY_NAME).forGetter(Ability::template),
@@ -47,7 +47,7 @@ class AbilityTemplate(
companion object {
@JvmField
@JvmStatic
val CODEC: Codec<AbilityTemplate> = CodecUtils.createByStringCodec(
Abilities::getOrDummy,
AbilityTemplate::name
@@ -29,7 +29,6 @@ interface PotentialAbility {
val type: PotentialAbilityType<*>
fun isSatisfiedBy(aspects: Set<String>): Boolean
companion object {
@JvmField
val types = mutableListOf<PotentialAbilityType<*>>()
}
}
@@ -52,4 +51,5 @@ open class CommonAbility(override val template: AbilityTemplate) : PotentialAbil
override val priority = Priority.LOWEST
override val type = CommonAbilityType
override fun isSatisfiedBy(aspects: Set<String>) = true
}
}
@@ -26,9 +26,8 @@ class AttackHostileMobsTaskConfig : SingleTaskConfig {
): BehaviorControl<in LivingEntity>? {
return AttackHostileMobsTask.create()
}
companion object {
@JvmField
val CODEC: Codec<AttackHostileMobsTaskConfig> = Codec.unit(AttackHostileMobsTaskConfig())
}
}
@@ -17,6 +17,7 @@ import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMostSpecificMoLangV
import com.cobblemon.mod.common.entity.OmniPathingEntity
import com.cobblemon.mod.common.entity.ai.CobblemonRandomSurfacePos
import com.cobblemon.mod.common.entity.ai.CobblemonWalkTarget
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import com.cobblemon.mod.common.util.asExpression
import com.cobblemon.mod.common.util.mainThreadRuntime
import com.cobblemon.mod.common.util.resolveFloat
@@ -184,6 +185,12 @@ class WanderTaskConfig : SingleTaskConfig {
if (targetVec == null) continue
// Ignore pathing targets outside of the pasture zone if the pokemon is pastured.
val tethering = (entity as? PokemonEntity)?.tethering
if (tethering?.canRoamTo(BlockPos.containing(targetVec)) == false) {
continue
}
pos = applyHeightConstraints(
pos = BlockPos.containing(targetVec),
minimumHeight = minimumHeight,
@@ -99,7 +99,6 @@ enum class Apricorn : StringRepresentable {
override fun getSerializedName() = this.name.lowercase()
companion object {
@JvmField
val CODEC: Codec<Apricorn> = StringRepresentable.fromValues(::values)
}
}
@@ -304,7 +304,8 @@ open class PokemonBattle(
.forEach{it.pokemon.heal()}
actors.forEach { actor ->
actor.pokemonList.forEach { battlePokemon ->
battlePokemon.entity?.let { entity -> battlePokemon.postBattleEntityOperation(entity) }
battlePokemon.postBattlePokemonOperations.forEach { it(battlePokemon) }
battlePokemon.entity?.let { entity -> battlePokemon.postBattleEntityOperations.forEach { it(entity) } }
if (battlePokemon.effectedPokemon.entity != null
&& battlePokemon.effectedPokemon.entity?.beamMode == 0
&& battlePokemon.effectedPokemon.entity?.platform != PlatformType.NONE) {
@@ -498,8 +499,8 @@ open class PokemonBattle(
}
fun stop() {
end()
writeShowdownAction(">forcetie") // This will terminate the Showdown connection
end()
}
fun checkForInputDispatch() {
@@ -24,7 +24,6 @@ class AllBiomeCondition(val minGroveSize: Int, val maxGroveSize: Int) : BerrySpa
}
companion object {
@JvmField
val ID = cobblemonResource("all_biome")
}
}
}
@@ -26,7 +26,6 @@ class PreferredBiomeCondition(val minGroveSize: Int, val maxGroveSize: Int) : Be
}
companion object {
@JvmField
val ID = cobblemonResource("preferred_biome")
}
}
}
@@ -24,7 +24,6 @@ class SpecificBiomeCondition : BerrySpawnCondition {
override fun getGroveSize(random: RandomSource) = random.nextIntBetweenInclusive(minGroveSize, maxGroveSize)
companion object {
@JvmField
val ID = cobblemonResource("specific_biome")
}
}
@@ -27,7 +27,6 @@ enum class Flavour(val colour: Int): StringRepresentable {
override fun getSerializedName() = name
companion object {
@JvmField
val CODEC = StringRepresentable.fromEnum<Flavour> { Flavour.entries.toTypedArray() }
}
}
}
@@ -17,7 +17,6 @@ data class Food(
val saturation: Float = 0f,
) {
companion object {
@JvmField
val CODEC: Codec<Food> = RecordCodecBuilder.create { builder ->
builder.group(
Codec.INT.optionalFieldOf("hunger", 0).forGetter { it.hunger },
@@ -38,7 +38,6 @@ data class Seasoning(
val mobEffects: List<SerializableMobEffectInstance>? = null
) {
companion object {
@JvmField
val CODEC: Codec<Seasoning> = RecordCodecBuilder.create { builder ->
builder.group(
ITEM_REGISTRY_LIKE_CODEC.fieldOf("ingredient").forGetter { it.ingredient },
@@ -59,7 +58,6 @@ data class Seasoning(
}
}
@JvmField
val STREAM_CODEC: StreamCodec<ByteBuf, Seasoning> = ByteBufCodecs.fromCodec(CODEC)
}
}
}
@@ -31,7 +31,6 @@ data class SerializableMobEffectInstance(
}
companion object {
@JvmField
val CODEC: Codec<SerializableMobEffectInstance> = RecordCodecBuilder.create { builder ->
builder.group(
ResourceLocation.CODEC.fieldOf("effect").forGetter { it.effect },
@@ -43,4 +42,4 @@ data class SerializableMobEffectInstance(
).apply(builder, ::SerializableMobEffectInstance)
}
}
}
}
@@ -26,11 +26,9 @@ class Dialogue(
val initializationAction: DialogueAction = FunctionDialogueAction { _, _ -> }
) {
companion object {
@JvmField
val DEFAULT_BACKGROUND = cobblemonResource("textures/gui/dialogue/dialogue_box.png")
@JvmOverloads
@JvmStatic
fun of(
pages: Iterable<DialoguePage>,
background: ResourceLocation = DEFAULT_BACKGROUND,
@@ -46,7 +44,6 @@ class Dialogue(
}
@JvmOverloads
@JvmStatic
fun of(
pages: Iterable<DialoguePage>,
background: ResourceLocation = DEFAULT_BACKGROUND,
@@ -23,7 +23,7 @@ import com.cobblemon.mod.common.util.resolve
*/
interface DialogueAction {
companion object {
@JvmField
@JvmStatic
val types = mutableMapOf<String, Class<out DialogueAction>>()
}
@@ -23,7 +23,6 @@ sealed interface DialogueFaceProvider {
val isLeftSide: Boolean
companion object {
@JvmField
val types = mutableMapOf(
"artificial" to ArtificialDialogueFaceProvider::class.java,
"player" to PlayerDialogueFaceProvider::class.java,
@@ -58,9 +58,4 @@ object DialogueManager {
DialogueClosedPacket(activeDialogue.dialogueId).sendToPlayer(playerEntity)
activeDialogues.remove(playerEntity.uuid)
}
@JvmStatic
fun getDialogue(playerEntity: ServerPlayer): ActiveDialogue? {
return activeDialogues[playerEntity.uuid]
}
}
@@ -38,7 +38,6 @@ class DialoguePage(
) {
companion object {
@JvmOverloads
@JvmStatic
fun of(
/** The ID is optional, but if you want to be able to jump to this page from other pages then you probably want to set this. */
id: String = "",
@@ -79,4 +78,4 @@ class DialoguePage(
)
)
}
}
}
@@ -20,7 +20,6 @@ import com.cobblemon.mod.common.util.resolveBoolean
*/
interface DialoguePredicate {
companion object {
@JvmField
val types = mutableMapOf<String, Class<out DialoguePredicate>>()
}
@@ -24,7 +24,6 @@ import net.minecraft.network.chat.MutableComponent
*/
interface DialogueText {
companion object {
@JvmField
val types = mutableMapOf<String, Class<out DialogueText>>(
"expression" to ExpressionLikeDialogueText::class.java,
)
@@ -26,10 +26,7 @@ interface DropEntry {
companion object {
val entryTypes = mutableMapOf<String, Class<out DropEntry>>()
var defaultType: Class<out DropEntry>? = null
@JvmStatic
fun getByName(name: String) = entryTypes[name]
@JvmOverloads
@JvmStatic
fun <T : DropEntry> register(name: String, clazz: Class<T>, isDefault: Boolean = false) {
entryTypes[name] = clazz
if (isDefault) {
@@ -63,16 +63,13 @@ interface EntityEffect {
register(TransformEffect.ID, TransformEffect::class, ::TransformEffect)
}
@JvmStatic
fun <T : EntityEffect> register(id: String, type: KClass<T>, default: () -> T) {
effects[id] = type
defaults[id] = default
}
@JvmStatic
fun createDefault(id: String): EntityEffect? = defaults[id]?.invoke()
@JvmStatic
fun loadFromNbt(nbt: CompoundTag, registryLookup: HolderLookup.Provider): EntityEffect? {
if (nbt.contains(DataKeys.ENTITY_EFFECT_ID)) {
val id = nbt.getString(DataKeys.ENTITY_EFFECT_ID)
@@ -103,4 +100,4 @@ interface MocKEffect : PhysicalEffect {
val exposedBall: PokeBall?
get() = this.mock.pokeball?.let { PokeBalls.getPokeBall(it.asIdentifierDefaultingNamespace()) }
}
}
@@ -9,6 +9,7 @@
package com.cobblemon.mod.common.api.events.battles
import com.bedrockk.molang.runtime.value.MoValue
import com.bedrockk.molang.runtime.value.StringValue
import com.cobblemon.mod.common.api.battles.interpreter.BattleContext
import com.cobblemon.mod.common.api.battles.model.PokemonBattle
import com.cobblemon.mod.common.api.battles.model.actor.ActorType
@@ -25,7 +26,8 @@ import com.cobblemon.mod.common.util.asArrayValue
data class BattleFaintedEvent(
override val battle: PokemonBattle,
val killed: BattlePokemon,
val context: BattleContext
val context: BattleContext,
val pnx: String
) : BattleEvent {
val structContext = mutableMapOf<String, MoValue>(
"battle" to battle.struct,
@@ -33,6 +35,7 @@ data class BattleFaintedEvent(
"npcs" to battle.actors.filter { it.type == ActorType.NPC }.asArrayValue { it.struct },
"wild_pokemon" to battle.actors.filter { it.type == ActorType.WILD }.asArrayValue { it.struct },
"pokemon" to killed.struct,
"context" to context.getStruct()
"context" to context.getStruct(),
"pnx" to StringValue(pnx)
)
}
}
@@ -8,10 +8,12 @@
package com.cobblemon.mod.common.api.events.battles.instruction
import com.bedrockk.molang.runtime.value.MoValue
import com.bedrockk.molang.runtime.value.StringValue
import com.cobblemon.mod.common.api.battles.model.PokemonBattle
import com.cobblemon.mod.common.api.battles.model.actor.ActorType
import com.cobblemon.mod.common.api.events.battles.BattleEvent
import com.cobblemon.mod.common.battles.dispatch.InterpreterInstruction
import com.cobblemon.mod.common.battles.pokemon.BattlePokemon
import com.cobblemon.mod.common.util.asArrayValue
@@ -35,7 +35,6 @@ class SpawnBait(
constructor(type: ResourceLocation, subcategory: Optional<ResourceLocation>, chance: Double, value: Double) : this(type, subcategory.orElse(null), chance, value)
companion object {
@JvmField
val CODEC = RecordCodecBuilder.create<Effect> { instance ->
instance.group(
ResourceLocation.CODEC.fieldOf("type").forGetter { it.type },
@@ -48,7 +47,6 @@ class SpawnBait(
}
companion object {
@JvmField
val CODEC = RecordCodecBuilder.create<SpawnBait> { instance ->
instance.group(
ITEM_REGISTRY_LIKE_CODEC.fieldOf("item").forGetter { it.item },
@@ -56,7 +54,6 @@ class SpawnBait(
).apply(instance, ::SpawnBait)
}
@JvmField
val STREAM_CODEC = ByteBufCodecs.fromCodec(CODEC)
}
@@ -99,4 +96,6 @@ class SpawnBait(
}
}
}
}
}
@@ -59,40 +59,32 @@ object PokemonInteractions : JsonDataRegistry<PokemonInteractionSet> {
.setPrettyPrinting()
.create()
val speciesInteractions = mutableListOf<PokemonInteractionSet>()
val generalInteractions = mutableListOf<PokemonInteractionSet>()
val interactions = mutableListOf<PokemonInteractionSet>()
override fun sync(player: ServerPlayer) {
PokemonInteractionsSyncPacket(
speciesInteractions,
generalInteractions,
).sendToPlayer(player)
PokemonInteractionsSyncPacket(interactions).sendToPlayer(player)
}
override fun reload(data: Map<ResourceLocation, PokemonInteractionSet>) {
speciesInteractions.clear()
generalInteractions.clear()
val split = data.entries.partition { it.value.requirements.any { requirement -> requirement is PokemonPropertiesRequirement && requirement.target.species != null } }
speciesInteractions.addAll(split.first.map {it.value})
generalInteractions.addAll(split.second.map {it.value})
Cobblemon.LOGGER.info("Loaded {} Pokémon interaction sets", data.size)
interactions.clear()
val split = data.entries
.partition {
it.value.requirements.any { requirement -> requirement is PokemonPropertiesRequirement && requirement.target.species != null }
}
// Put the species specific interactions first as they take priority
interactions.addAll(split.first.map {it.value})
interactions.addAll(split.second.map {it.value})
Cobblemon.LOGGER.info("Loaded {} Pokémon interaction sets", interactions.size)
}
fun findInteraction(pokemon: PokemonEntity): PokemonInteraction? {
val setCheck: (PokemonInteractionSet) -> Boolean = { it.requirements.all { req -> req.check(pokemon.pokemon) }}
val interactionCheck: (PokemonInteraction) -> Boolean = { it.requirements.all { req -> req.check(pokemon.pokemon) } && !pokemon.pokemon.isOnInteractionCooldown(it.grouping) }
// species-specific interactions take priority
val validInteractions = speciesInteractions
return interactions
.filter(setCheck)
.flatMap { it.interactions }
.filter(interactionCheck)
.toMutableList()
if (validInteractions.isEmpty()) { // if all species-specific interactions are absent/on cooldown, fallback to more generic ones
validInteractions.addAll(generalInteractions.filter(setCheck).flatMap { it.interactions }
.filter(interactionCheck)
)
}
return validInteractions.randomOrNull()
.firstOrNull(interactionCheck)
}
}
@@ -43,17 +43,9 @@ data class PokemonInteractionSet(
companion object {
fun decode(buffer: FriendlyByteBuf): PokemonInteractionSet {
val requirements = buffer.readList { it ->
CobblemonRequirementAdapter.decode(it)
}
val interactions = buffer.readList { it ->
PokemonInteraction.decode(it)
}
return PokemonInteractionSet(
requirements,
interactions,
)
val requirements = buffer.readList(CobblemonRequirementAdapter::decode)
val interactions = buffer.readList(PokemonInteraction::decode)
return PokemonInteractionSet(requirements, interactions)
}
}
}
@@ -223,7 +223,6 @@ abstract class RequestManager<T : ServerPlayerActionRequest> {
companion object {
private val managers = mutableListOf<RequestManager<*>>()
@JvmStatic
fun register(manager: RequestManager<*>) = managers.add(manager)
fun onLogoff(player: ServerPlayer) = managers.forEach { it.onLogoff(player) }
@@ -59,7 +59,7 @@ interface AbilityChanger<T : PotentialAbility> {
*
* While this can be used in custom data scenarios this functions most "game-like" if the Pokémon only has 2 common abilities.
*/
@JvmField
@JvmStatic
val COMMON_ABILITY: AbilityChanger<CommonAbility> = AbilityTypeChanger(CommonAbilityType) { other -> other == CommonAbilityType }
/**
@@ -67,7 +67,7 @@ interface AbilityChanger<T : PotentialAbility> {
*
* While this can be used in custom data scenarios this functions most "game-like" if the Pokémon only has 1 hidden ability.
*/
@JvmField
@JvmStatic
val HIDDEN_ABILITY: AbilityChanger<HiddenAbility> = AbilityTypeChanger(HiddenAbilityType) { other -> other == CommonAbilityType || other == HiddenAbilityType }
}
@@ -35,11 +35,10 @@ interface ExpressionLike {
fun resolveObject(runtime: MoLangRuntime) = resolve(runtime) as ObjectValue<*>
companion object {
@JvmField
val CODEC: Codec<ExpressionLike> = Codec.STRING.xmap({
it.asExpressionLike()
}) {
it.getString()
}
}
}
}
@@ -145,6 +145,7 @@ import net.minecraft.world.entity.item.ItemEntity
import net.minecraft.world.entity.monster.Monster
import net.minecraft.world.entity.player.Player
import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.enchantment.EnchantmentHelper
import net.minecraft.world.level.ClipContext
import net.minecraft.world.level.GameType
import net.minecraft.world.level.Level
@@ -368,6 +369,11 @@ object MoLangFunctions {
val b = format.parse(dateB)
DoubleValue(a.after(b))
},
"get_move_from_id" to java.util.function.Function { params ->
val moveId = params.getString(0)
val moveTemplate = Moves.getByName(moveId)
return@Function moveTemplate?.struct ?: DoubleValue.ZERO
},
"create_simple_party_provider" to java.util.function.Function { params ->
val partyProvider = SimplePartyProvider()
return@Function partyProvider.struct
@@ -378,6 +384,13 @@ object MoLangFunctions {
val pickupItem = ObtainableItem(item = item, pickupPriority = pickupPriority)
return@Function pickupItem.struct
},
"create_itemstack" to java.util.function.Function { params ->
val itemId = params.getString(0).asIdentifierDefaultingNamespace()
val item = BuiltInRegistries.ITEM.get(itemId) ?: return@Function DoubleValue.ZERO
val count = params.getIntOrNull(1) ?: 1
val itemStack = ItemStack(item, count)
return@Function ObjectValue(itemStack)
},
"file" to java.util.function.Function { MoLangLoadedFilesCache.struct }
)
val biomeFunctions = mutableListOf<(Holder<Biome>) -> HashMap<String, java.util.function.Function<MoParams, Any>>>()
@@ -583,6 +596,62 @@ object MoLangFunctions {
}
return@put items
}
map.put("has_inventory_space") { _ ->
val inventory = player.inventory
return@put if (inventory.getFreeSlot() != -1) DoubleValue.ONE else DoubleValue.ZERO
}
map.put("set_inventory_slot") { params ->
val slot = params.getInt(0)
val inventory = player.inventory
if (slot !in 0 until inventory.containerSize) return@put DoubleValue.ZERO
val value = params.getOrNull<MoValue>(1) ?: return@put DoubleValue.ZERO
val stack: ItemStack? = when (value) {
is ObjectValue<*> -> value.obj as? ItemStack
is StringValue -> {
val id = ResourceLocation.parse(value.value)
val item = player.registryAccess().registryOrThrow(Registries.ITEM).get(id) ?: return@put DoubleValue.ZERO
ItemStack(item)
}
else -> null
}
if (stack == null) return@put DoubleValue.ZERO
inventory.setItem(slot, stack)
return@put DoubleValue.ONE
}
map.put("give_item") { params ->
val inventory = player.inventory
val freeSlot = inventory.getFreeSlot()
val value = params.getOrNull<MoValue>(0) ?: return@put DoubleValue.ZERO
val dropIfFull = params.getBooleanOrNull(1) ?: false
val stack: ItemStack? = when (value) {
is ObjectValue<*> -> value.obj as? ItemStack
is StringValue -> {
val id = ResourceLocation.parse(value.value)
val item = player.registryAccess().registryOrThrow(Registries.ITEM).get(id) ?: return@put DoubleValue.ZERO
ItemStack(item)
}
else -> null
}
if (stack == null) return@put DoubleValue.ZERO
if (freeSlot == -1) {
if (dropIfFull) {
player.drop(stack, false)
return@put DoubleValue.ONE
} else {
return@put DoubleValue.ZERO
}
}
inventory.setItem(freeSlot, stack)
return@put DoubleValue.ONE
}
map.put("face") { params -> ObjectValue(PlayerDialogueFaceProvider(player.uuid, params.getBooleanOrNull(0) != false)) }
map.put("swing_hand") { _ -> player.swing(player.usedItemHand) }
map.put("food_level") { _ -> DoubleValue(player.foodData.foodLevel) }
@@ -626,8 +695,7 @@ object MoLangFunctions {
}
map.put("active_dialogue") { _ ->
if (player.isInDialogue) {
player.activeDialogue?.dialogueId.toString()
return@put DoubleValue.ONE
return@put player.activeDialogue?.toMoLangStruct() ?: DoubleValue.ZERO
} else {
DoubleValue.ZERO
}
@@ -804,6 +872,8 @@ object MoLangFunctions {
DoubleValue(value)
}
map.put("get_starter_uuid") { _ -> Cobblemon.playerDataManager.getGenericData(player).starterUUID?.let{ StringValue(it.toString()) } ?: DoubleValue.ZERO }
map.put("has_chosen_starter") { _ -> DoubleValue(Cobblemon.playerDataManager.getGenericData(player).starterSelected) }
}
map
}
@@ -824,6 +894,15 @@ object MoLangFunctions {
map.put("is_of") { params -> DoubleValue(holder.`is`(params.getString(0).asIdentifierDefaultingNamespace())) }
map.put("is_in") { params -> DoubleValue(holder.`is`(TagKey.create(Registries.ITEM, params.getString(0).replace("#", "").asIdentifierDefaultingNamespace()))) }
map.put("is_food") { params -> DoubleValue(stack.has(DataComponents.FOOD)) }
map.put("is_enchanted") { params -> DoubleValue(stack.hasFoil()) }
map.put("has_enchantment") { params ->
val enchantmentId = params.getString(0).asIdentifierDefaultingNamespace()
val minLevel = params.getIntOrNull(1) ?: 1
val enchantmentRegistry = registryAccess.registryOrThrow(Registries.ENCHANTMENT)
val holder = enchantmentRegistry.getHolder(enchantmentId).orElse(null) ?: return@put DoubleValue.ZERO
val level = EnchantmentHelper.getItemEnchantmentLevel(holder, stack)
return@put DoubleValue(level >= minLevel)
}
return@mutableListOf map
}
)
@@ -1862,8 +1941,7 @@ object MoLangFunctions {
return@put DoubleValue(if (pokemon.addRideBoost(stat, value)) 1.0 else 0.0)
}
map.put("initialize_moveset") { params ->
val preferLatest = params.getBooleanOrNull(0) ?: true
pokemon.initializeMoveset(preferLatest)
pokemon.initializeMovesetFromDefault()
return@put DoubleValue.ONE
}
map.put("validate_moveset") { params ->
@@ -2748,8 +2826,8 @@ object MoLangFunctions {
}
variable
}
else -> null
} ?: throw IllegalArgumentException("Invalid NBT element type: ${nbt.type}")
else -> VariableStruct()
}
}
}
@@ -112,7 +112,7 @@ class BenchedMoves : Iterable<BenchedMove> {
}
companion object {
@JvmField
@JvmStatic
val CODEC: Codec<BenchedMoves> = Codec.list(BenchedMove.CODEC)
.xmap(
{ moveList ->
@@ -144,7 +144,6 @@ data class BenchedMove(val moveTemplate: MoveTemplate, val ppRaisedStages: Int)
}
companion object {
@JvmStatic
fun loadFromNBT(nbt: CompoundTag): BenchedMove {
val name = nbt.getString(DataKeys.POKEMON_MOVESET_MOVENAME)
return BenchedMove(
@@ -153,7 +152,6 @@ data class BenchedMove(val moveTemplate: MoveTemplate, val ppRaisedStages: Int)
)
}
@JvmStatic
fun loadFromJSON(json: JsonObject): BenchedMove {
val name = json.get(DataKeys.POKEMON_MOVESET_MOVENAME).asString
return BenchedMove(
@@ -162,7 +160,6 @@ data class BenchedMove(val moveTemplate: MoveTemplate, val ppRaisedStages: Int)
)
}
@JvmStatic
fun loadFromBuffer(buffer: RegistryFriendlyByteBuf): BenchedMove {
val name = buffer.readString()
return BenchedMove(
@@ -171,7 +168,7 @@ data class BenchedMove(val moveTemplate: MoveTemplate, val ppRaisedStages: Int)
)
}
@JvmField
@JvmStatic
val CODEC: Codec<BenchedMove> = RecordCodecBuilder.create { it.group(
MoveTemplate.BY_STRING_CODEC.fieldOf(DataKeys.POKEMON_MOVESET_MOVENAME).forGetter(BenchedMove::moveTemplate),
Codec.intRange(0, 3).fieldOf(DataKeys.POKEMON_MOVESET_RAISED_PP_STAGES).forGetter(BenchedMove::ppRaisedStages)
@@ -0,0 +1,57 @@
/*
* 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.pokemon.FormData
import com.cobblemon.mod.common.util.cobblemonResource
import net.minecraft.resources.ResourceLocation
/**
* This is all you need tbh. A moveset builder that picks moves from up to 4 slots of move selectors.
*
* @author Hiroku
* @since December 5th, 2025
*/
class DefaultMovesetBuilder : MovesetBuilder {
companion object {
val TYPE = cobblemonResource("default")
}
override val type: ResourceLocation = TYPE
override var id: ResourceLocation = cobblemonResource("temp") // replaced on load.
val slot1: List<MoveSelector> = listOf()
val slot2: List<MoveSelector> = listOf()
val slot3: List<MoveSelector> = listOf()
val slot4: List<MoveSelector> = listOf()
override fun build(form: FormData, level: Int): MoveSet {
val chosenMoves = mutableSetOf<MoveTemplate>()
tryAddMoveFromSlot(form, level, slot1, chosenMoves)
tryAddMoveFromSlot(form, level, slot2, chosenMoves)
tryAddMoveFromSlot(form, level, slot3, chosenMoves)
tryAddMoveFromSlot(form, level, slot4, chosenMoves)
if (chosenMoves.isEmpty()) {
chosenMoves.add(Moves.getExceptional())
}
val moveset = MoveSet()
chosenMoves.map(MoveTemplate::create).forEach(moveset::add)
return moveset
}
fun tryAddMoveFromSlot(form: FormData, level: Int, selectors: List<MoveSelector>, chosenMoves: MutableSet<MoveTemplate>) {
for (selector in selectors) {
val move = selector(form, form.moves, level, chosenMoves)
if (move != null) {
chosenMoves.add(move)
return
}
}
}
}
@@ -149,14 +149,12 @@ open class Move(
}
companion object {
@JvmStatic
fun loadFromNBT(nbt: CompoundTag): Move {
val moveName = nbt.getString(DataKeys.POKEMON_MOVESET_MOVENAME)
val template = Moves.getByNameOrDummy(moveName)
return template.create(nbt.getInt(DataKeys.POKEMON_MOVESET_MOVEPP), nbt.getInt(DataKeys.POKEMON_MOVESET_RAISED_PP_STAGES))
}
@JvmStatic
fun loadFromJSON(json: JsonObject): Move {
val moveName = json.get(DataKeys.POKEMON_MOVESET_MOVENAME).asString
val template = Moves.getByNameOrDummy(moveName)
@@ -165,7 +163,6 @@ open class Move(
return Move(template, currentPp, raisedPpStages)
}
@JvmStatic
fun loadFromBuffer(buffer: RegistryFriendlyByteBuf): Move {
val moveName = buffer.readString()
val currentPp = buffer.readSizedInt(IntSize.U_BYTE)
@@ -174,7 +171,7 @@ open class Move(
return template.create(currentPp, raisedPpStages)
}
@JvmField
@JvmStatic
val CODEC: Codec<Move> = RecordCodecBuilder.create { it.group(
MoveTemplate.BY_STRING_CODEC.fieldOf(DataKeys.POKEMON_MOVESET_MOVENAME).forGetter(Move::template),
Codec.intRange(0, Int.MAX_VALUE).fieldOf(DataKeys.POKEMON_MOVESET_MOVEPP).forGetter(Move::currentPp),
@@ -0,0 +1,148 @@
/*
* 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.api.moves.categories.DamageCategories
import com.cobblemon.mod.common.api.pokemon.moves.Learnset
import com.cobblemon.mod.common.api.pokemon.stats.Stats
import com.cobblemon.mod.common.pokemon.FormData
import com.cobblemon.mod.common.util.weightedSelection
/**
* A function that selects a move from a given [Learnset] for a particular [FormData] at a certain level,
* taking into account any moves that have already been chosen for the moveset.
*
* @author Hiroku
* @since December 5th, 2025
*/
fun interface MoveSelector {
operator fun invoke(form: FormData, learnset: Learnset, level: Int, chosenMoves: Set<MoveTemplate>): MoveTemplate?
companion object {
val NONE = MoveSelector { _, _, _, _ -> null }
val LAST_LEVELUP = MoveSelector { form, learnset, level, chosenMoves ->
val levels = learnset.levelUpMoves.keys.filter { it <= level }.sortedDescending()
levels.forEach {
val moves = (learnset.levelUpMoves[it] ?: return@forEach) - chosenMoves
if (moves.isNotEmpty()) {
return@MoveSelector moves.weightedSelection { it.getSelectionWeight(form) }
}
}
return@MoveSelector null
}
val LAST_OFFENSIVE = MoveSelector { form, learnset, level, chosenMoves ->
val levels = learnset.levelUpMoves.keys.filter { it <= level }.sortedDescending()
levels.forEach {
val moves = (learnset.levelUpMoves[it]?.filter { it.damageCategory != DamageCategories.STATUS } ?: return@forEach) - chosenMoves
if (moves.isNotEmpty()) {
return@MoveSelector moves.weightedSelection { it.getSelectionWeight(form) }
}
}
return@MoveSelector null
}
val LAST_SUITABLE_OFFENSIVE = MoveSelector { form, learnset, level, chosenMoves ->
val levels = learnset.levelUpMoves.keys.filter { it <= level }.sortedDescending()
val suitableCategories = if (form.baseStats[Stats.ATTACK]!! > form.baseStats[Stats.SPECIAL_ATTACK]!!) {
setOf(DamageCategories.PHYSICAL)
} else if (form.baseStats[Stats.SPECIAL_ATTACK]!! > form.baseStats[Stats.ATTACK]!!) {
setOf(DamageCategories.SPECIAL)
} else {
setOf(DamageCategories.PHYSICAL, DamageCategories.SPECIAL)
}
levels.forEach {
val moves = (learnset.levelUpMoves[it]?.filter { it.damageCategory in suitableCategories } ?: return@forEach) - chosenMoves
if (moves.isNotEmpty()) {
return@MoveSelector moves.weightedSelection { it.getSelectionWeight(form) }
}
}
return@MoveSelector null
}
val LAST_STATUS = MoveSelector { form, learnset, level, chosenMoves ->
val levels = learnset.levelUpMoves.keys.filter { it <= level }.sortedDescending()
levels.forEach {
val moves = (learnset.levelUpMoves[it]?.filter { it.damageCategory == DamageCategories.STATUS } ?: return@forEach) - chosenMoves
if (moves.isNotEmpty()) {
return@MoveSelector moves.weightedSelection { it.getSelectionWeight(form) }
}
}
return@MoveSelector null
}
val STAB = MoveSelector { form, learnset, level, chosenMoves ->
val moves = learnset.getLevelUpMovesUpTo(level) - chosenMoves
val stabMoves = moves.filter { it.elementalType in form.types && it.damageCategory != DamageCategories.STATUS }
return@MoveSelector stabMoves.weightedSelection { it.getSelectionWeight(form) }
}
val STAB_PHYSICAL = MoveSelector { form, learnset, level, chosenMoves ->
val moves = learnset.getLevelUpMovesUpTo(level) - chosenMoves
val stabMoves = moves.filter { it.elementalType in form.types && it.damageCategory == DamageCategories.PHYSICAL }
return@MoveSelector stabMoves.weightedSelection { it.getSelectionWeight(form) }
}
val STAB_SPECIAL = MoveSelector { form, learnset, level, chosenMoves ->
val moves = learnset.getLevelUpMovesUpTo(level) - chosenMoves
val stabMoves = moves.filter { it.elementalType in form.types && it.damageCategory == DamageCategories.SPECIAL }
return@MoveSelector stabMoves.weightedSelection { it.getSelectionWeight(form) }
}
val PHYSICAL = MoveSelector { form, learnset, level, chosenMoves ->
val moves = learnset.getLevelUpMovesUpTo(level) - chosenMoves
val physicalMoves = moves.filter { it.damageCategory == DamageCategories.PHYSICAL }
return@MoveSelector physicalMoves.weightedSelection { it.getSelectionWeight(form) }
}
val SPECIAL = MoveSelector { form, learnset, level, chosenMoves ->
val moves = learnset.getLevelUpMovesUpTo(level) - chosenMoves
val specialMoves = moves.filter { it.damageCategory == DamageCategories.SPECIAL }
return@MoveSelector specialMoves.weightedSelection { it.getSelectionWeight(form) }
}
val OFFENSIVE = MoveSelector { form, learnset, level, chosenMoves ->
val moves = learnset.getLevelUpMovesUpTo(level) - chosenMoves
val offensiveMoves = moves.filter { it.damageCategory != DamageCategories.STATUS }
return@MoveSelector offensiveMoves.weightedSelection { it.getSelectionWeight(form) }
}
val RANDOM_LEVELUP = MoveSelector { form, learnset, level, chosenMoves ->
val moves = learnset.getLevelUpMovesUpTo(level) - chosenMoves
return@MoveSelector moves.weightedSelection { it.getSelectionWeight(form) }
}
val STATUS = MoveSelector { form, learnset, level, chosenMoves ->
val moves = learnset.getLevelUpMovesUpTo(level) - chosenMoves
val statusMoves = moves.filter { it.damageCategory == DamageCategories.STATUS }
return@MoveSelector statusMoves.weightedSelection { it.getSelectionWeight(form) }
}
val TM = MoveSelector { form, learnset, level, chosenMoves ->
val moves = learnset.tmMoves - chosenMoves - learnset.getLevelUpMovesUpTo(level)
return@MoveSelector moves.weightedSelection { it.getSelectionWeight(form) }
}
val STAB_TM = MoveSelector { form, learnset, level, chosenMoves ->
val moves = learnset.tmMoves - chosenMoves - learnset.getLevelUpMovesUpTo(level)
val stabMoves = moves.filter { it.elementalType in form.types }
return@MoveSelector stabMoves.weightedSelection { it.getSelectionWeight(form) }
}
val EGG = MoveSelector { form, learnset, level, chosenMoves ->
val moves = learnset.eggMoves - chosenMoves - learnset.getLevelUpMovesUpTo(level)
return@MoveSelector moves.weightedSelection { it.getSelectionWeight(form) }
}
val selectors = mutableMapOf(
"none" to NONE,
"last_levelup" to LAST_LEVELUP,
"last_offensive" to LAST_OFFENSIVE,
"last_suitable_offensive" to LAST_SUITABLE_OFFENSIVE,
"last_status" to LAST_STATUS,
"levelup" to RANDOM_LEVELUP,
"stab" to STAB,
"stab_physical" to STAB_PHYSICAL,
"stab_special" to STAB_SPECIAL,
"physical" to PHYSICAL,
"special" to SPECIAL,
"offensive" to OFFENSIVE,
"status" to STATUS,
"tm" to TM,
"stab_tm" to STAB_TM,
"egg" to EGG
)
}
}
@@ -208,7 +208,7 @@ class MoveSet : Iterable<Move> {
companion object {
const val MOVE_COUNT = 4
@JvmField
@JvmStatic
val CODEC: Codec<MoveSet> = Codec.list(Move.CODEC, 0, MOVE_COUNT)
.xmap(
{ moveList ->
@@ -12,12 +12,12 @@ import com.bedrockk.molang.runtime.struct.MoStruct
import com.bedrockk.molang.runtime.struct.QueryStruct
import com.bedrockk.molang.runtime.value.DoubleValue
import com.bedrockk.molang.runtime.value.StringValue
import com.cobblemon.mod.common.api.moves.animations.ActionEffectTimeline
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.pokemon.FormData
import com.cobblemon.mod.common.util.codec.CodecUtils
import com.cobblemon.mod.common.pokemon.Pokemon
import com.cobblemon.mod.common.util.lang
@@ -53,22 +53,26 @@ open class MoveTemplate(
val pp: Int,
val priority: Int,
val critRatio: Double,
val effectChances: Array<Double>
val effectChances: Array<Double>,
val weight: Float
) {
val struct: MoStruct by lazy {
QueryStruct(hashMapOf())
.addFunction("name") { StringValue(name) }
.addFunction("display_name") { StringValue(displayName.string) }
.addFunction("description") { StringValue(description.string) }
.addFunction("type") { StringValue(elementalType.showdownId) }
.addFunction("damage_category") { StringValue(damageCategory.name) }
.addFunction("power") { DoubleValue(power) }
.addFunction("target") { StringValue(target.name) }
.addFunction("accuracy") { DoubleValue(accuracy) }
.addFunction("pp") { DoubleValue(pp) }
.addFunction("max_pp") { DoubleValue(maxPp) }
.addFunction("priority") { DoubleValue(priority) }
.addFunction("crit_ratio") { DoubleValue(critRatio) }
.addFunction("weight") { DoubleValue(weight.toDouble()) }
}
val displayName: MutableComponent
get() = lang("move.$name")
val description: MutableComponent
@@ -86,14 +90,14 @@ open class MoveTemplate(
pp = 5,
priority = 0,
critRatio = 0.0,
effectChances = emptyArray()
effectChances = emptyArray(),
weight = 0F,
)
companion object {
@JvmStatic
fun dummy(name: String) = Dummy(name)
@JvmField
@JvmStatic
val BY_STRING_CODEC: Codec<MoveTemplate> = CodecUtils.createByStringCodec(
Moves::getByNameOrDummy,
MoveTemplate::name
@@ -158,4 +162,12 @@ open class MoveTemplate(
}
return this.elementalType
}
}
fun getSelectionWeight(form: FormData): Float {
return if (this in form.signatureMoves) {
weight * MovesetBuilder.signatureMoveWeightMultiplier
} else {
weight
}
}
}
@@ -10,15 +10,15 @@ 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.animations.ActionEffects
import com.cobblemon.mod.common.api.moves.categories.DamageCategories
import com.cobblemon.mod.common.api.reactive.SimpleObservable
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
import com.cobblemon.mod.common.util.asIdentifierDefaultingNamespace
import com.cobblemon.mod.common.util.cobblemonResource
import com.cobblemon.mod.common.util.fromJson
import com.google.gson.GsonBuilder
import com.google.gson.JsonArray
import com.google.gson.JsonObject
import net.minecraft.resources.ResourceLocation
@@ -46,6 +46,14 @@ object Moves : DataRegistry {
this.idMapping.clear()
this.moveScripts.clear()
val weights = mutableMapOf<String, Number>()
manager.getResourceStack(cobblemonResource("move_weights.json")).forEach {
it.open().use {
val map = GsonBuilder().create().fromJson<Map<String, Number>>(it.reader())
weights.putAll(map)
}
}
ShowdownService.service.resetRegistryData("move")
manager.listResources("moves") { it.path.endsWith(".js") }.forEach { (identifier, resource) ->
resource.open().use { stream ->
@@ -75,6 +83,7 @@ object Moves : DataRegistry {
val priority = jsMove.get("priority").asInt
val critRatio = jsMove.get("critRatio")?.asDouble ?: 1.0
val effectChances = arrayListOf<Double>()
val weight = weights[id]?.toFloat() ?: 50F
val secondariesMember = jsMove.get("secondaries")
val secondaryMember = jsMove.get("secondary")
if (secondariesMember != null && secondariesMember is JsonArray) {
@@ -92,7 +101,20 @@ object Moves : DataRegistry {
effectChances += secondaryMember.get("chance").asDouble
}
}
val move = MoveTemplate(id, num, elementalType, damageCategory, power, target, accuracy, pp, priority, critRatio, effectChances.toTypedArray())
val move = MoveTemplate(
name = id,
num = num,
elementalType = elementalType,
damageCategory = damageCategory,
power = power,
target = target,
accuracy = accuracy,
pp = pp,
priority = priority,
critRatio = critRatio,
effectChances = effectChances.toTypedArray(),
weight = weight
)
this.register(move)
} catch (e: Exception) {
Cobblemon.LOGGER.error("Caught exception trying to resolve the move '{}'", id, e)
@@ -113,7 +135,7 @@ object Moves : DataRegistry {
@JvmStatic
fun getByNameOrDummy(name: String) = allMoves[name.lowercase()] ?: MoveTemplate.dummy(name.lowercase())
@JvmStatic
fun getExceptional() = getByName("tackle") ?: allMoves.values.random()
fun getExceptional() = getByName("tackle") ?: allMoves.values.first()
@JvmStatic
fun count() = allMoves.size
@JvmStatic
@@ -129,5 +151,4 @@ object Moves : DataRegistry {
this.allMoves[move.name] = move
this.idMapping[move.num] = move
}
}
@@ -0,0 +1,38 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.moves
import com.cobblemon.mod.common.pokemon.FormData
import com.cobblemon.mod.common.util.cobblemonResource
import net.minecraft.resources.ResourceLocation
/**
* Builders a moveset for a particular [FormData] and level. Probably only really need [DefaultMovesetBuilder] though.
*
* @author Hiroku
* @since December 5th, 2025
*/
interface MovesetBuilder {
/** The ID of this builder. It's autofilled from the registry loader. */
var id: ResourceLocation
/** The subtype designation for this moveset builder. Generally unused once read from JSON. */
val type: ResourceLocation
/** Builds a brand new moveset for the [form] and [level]. */
fun build(form: FormData, level: Int): MoveSet
companion object {
/** Weight multiplier for moves that are in the form's signatureMoves list. Makes them way more likely to be chosen. */
var signatureMoveWeightMultiplier = 5F
/** Subtypes of MovesetBuilder. I personally doubt you'll need any other subtypes, but hey. */
val movesetBuilderTypes = mutableMapOf<ResourceLocation, Class<out MovesetBuilder>>(
cobblemonResource("default") to DefaultMovesetBuilder::class.java
)
}
}
@@ -32,7 +32,6 @@ class ActionEffectTimeline(
val condition: ExpressionLike = "true".asExpressionLike()
) {
companion object {
@JvmField
val NONE = ActionEffectTimeline()
}
@@ -99,4 +98,4 @@ interface EntityProvider {
// val sound: ResourceLocation? = null,
// val animation: List<AnimationWithMoments> = listOf(),
// val effects: List<ActionEffect> = listOf()
//)
//)
@@ -21,10 +21,8 @@ import java.util.concurrent.CompletableFuture
*/
interface ActionEffectKeyframe {
companion object {
@JvmField
val types = mutableMapOf<String, Class<out ActionEffectKeyframe>>()
@JvmStatic
inline fun <reified T : ActionEffectKeyframe> register(type: String) {
types[type] = T::class.java
}
@@ -33,4 +31,4 @@ interface ActionEffectKeyframe {
fun play(context: ActionEffectContext): CompletableFuture<Unit>
fun interrupt(context: ActionEffectContext) {}
fun skip(): CompletableFuture<Unit> = CompletableFuture.completedFuture(Unit)
}
}
@@ -32,4 +32,4 @@ enum class MulchVariant(val duration: Int = -1) : StringRepresentable {
companion object {
const val GROWTH_TIME_MULTIPLIER = 0.5
}
}
}
@@ -109,7 +109,6 @@ object NPCClasses : JsonDataRegistry<NPCClass> {
* @param name The path of the NPC class asset.
* @return The [NPCClass] if existing.
*/
@JvmStatic
fun getByName(name: String) = this.getByIdentifier(cobblemonResource(name))
/**
@@ -8,12 +8,14 @@
package com.cobblemon.mod.common.api.npc
import com.cobblemon.mod.common.api.npc.partyproviders.ComposedPoolPartyProvider
import com.cobblemon.mod.common.api.npc.partyproviders.PoolPartyProvider
import com.cobblemon.mod.common.api.npc.partyproviders.ScriptPartyProvider
import com.cobblemon.mod.common.api.npc.partyproviders.SimplePartyProvider
import com.cobblemon.mod.common.api.storage.party.NPCPartyStore
import com.cobblemon.mod.common.entity.npc.NPCEntity
import com.google.gson.JsonElement
import net.minecraft.resources.ResourceLocation
import net.minecraft.server.level.ServerPlayer
/**
@@ -25,15 +27,15 @@ import net.minecraft.server.level.ServerPlayer
*/
interface NPCPartyProvider {
companion object {
@JvmField
val types = mutableMapOf<String, (String) -> NPCPartyProvider>(
SimplePartyProvider.TYPE to { SimplePartyProvider() },
PoolPartyProvider.TYPE to { PoolPartyProvider() },
ScriptPartyProvider.TYPE to { ScriptPartyProvider() }
val types = mutableMapOf(
SimplePartyProvider.TYPE to ::SimplePartyProvider,
PoolPartyProvider.TYPE to ::PoolPartyProvider,
ScriptPartyProvider.TYPE to ::ScriptPartyProvider,
ComposedPoolPartyProvider.TYPE to ::ComposedPoolPartyProvider
)
}
val type: String
val type: ResourceLocation
val isStatic: Boolean
fun provide(npc: NPCEntity, level: Int, players: List<ServerPlayer> = emptyList()): NPCPartyStore
// Why did I opt for manual JSON loading??? I must have had a reason but I can't remember. Maybe for S2C? Use a codec doofus
@@ -0,0 +1,68 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.npc
import com.bedrockk.molang.runtime.MoLangRuntime
import com.cobblemon.mod.common.pokemon.Pokemon
import com.cobblemon.mod.common.util.cobblemonResource
import kotlin.random.Random
/**
* A kind of definition for how to compose a party of Pokémon given a [PartyPool].
*
* @author Hiroku
* @since December 7th, 2025
*/
class PartyComposition {
var id = cobblemonResource("dummy_composition")
// val displayName = "cobblemon.party_composition.$id" // dunno if i will use this yet
val scrambleOrder: Boolean = false
val slot1 = listOf<String>()
val slot2 = listOf<String>()
val slot3 = listOf<String>()
val slot4 = listOf<String>()
val slot5 = listOf<String>()
val slot6 = listOf<String>()
fun compose(pool: PartyPool, level: Int, aspects: Set<String>, desiredPokemonCount: Int, runtime: MoLangRuntime, random: Random = Random.Default): List<Pokemon> {
val chosenEntries = mutableListOf<PartyPool.PoolEntry>()
val availableEntries = pool.entries.filter { level in it.npcLevels.resolve(runtime) && (it.npcAspects.isEmpty() || it.npcAspects.all(aspects::contains)) }
for (labelSet in listOf(slot1, slot2, slot3, slot4, slot5, slot6)) {
pool.tryChoosingEntry(labelSet, runtime, random, availableEntries, chosenEntries)
if (chosenEntries.size >= desiredPokemonCount) {
break
}
}
val finalEntries = if (scrambleOrder) {
chosenEntries.shuffled(random)
} else {
chosenEntries
}
val pokemon = finalEntries.map { entry ->
val levelVariation = entry.levelVariation.resolve(runtime)
val lvlVariation = if (levelVariation.first == levelVariation.last) {
levelVariation.first
} else {
levelVariation.random(random)
}
val finalLevel = level + lvlVariation
val properties = entry.pokemon.copy()
properties.level = properties.level ?: finalLevel
val pokemon = properties.create()
entry.movesetBuilders.randomOrNull()?.let(pokemon::initializeMovesetFrom)
pokemon
}
return pokemon
}
}
@@ -0,0 +1,77 @@
/*
* 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.npc
import com.bedrockk.molang.runtime.MoLangRuntime
import com.cobblemon.mod.common.api.molang.ExpressionLike
import com.cobblemon.mod.common.api.moves.MovesetBuilder
import com.cobblemon.mod.common.api.pokemon.PokemonProperties
import com.cobblemon.mod.common.util.ScriptableIntRange
import com.cobblemon.mod.common.util.asExpressionLike
import com.cobblemon.mod.common.util.cobblemonResource
import com.cobblemon.mod.common.util.toProperties
import com.cobblemon.mod.common.util.weightedSelection
import kotlin.random.Random
/**
* A pool of Pokémon to choose from, typically for generating a party for an NPC. The entries
* of the pool work on a weight and label system which is used as part of a [PartyComposition].
*
* @author Hiroku
* @since December 7th, 2025
*/
class PartyPool {
var id = cobblemonResource("dummy")
val displayName = "cobblemon.party_pool.$id"
val entries = mutableListOf<PoolEntry>()
class PoolEntry {
val pokemon: PokemonProperties = "pikachu".toProperties()
val labels: List<String> = emptyList()
val npcAspects: List<String> = emptyList()
val required: List<String> = emptyList()
val excluded: List<String> = emptyList()
val maxSelectableTimes: ExpressionLike = "6".asExpressionLike()
val levelVariation: ScriptableIntRange = ScriptableIntRange(0, 0)
val npcLevels: ScriptableIntRange = ScriptableIntRange(1, 100)
val movesetBuilders: List<MovesetBuilder> = emptyList()
val weight: ExpressionLike = "50".asExpressionLike()
}
/**
* Goes through each of the labels in order, trying to find a valid choice. Once it finds one, it skips the later
* labels and adds the value to [chosenEntries] and returns. If none of the labels could find a valid entry, nothing is added.
*/
fun tryChoosingEntry(
labels: List<String>,
runtime: MoLangRuntime,
random: Random,
availableEntries: List<PoolEntry>,
chosenEntries: MutableList<PoolEntry>,
) {
for (label in labels) {
val entries = availableEntries
.filter { label in it.labels || label.lowercase() == "any" }
.filter { entry ->
// Check required labels
entry.required.all { it in labels } &&
// Check excluded labels
entry.excluded.none { it in labels } &&
// Check max selectable times
chosenEntries.count { it == entry } < entry.maxSelectableTimes.resolveFloat(runtime)
}
if (entries.isNotEmpty()) {
val selectedEntry = entries.weightedSelection(random) { it.weight.resolveFloat(runtime) } ?: return
chosenEntries.add(selectedEntry)
return
}
}
}
}
@@ -34,7 +34,6 @@ interface NPCInteractConfiguration {
companion object {
val types = mutableMapOf<String, NPCInteractConfigurationType<out NPCInteractConfiguration>>()
@JvmStatic
fun register(type: String, displayName: MutableComponent, clazz: Class<out NPCInteractConfiguration>) {
types[type] = NPCInteractConfigurationType(displayName, clazz)
}
@@ -0,0 +1,94 @@
/*
* 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.npc.partyproviders
import com.bedrockk.molang.Expression
import com.bedrockk.molang.runtime.MoLangRuntime
import com.bedrockk.molang.runtime.value.DoubleValue
import com.cobblemon.mod.common.CobblemonPartyCompositions
import com.cobblemon.mod.common.CobblemonPartyPools
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMoLangValue
import com.cobblemon.mod.common.api.molang.MoLangFunctions.setup
import com.cobblemon.mod.common.api.npc.NPCPartyProvider
import com.cobblemon.mod.common.api.npc.PartyComposition
import com.cobblemon.mod.common.api.npc.PartyPool
import com.cobblemon.mod.common.api.storage.party.NPCPartyStore
import com.cobblemon.mod.common.entity.npc.NPCEntity
import com.cobblemon.mod.common.util.asArrayValue
import com.cobblemon.mod.common.util.asExpression
import com.cobblemon.mod.common.util.asIdentifierDefaultingNamespace
import com.cobblemon.mod.common.util.cobblemonResource
import com.cobblemon.mod.common.util.resolveInt
import com.cobblemon.mod.common.util.withQueryValue
import com.google.gson.JsonElement
import com.google.gson.JsonObject
import kotlin.random.Random
import kotlin.ranges.random
import net.minecraft.server.level.ServerPlayer
/**
* An [NPCPartyProvider] which uses a [PartyComposition] and [PartyPool] to generate a party.
*
* There are controls for minimum and maximum Pokémon count, as well as whether to use a fixed random seed for the NPC.
*
* @author Hiroku
* @since December 8th, 2025
*/
class ComposedPoolPartyProvider : NPCPartyProvider {
companion object {
val TYPE = cobblemonResource("composed_pool")
}
override val type = TYPE
override var isStatic: Boolean = true
var useFixedRandom: Boolean = false
var minPokemon: Expression = "1".asExpression()
var maxPokemon: Expression = "6".asExpression()
lateinit var pool: PartyPool
lateinit var composition: PartyComposition
override fun loadFromJSON(json: JsonElement) {
json as JsonObject
isStatic = json.getAsJsonPrimitive("isStatic")?.asBoolean ?: true
useFixedRandom = json.getAsJsonPrimitive("useFixedRandom")?.asBoolean ?: false
pool = CobblemonPartyPools.partyPools[json.get("pool").asString.asIdentifierDefaultingNamespace()]
?: throw IllegalArgumentException("Unknown PartyPool id: ${json.get("pool").asString}")
composition = CobblemonPartyCompositions.partyCompositions[json.get("composition").asString.asIdentifierDefaultingNamespace()]
?: throw IllegalArgumentException("Unknown PartyComposition id: ${json.get("composition").asString}")
minPokemon = json.getAsJsonPrimitive("minPokemon").asString?.asExpression() ?: "1".asExpression()
maxPokemon = json.getAsJsonPrimitive("maxPokemon").asString?.asExpression() ?: "6".asExpression()
}
override fun provide(npc: NPCEntity, level: Int, players: List<ServerPlayer>): NPCPartyStore {
val runtime = MoLangRuntime().setup().withQueryValue("npc", npc.struct)
val random = if (useFixedRandom) Random(npc.uuid.hashCode()) else Random.Default
runtime.withQueryValue("level", DoubleValue(level))
runtime.withQueryValue("players", players.asArrayValue { it.asMoLangValue() })
if (players.size == 1) {
// This is for the convenience, most cases will be pvn one player
runtime.withQueryValue("player", players.first().asMoLangValue())
}
val minPokemon = runtime.resolveInt(this.minPokemon)
val maxPokemon = runtime.resolveInt(this.maxPokemon)
val desiredPokemonCount = (minPokemon..maxPokemon).random(random)
val pokemonList = composition.compose(
pool = pool,
level = level,
aspects = npc.aspects,
desiredPokemonCount = desiredPokemonCount,
runtime = runtime,
random = random
)
val partyStore = NPCPartyStore(npc)
pokemonList.forEach(partyStore::add)
return partyStore
}
}
@@ -48,7 +48,7 @@ import kotlin.random.Random
*/
class PoolPartyProvider : NPCPartyProvider {
companion object {
const val TYPE = "pool"
val TYPE = cobblemonResource("pool")
}
@Transient
@@ -150,10 +150,10 @@ class PoolPartyProvider : NPCPartyProvider {
val instance = selected.pokemon.copy().also { it.level = it.level ?: dictatedLevel ?: randomLevel }.create()
party.add(instance)
}
if (party.none()) {
LOGGER.error("${npc} has no Pokemon on Party")
}
if (party.none()) {
LOGGER.error("$npc had no Pokémon produced by their party provider")
}
}
override fun provide(npc: NPCEntity, level: Int, players: List<ServerPlayer>): NPCPartyStore {
@@ -28,7 +28,7 @@ import net.minecraft.server.level.ServerPlayer
class ScriptPartyProvider : NPCPartyProvider {
companion object {
const val TYPE = "script"
val TYPE = cobblemonResource("script")
}
override val type = TYPE
@@ -16,6 +16,7 @@ import com.cobblemon.mod.common.api.pokemon.PokemonProperties
import com.cobblemon.mod.common.api.storage.party.NPCPartyStore
import com.cobblemon.mod.common.entity.npc.NPCEntity
import com.cobblemon.mod.common.util.asArrayValue
import com.cobblemon.mod.common.util.cobblemonResource
import com.cobblemon.mod.common.util.getBooleanOrNull
import com.cobblemon.mod.common.util.toProperties
import com.google.gson.JsonElement
@@ -29,7 +30,7 @@ import net.minecraft.server.level.ServerPlayer
*/
class SimplePartyProvider : NPCPartyProvider {
companion object {
const val TYPE = "simple"
val TYPE = cobblemonResource("simple")
}
@Transient
@@ -34,7 +34,6 @@ interface NPCVariationProvider {
"random" to RandomNPCVariationProvider::class.java
)
@JvmStatic
fun register(type: String, clazz: Class<out NPCVariationProvider>) {
types[type] = clazz
}
@@ -23,11 +23,8 @@ import kotlin.math.sign
open class OrientationController(val entity: LivingEntity) {
companion object {
@JvmField
val FORWARDS: Vector3f = Vector3f(0.0f, 0.0f, -1.0f)
@JvmField
val UP: Vector3f = Vector3f(0.0f, 1.0f, 0.0f)
@JvmField
val LEFT: Vector3f = Vector3f(-1.0f, 0.0f, 0.0f)
}
@@ -132,4 +129,4 @@ open class OrientationController(val entity: LivingEntity) {
return@updateOrientation Matrix3f().set(resultQuat)
}
}
}
@@ -25,7 +25,6 @@ enum class PermissionLevel(val numericalValue: Int) {
ALL_COMMANDS(4);
companion object {
@JvmStatic
fun byNumericValue(value: Int): PermissionLevel {
return entries.first { it.numericalValue == value }
}
@@ -23,8 +23,6 @@ data class CaptureContext(
* @param critical If the capture is a critical capture, defaults to false.
* @return The generated [CaptureContext].
*/
@JvmOverloads
@JvmStatic
fun successful(critical: Boolean = false): CaptureContext {
if (critical) {
return CaptureContext(numberOfShakes = 1, isSuccessfulCapture = true, isCriticalCapture = true)
@@ -37,7 +37,6 @@ import net.minecraft.network.RegistryFriendlyByteBuf
*/
class FormDexRecord {
companion object {
@JvmField
val CODEC: Codec<FormDexRecord> = RecordCodecBuilder.create { instance ->
instance.group(
ListCodec(Codec.STRING, 0, 3).fieldOf("genders").forGetter { it.genders.map { it.name } },
@@ -26,11 +26,10 @@ enum class PokedexEntryProgress : StringRepresentable, Comparable<PokedexEntryPr
override fun getSerializedName() = this.name
companion object {
@JvmField
val CODEC: Codec<PokedexEntryProgress> = RecordCodecBuilder.create { instance ->
instance.map ({
PokedexEntryProgress.valueOf(it)
}, PrimitiveCodec.STRING.fieldOf("name").forGetter { it.name })
}
}
}
}
@@ -70,7 +70,6 @@ class PokedexManager(
}
companion object {
@JvmField
val CODEC = RecordCodecBuilder.create<PokedexManager> { instance ->
instance.group(
PrimitiveCodec.STRING.fieldOf("uuid").forGetter { it.uuid.toString() },
@@ -33,7 +33,6 @@ import net.minecraft.resources.ResourceLocation
*/
class SpeciesDexRecord {
companion object {
@JvmField
val CODEC: Codec<SpeciesDexRecord> = RecordCodecBuilder.create { instance ->
instance.group(
ListCodec(PrimitiveCodec.STRING, 0, 512).fieldOf("aspects").forGetter { it.aspects.toList() },
@@ -76,9 +76,7 @@ class AggregatePokedexDef(
}
companion object {
@JvmField
val ID = cobblemonResource("aggregate_pokedex_def")
@JvmField
val CODEC: MapCodec<AggregatePokedexDef> = RecordCodecBuilder.mapCodec { instance ->
instance.group(
ResourceLocation.CODEC.fieldOf("id").forGetter { it.id },
@@ -34,12 +34,9 @@ abstract class PokedexDef: ClientDataSynchronizer<PokedexDef> {
abstract fun getEntries(): List<PokedexEntry>
companion object {
@JvmField
val CODEC: Codec<PokedexDef> = ResourceLocation.CODEC.dispatch("type", PokedexDef::typeId, PokedexDef::getCodecById)
@JvmField
val PACKET_CODEC: StreamCodec<ByteBuf, PokedexDef> = ResourceLocation.STREAM_CODEC.dispatch({ it.typeId }, ::getPacketCodecById)
@JvmStatic
fun getPacketCodecById(id: ResourceLocation): StreamCodec<ByteBuf, out PokedexDef> {
return when (id) {
SimplePokedexDef.ID -> SimplePokedexDef.PACKET_CODEC
@@ -48,7 +45,6 @@ abstract class PokedexDef: ClientDataSynchronizer<PokedexDef> {
}
}
@JvmStatic
fun getCodecById(id: ResourceLocation): MapCodec<out PokedexDef> {
return when (id) {
SimplePokedexDef.ID -> SimplePokedexDef.CODEC
@@ -64,9 +64,7 @@ class SimplePokedexDef(
}
companion object {
@JvmField
val ID = cobblemonResource("simple_pokedex_def")
@JvmField
val CODEC: MapCodec<SimplePokedexDef> = RecordCodecBuilder.mapCodec { instance ->
instance.group(
ResourceLocation.CODEC.fieldOf("id").forGetter { it.id },
@@ -80,7 +78,6 @@ class SimplePokedexDef(
}
}
@JvmField
val PACKET_CODEC: StreamCodec<ByteBuf, SimplePokedexDef> = StreamCodec.composite(
ResourceLocation.STREAM_CODEC, SimplePokedexDef::id,
ByteBufCodecs.INT, SimplePokedexDef::sortOrder,
@@ -10,6 +10,7 @@ package com.cobblemon.mod.common.api.pokemon
import com.cobblemon.mod.common.Cobblemon
import com.cobblemon.mod.common.Cobblemon.config
import com.cobblemon.mod.common.CobblemonMovesetBuilders
import com.cobblemon.mod.common.api.abilities.Abilities
import com.cobblemon.mod.common.api.abilities.Ability
import com.cobblemon.mod.common.api.events.CobblemonEvents
@@ -82,13 +83,13 @@ import kotlin.jvm.optionals.getOrNull
open class PokemonProperties {
companion object {
@JvmField
@JvmStatic
val CODEC: Codec<PokemonProperties> = Codec.STRING.xmap(
{ parse(it) },
{ it.asString() }
)
@JvmField
@JvmStatic
val CUSTOM_PROPERTIES_CODEC: Codec<MutableList<CustomPokemonProperty>> = Codec.list(Codec.STRING)
.xmap(
{ string -> parse(string.joinToString(" ")).customProperties },
@@ -96,7 +97,6 @@ open class PokemonProperties {
)
@JvmOverloads
@JvmStatic
fun parse(string: String, delimiter: String = " ", assigner: String = "="): PokemonProperties {
val props = PokemonProperties()
props.originalString = string
@@ -149,6 +149,13 @@ open class PokemonProperties {
props.originalTrainerType = OriginalTrainerType.entries.toList().parsePropertyOfCollection(keyPairs, listOf("originaltrainertype", "ottype"), labelsOptional = true) { it.name.lowercase() }
props.originalTrainer = parsePlayerProperty(keyPairs, listOf("originaltrainer", "ot"))
props.moves = parseString(keyPairs, listOf("moves"))?.split(",")
props.movesetBuilders = parseString(keyPairs, listOf("moveset_builders", "movesetbuilders", "moveset_builder", "movesetbuilder"))?.split(",")?.mapNotNull {
try {
it.asIdentifierDefaultingNamespace()
} catch (_: ResourceLocationException) {
null
}
}
props.heldItem = parseString(keyPairs, listOf("helditem", "held_item"))
props.minPerfectIVs = parseIntProperty(keyPairs, listOf("min_perfect_ivs"))?.coerceIn(0, Stats.PERMANENT.size)
props.scaleModifier = parseFloatProperty(keyPairs, listOf("scale_modifier"))
@@ -357,6 +364,7 @@ open class PokemonProperties {
var originalTrainerType: OriginalTrainerType? = null
var originalTrainer: String? = null // Original Trainer by Username or UUID
var moves: List<String>? = null
var movesetBuilders: List<ResourceLocation>? = null
var heldItem: String? = null
var cosmeticItem: String? = null
var scaleModifier: Float? = null
@@ -463,7 +471,7 @@ open class PokemonProperties {
}
moves?.let { moves ->
if (pokemon.moveSet.getMoves().isEmpty()) {
pokemon.initializeMoveset(preferLatest = true)
pokemon.initializeMovesetFromDefault()
}
val moveTemplates = moves.mapNotNull(Moves::getByName).shuffled()
val replaceableIndices = (0..3).filterNot { pokemon.moveSet[it]?.template?.let(moveTemplates::contains) == true }.shuffled()
@@ -476,6 +484,13 @@ open class PokemonProperties {
pokemon.moveSet.update()
}
}
movesetBuilders?.let { movesetBuilders ->
val builders = movesetBuilders.mapNotNull { CobblemonMovesetBuilders.movesetBuilders[it] }
if (builders.isNotEmpty()) {
val movesetBuilder = builders.random()
pokemon.initializeMovesetFrom(movesetBuilder)
}
}
heldItem?.let { itemKey ->
val server = server() ?: return@let
val parser = ItemParser(server.registryAccess())
@@ -679,6 +694,7 @@ open class PokemonProperties {
originalTrainerType?.let { nbt.putInt(DataKeys.POKEMON_ORIGINAL_TRAINER_TYPE, it.ordinal) }
originalTrainer?.let { nbt.putString(DataKeys.POKEMON_ORIGINAL_TRAINER, it) }
moves?.let { nbt.putString(DataKeys.POKEMON_PROPERTIES_MOVES, it.joinToString(separator = ",")) }
movesetBuilders?.let { nbt.putString(DataKeys.POKEMON_PROPERTIES_MOVESET_BUILDERS, it.joinToString(separator = ",") { source -> source.toString() }) }
heldItem?.let {nbt.putString(DataKeys.POKEMON_PROPERTIES_HELDITEM, it)}
scaleModifier?.let { nbt.putFloat(DataKeys.POKEMON_SCALE_MODIFIER, it) }
val custom = ListTag()
@@ -713,6 +729,7 @@ open class PokemonProperties {
originalTrainerType = if (tag.contains(DataKeys.POKEMON_ORIGINAL_TRAINER_TYPE)) OriginalTrainerType.valueOf(tag.getString(DataKeys.POKEMON_ORIGINAL_TRAINER_TYPE)) else null
originalTrainer = if (tag.contains(DataKeys.POKEMON_ORIGINAL_TRAINER)) tag.getString(DataKeys.POKEMON_ORIGINAL_TRAINER) else null
moves = if (tag.contains(DataKeys.POKEMON_PROPERTIES_MOVES)) tag.getString(DataKeys.POKEMON_PROPERTIES_MOVES).split(",") else null
movesetBuilders = if (tag.contains(DataKeys.POKEMON_PROPERTIES_MOVESET_BUILDERS)) tag.getString(DataKeys.POKEMON_PROPERTIES_MOVESET_BUILDERS).split(",").map { it.asIdentifierDefaultingNamespace() } else null
heldItem = if (tag.contains(DataKeys.POKEMON_PROPERTIES_HELDITEM)) tag.getString(DataKeys.POKEMON_PROPERTIES_HELDITEM) else null
scaleModifier = if (tag.contains(DataKeys.POKEMON_SCALE_MODIFIER)) tag.getFloat(DataKeys.POKEMON_SCALE_MODIFIER) else null
val custom = tag.getList(DataKeys.POKEMON_PROPERTIES_CUSTOM, Tag.TAG_STRING.toInt())
@@ -748,6 +765,7 @@ open class PokemonProperties {
originalTrainerType?.let { json.addProperty(DataKeys.POKEMON_ORIGINAL_TRAINER_TYPE, it.name) }
originalTrainer?.let { json.addProperty(DataKeys.POKEMON_ORIGINAL_TRAINER, it) }
moves?.let { json.addProperty(DataKeys.POKEMON_PROPERTIES_MOVES, it.joinToString(separator = ",")) }
movesetBuilders?.let { json.addProperty(DataKeys.POKEMON_PROPERTIES_MOVESET_BUILDERS, it.joinToString(separator = ",") { source -> source.toString() }) }
heldItem?.let {json.addProperty(DataKeys.POKEMON_PROPERTIES_HELDITEM, it)}
scaleModifier?.let { json.addProperty(DataKeys.POKEMON_SCALE_MODIFIER, it) }
val custom = JsonArray()
@@ -782,6 +800,7 @@ open class PokemonProperties {
originalTrainerType = json.get(DataKeys.POKEMON_ORIGINAL_TRAINER_TYPE)?.asString?.let { OriginalTrainerType.valueOf(it) }
originalTrainer = json.get(DataKeys.POKEMON_ORIGINAL_TRAINER)?.asString
moves = json.get(DataKeys.POKEMON_PROPERTIES_MOVES)?.asString?.split(",")
movesetBuilders = json.get(DataKeys.POKEMON_PROPERTIES_MOVESET_BUILDERS)?.asString?.split(",")?.map { it.asIdentifierDefaultingNamespace() }
heldItem = json.get(DataKeys.POKEMON_PROPERTIES_HELDITEM)?.asString
scaleModifier = json.get(DataKeys.POKEMON_SCALE_MODIFIER)?.asFloat
val custom = json.get(DataKeys.POKEMON_PROPERTIES_CUSTOM)?.asJsonArray
@@ -821,6 +840,7 @@ open class PokemonProperties {
originalTrainer?.let { pieces.add("originaltrainer=$it") }
customProperties.forEach { pieces.add(it.asString()) }
moves?.let { pieces.add("moves=${it.joinToString(separator = ",")}") }
movesetBuilders?.let { pieces.add("movesetbuilders=${it.joinToString(separator = ",") { source -> source.toString() }}") }
heldItem?.let {pieces.add("helditem=$it")}
scaleModifier?.let { pieces.add("scale_modifier=$it") }
return pieces.joinToString(separator)
@@ -23,6 +23,7 @@ import com.cobblemon.mod.common.api.drop.ItemDropMethod
import com.cobblemon.mod.common.api.entity.EntityDimensionsAdapter
import com.cobblemon.mod.common.api.molang.ExpressionLike
import com.cobblemon.mod.common.api.moves.MoveTemplate
import com.cobblemon.mod.common.api.moves.MovesetBuilder
import com.cobblemon.mod.common.api.moves.adapters.MoveTemplateAdapter
import com.cobblemon.mod.common.api.npc.configuration.MoLangConfigVariable
import com.cobblemon.mod.common.api.pokemon.PokemonSpecies.getByIdentifier
@@ -131,6 +132,7 @@ object PokemonSpecies : JsonDataRegistry<Species> {
.registerTypeAdapter(RidingBehaviourSettings::class.java, RidingBehaviourSettingsAdapter)
.registerTypeAdapter(RideSoundSettingsList::class.java, RideSoundSettingsListAdapter)
.registerTypeAdapter(ObtainableItemCondition::class.java, ObtainableItemConditionAdapter)
.registerTypeAdapter(MovesetBuilder::class.java, MovesetBuilderReferenceAdapter)
.disableHtmlEscaping()
.enableComplexMapKeySerialization()
.create()
@@ -22,14 +22,10 @@ import com.cobblemon.mod.common.pokemon.Pokemon
interface AspectProvider {
companion object {
val providers = mutableListOf<AspectProvider>()
@JvmStatic
fun register(provider: AspectProvider): AspectProvider {
providers.add(provider)
return provider
}
@JvmStatic
fun unregister(provider: AspectProvider) {
providers.remove(provider)
}
@@ -21,7 +21,6 @@ import com.cobblemon.mod.common.pokemon.Pokemon
*/
interface SingleConditionalAspectProvider : AspectProvider {
companion object {
@JvmStatic
fun getForFeature(name: String): SingleConditionalAspectProvider {
return object : SingleConditionalAspectProvider {
override val aspect: String = name

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