Compare commits

..
Author SHA1 Message Date
MeAlam1 58cdf2e756 Added Debug Logging to hopefully find the issue 2026-08-06 18:26:43 +02:00
Hiroku d4b6e36aab Merge branch 'gamemasters' into 'main'
Interaction Fix

See merge request cable-mc/cobblemon!2339
2026-08-03 08:49:25 +00:00
dhi_holo 0fb721702d Interaction Fix
Solves interaction problem reported https://discord.com/channels/725110639554592879/1481053968716009493/1533385403170820148

Habitat Block acts like a block without interactions if right clicked by a player in survival, or without operator permissions of level 2 or higher (same as command blocks, known as Gamemaster)
With those permissions, it works as usual

Also removed Habitat Block from the Cobblemon Blocks tab, leaving it solely in the Operator Items Tab, like Command Blocks.
2026-08-02 21:08:13 +10:00
Polymeta 0e5053b787 Merge branch 'config-screen-scrolling-labels' into 'main'
Labels on the config screen now scroll instead of overflowing

See merge request cable-mc/cobblemon!2338
2026-08-01 22:09:46 +00:00
lionandPolymeta f3867e0b1d Labels on the config screen now scroll instead of overflowing 2026-08-01 22:09:46 +00:00
Hiroku a4fcd1ae7b Merge branch 'transparent-occlusion' into 'main'
Fix translucent draw order

See merge request cable-mc/cobblemon!2337
2026-08-01 01:56:58 +00:00
JordanandHiroku ed9aff2448 Fix translucent draw order 2026-08-01 01:56:57 +00:00
Nick 8497a2a083 Merge branch 'trade-dupe-fix' into 'main'
Trade dupe fix

See merge request cable-mc/cobblemon!2336
2026-07-31 15:22:15 -07:00
Deltric b389a95b5e Trade dupe fix 2026-07-31 17:03:33 -05:00
Polymeta c310027ce1 Merge branch 'Habitat-Bug-Fixes' into 'main'
Fixin some things

See merge request cable-mc/cobblemon!2335
2026-07-31 20:34:24 +00:00
Slippy 5ddb01df36 More Bug Fixes 2026-07-31 14:25:33 -05:00
Slippy 5a6f49aad5 found one more thing 2026-07-31 02:54:16 -05:00
Slippy 793efcfa3d Fixin some things 2026-07-31 02:49:24 -05:00
Polymeta d671c5a8b8 [skip-ci] tidy up changelog
Signed-off-by: Polymeta <4726322-polymeta@users.noreply.gitlab.com>
2026-07-29 11:59:10 +01:00
Polymeta 69b31dd9b9 fix up null checks to prevent crashes during ticks in BerryBlock
Signed-off-by: Polymeta <4726322-polymeta@users.noreply.gitlab.com>
2026-07-29 11:45:50 +01:00
Polymeta fc94bbac4c Merge branch 'dandelion-sinistertea-fix' into 'main'
Dandelion Sinister Tea Fix

See merge request cable-mc/cobblemon!2324
2026-07-28 15:53:25 +00:00
CeejayandPolymeta f7d315fa33 Dandelion Sinister Tea Fix 2026-07-28 15:53:25 +00:00
Paul 7c30fd81f3 Scraped behaviours for updated AI behaviour 2026-07-28 20:10:29 +10:00
Paul 7f1704d573 Fixed habitat spelling beheeyem wrong 2026-07-28 19:49:22 +10:00
Paul 0c2ec3ca81 Scraped habitat spawns, deduplicated fixes in changelog, update wildlife -> wildfire in habitat pool 2026-07-28 19:43:09 +10:00
Paul 33d3e156cc Merge remote-tracking branch 'origin/lang-updates' 2026-07-28 19:06:49 +10:00
arvid6andWeblate 415642a8ba Translated using Weblate (Spanish)
Currently translated at 99.6% (9432 of 9467 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/es/
2026-07-27 18:45:01 +00:00
arvid6andWeblate dd12081cd1 Translated using Weblate (Spanish)
Currently translated at 99.5% (9425 of 9467 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/es/
2026-07-27 11:20:52 +00:00
arvid6andWeblate b7de84acfd Translated using Weblate (Spanish)
Currently translated at 99.1% (9384 of 9467 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/es/
2026-07-27 11:06:54 +00:00
Hiroku 8efda8c47b Merge branch 'main' into 'main'
Fix load time deadlock between ElementalType and ElementalTypes

Closes #2034

See merge request cable-mc/cobblemon!2332
2026-07-26 02:24:21 +00:00
Naitronbomb 6baf96f83b Add changelog entry for load time deadlock fix 2026-07-25 11:13:18 -07:00
Naitronbomb 009a9c3f15 Fix load time deadlock between ElementalType and ElementalTypes 2026-07-25 09:29:47 -07:00
Polymeta fc0a6c0c8b Merge branch 'gem-unbalance' into 'main'
Type Gem Loot Table Tweaks

See merge request cable-mc/cobblemon!2322
2026-07-25 16:14:44 +00:00
Hiroku 041e080cd4 Merge branch 'fix-starter-toast-dismissal' into 'main'
Fix starter toast not being dismissed when capturing a pokemon

See merge request cable-mc/cobblemon!2331
2026-07-25 03:13:11 +00:00
lionandHiroku 65bbadcfa8 Fix starter toast not being dismissed when capturing a pokemon 2026-07-25 03:13:11 +00:00
阿鱼andWeblate a70d5e200a Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 99.5% (9420 of 9467 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/zh_Hans/
2026-07-25 00:24:55 +00:00
阿鱼andWeblate 4d0ee751a3 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 97.2% (9206 of 9467 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/zh_Hans/
2026-07-24 22:42:33 +00:00
Hiroku d87438e53d I'll try changing the repo URL, that's a good trick 2026-07-24 16:57:53 +10:00
Hiroku 3efef07afa Merge remote-tracking branch 'origin/main' 2026-07-24 16:27:11 +10:00
Hiroku 9ff227fbef Fix pipelines maybe with findutils installs? 2026-07-24 16:27:01 +10:00
Hiroku 55ef5fd537 Merge branch 'fix-forms-riding-camera-offset' into 'main'
Fix riding camera offset defined on Pokemon forms not being applied

See merge request cable-mc/cobblemon!2326
2026-07-24 06:23:29 +00:00
lionandHiroku b3cdfb579c Fix riding camera offset defined on Pokemon forms not being applied 2026-07-24 06:23:28 +00:00
Hiroku 29588f1fde Merge branch 'implement_pokemon' into 'main'
the last of 1.8 (merge once ride stats are in)

See merge request cable-mc/cobblemon!2329
2026-07-24 06:19:25 +00:00
Polymeta 24c10d1a4f Merge branch 'riding-scrape-1.8' into 'implement_pokemon'
Riding scrape

See merge request cable-mc/cobblemon!2330
2026-07-24 06:10:15 +00:00
Carmendar ac0d9d4d74 Seat fixes 2026-07-24 00:53:00 -05:00
Nico MerenqandWeblate d33974b19e Translated using Weblate (Russian)
Currently translated at 78.8% (7467 of 9467 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/ru/
2026-07-24 05:48:29 +00:00
Carmendar 1dcdfe309e Correcting Goodra ride stats 2026-07-24 00:03:33 -05:00
Landon Wills 6ce1990145 Fix issues with scraper 2026-07-24 00:54:33 -04:00
Landon Wills 1203721889 Remove pidgeotto scrape 2026-07-24 00:54:01 -04:00
Landon Wills 333672f993 Push pidgeot riding scrape 2026-07-24 00:53:33 -04:00
Carmendar f0f9a9596f Merge remote-tracking branch 'origin/implement_pokemon' into implement_pokemon 2026-07-23 23:52:58 -05:00
Carmendar 80b8aa2b8c Hisuian Goodra anim updates 2026-07-23 23:52:41 -05:00
Landon Wills b919e447d8 Add scraped files 2026-07-24 00:36:22 -04:00
Hiroku 3075b7fd73 Improved spawn scraper script: recognize more time range names, support 'storm' as a weather condition 2026-07-24 14:31:13 +10:00
ewwww 412e3fcb8a minor poser tweaks 2026-07-24 00:23:14 -04:00
ewwww 32253fd462 starmie shiny texture fix 2026-07-23 23:17:42 -04:00
arvid6andWeblate 4de018a209 Translated using Weblate (Spanish)
Currently translated at 98.2% (9297 of 9467 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/es/
2026-07-23 15:30:25 +00:00
ewwww 2204a4b700 substitute remodel + animations 2026-07-23 02:43:37 -04:00
arvid6andWeblate 22a27cbbd7 Translated using Weblate (Spanish)
Currently translated at 97.5% (9238 of 9467 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/es/
2026-07-21 18:03:56 +00:00
arvid6andWeblate e202e7bf2f Translated using Weblate (Spanish)
Currently translated at 97.3% (9217 of 9467 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/es/
2026-07-21 17:03:35 +00:00
ewwww 03104b3a3d re-deleting these 2026-07-20 04:09:26 -04:00
Polymeta 280e1ae820 Merge branch 'implement_these_dumbfuck_birds' into 'implement_pokemon'
Implement these dumbfuck birds

See merge request cable-mc/cobblemon!2328
2026-07-20 08:02:19 +00:00
Carmendar ee5653bfba Merge branch 'implement_pokemon' into implement_these_dumbfuck_birds
# Conflicts:
#	common/src/main/kotlin/com/cobblemon/mod/common/client/render/models/blockbench/repository/VaryingModelRepository.kt
2026-07-20 02:49:35 -05:00
Carmendar a9c3c14367 Finishing touches to Pidgeot 2026-07-20 02:44:46 -05:00
Paul 9cdc979067 Fixed /giveallpokemon not respecting the min and max options 2026-07-20 13:13:27 +10:00
Carmendar 4b45fdde3f Pidgeotto fixed, and work done to Pidgeot. 2026-07-19 14:55:31 -05:00
Nico MerenqandWeblate 5bf7cc6aef Translated using Weblate (Russian)
Currently translated at 78.7% (7454 of 9467 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/ru/
2026-07-19 12:01:56 +00:00
Polymeta 7cf1f5a4e5 Merge branch 'habitats-crash-fix' into 'main'
Fixed some crashes that happened due to invalid processor referencing and structure

See merge request cable-mc/cobblemon!2327
2026-07-18 22:12:10 +00:00
Faintful 0fe2b0f60c Fixed some crashes that happened due to invalid processor referencing and structure 2026-07-18 22:22:56 +02:00
阿鱼andWeblate 667376226b Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 96.4% (9134 of 9467 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/zh_Hans/
2026-07-18 14:24:13 +00:00
Nico MerenqandWeblate 5506e076f6 Translated using Weblate (Russian)
Currently translated at 78.5% (7437 of 9467 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/ru/
2026-07-18 14:24:11 +00:00
Hiroku f8799efd9d Merge branch 'Habitat-Blocks-pt2' into 'main'
Habitat blocks pt2

See merge request cable-mc/cobblemon!2325
2026-07-18 01:47:16 +00:00
Slippy bb642fbf29 ALL HABITATS HAVE HABITAT BLOCKS!!! 2026-07-17 16:23:59 -05:00
Nico MerenqandWeblate e19aa02283 Translated using Weblate (Russian)
Currently translated at 78.5% (7433 of 9467 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/ru/
2026-07-17 17:47:39 +00:00
Slippy e65010e289 Six more habitats with habitat blocks 2026-07-16 01:05:07 -05:00
Nico MerenqandWeblate 4b4a715868 Translated using Weblate (Russian)
Currently translated at 78.4% (7429 of 9467 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/ru/
2026-07-15 20:06:53 +00:00
Slippy 26ec5717f1 11 more habitats with habitat blocks 2026-07-15 11:55:41 -05:00
Nico MerenqandWeblate 446d4771d8 Translated using Weblate (Russian)
Currently translated at 78.4% (7429 of 9467 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/ru/
2026-07-15 13:44:03 +00:00
Nico MerenqandWeblate 9d817b3f77 Translated using Weblate (Russian)
Currently translated at 78.4% (7427 of 9467 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/ru/
2026-07-15 03:10:05 +00:00
Zack the GhastandWeblate 21213c4fce Translated using Weblate (Portuguese (Portugal))
Currently translated at 66.3% (6281 of 9467 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/pt_PT/
2026-07-14 07:36:57 +00:00
Watuneni iteiteandWeblate cebf105dd5 Translated using Weblate (Japanese)
Currently translated at 100.0% (9467 of 9467 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/ja/
2026-07-13 07:43:46 +00:00
Jakotens 123d3291c6 Fixed Gogoat's battle_idle animation being absent from its poser which caused certain battle animations to break. 2026-07-12 16:21:57 -06:00
dhi_holo 935a39c578 Type Gems now place Stage 1 (Medium) rather than Stage 0 (Small) 2026-07-12 17:56:24 +10:00
dhi_holo d53e67b55c New Loot Tables 2026-07-12 17:31:50 +10:00
Zack the GhastandWeblate ec0766ddcd Translated using Weblate (Portuguese (Portugal))
Currently translated at 65.9% (6244 of 9467 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/pt_PT/
2026-07-11 15:56:17 +00:00
Nico MerenqandWeblate 917577f7a8 Translated using Weblate (Russian)
Currently translated at 78.3% (7418 of 9467 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/ru/
2026-07-11 03:06:15 +00:00
Nico MerenqandWeblate 01de2f71af Translated using Weblate (Russian)
Currently translated at 78.2% (7412 of 9467 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/ru/
2026-07-10 14:42:24 +00:00
Nico MerenqandWeblate 0779251581 Translated using Weblate (Russian)
Currently translated at 76.5% (7244 of 9467 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/ru/
2026-07-09 23:17:58 +00:00
Nico MerenqandWeblate 14d4c6c2e4 Translated using Weblate (Russian)
Currently translated at 76.2% (7222 of 9467 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/ru/
2026-07-09 21:50:35 +00:00
Nico MerenqandWeblate de82d36da3 Translated using Weblate (Russian)
Currently translated at 75.2% (7124 of 9467 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/ru/
2026-07-09 17:04:40 +00:00
Nico MerenqandWeblate ae2704e218 Translated using Weblate (Russian)
Currently translated at 75.0% (7104 of 9467 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/ru/
2026-07-09 13:30:48 +00:00
Nico MerenqandWeblate a235c1286c Translated using Weblate (Russian)
Currently translated at 74.6% (7063 of 9467 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/ru/
2026-07-09 13:20:24 +00:00
Polymeta ce584bd403 Merge branch 'tm-unlock-utilities' into 'main'
Move Data Monitor Learn to Helper, Add Utility and MoLang Functions for Unlocking TMs + Impossible Obtain Method

See merge request cable-mc/cobblemon!2321
2026-07-09 08:09:45 +00:00
Konoha DandPolymeta 1c25861e04 Move Data Monitor Learn to Helper, Add Utility and MoLang Functions for Unlocking TMs + Impossible Obtain Method 2026-07-09 08:09:45 +00:00
Watuneni iteiteandWeblate 006cc21ebb Translated using Weblate (Japanese)
Currently translated at 100.0% (9467 of 9467 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/ja/
2026-07-08 03:33:00 +00:00
Watuneni iteiteandWeblate 5ab9072f94 Translated using Weblate (Japanese)
Currently translated at 99.6% (9431 of 9467 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/ja/
2026-07-07 09:36:33 +00:00
Watuneni iteiteandWeblate f7023b9737 Translated using Weblate (Japanese)
Currently translated at 99.4% (9417 of 9467 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/ja/
2026-07-06 07:04:09 +00:00
Paul 987a7d0ccc Fixed entity attributes not updating when a pokemon levels up 2026-07-04 11:56:47 +10:00
ewwww d49c0a0ec6 changelog 2026-07-03 17:26:41 -04:00
ewwww d4a910bf26 added corsola's physical attack + updated textures 2026-07-03 17:23:13 -04:00
Kenji_64 25b75231ad Implemented Cottonee and Whimsicott animations! 2026-07-03 17:22:13 +02:00
RedGenesectNinja 0db1f372e3 Adjusted swimming heights for both forms of Grimer and Muk 2026-07-03 03:58:57 -05:00
RedGenesectNinja 1ddffc1c0d Merge remote-tracking branch 'origin/implement_pokemon' into implement_pokemon 2026-07-03 01:19:34 -05:00
RedGenesectNinja 5fe04aad83 Implemented Grimer animations 2026-07-02 20:26:49 -05:00
Polymeta 03b74d4b72 Merge branch 'implement_pokemon' into 'main'
various asset updates

See merge request cable-mc/cobblemon!2319
2026-07-02 06:16:52 +00:00
ewwww a5f150af9a poser tweaks 2026-07-02 00:56:11 -04:00
ewwww b3b5e47cc9 tinyprogress 2026-07-02 00:06:01 -04:00
Watuneni iteiteandWeblate 1d0aa06dc4 Translated using Weblate (Japanese)
Currently translated at 99.1% (9389 of 9467 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/ja/
2026-07-01 11:24:54 +00:00
ewwww 1e5c0f5137 added chansey + blissey animations 2026-07-01 00:26:07 -04:00
ewwww 7bafd53f58 minor dugtrio tweaks 2026-06-30 07:36:16 -04:00
ewwww bdbdf238f5 dugtrio physical attack + diglett tweaks 2026-06-30 07:06:24 -04:00
ewwww 6cd71050df added golett remodel 2026-06-30 04:11:09 -04:00
Polymeta 2047f4f461 Merge branch 'my-stupid-tmm-bug' into 'main'
Fix for TMM putting burn screen tab when no tm is selected

See merge request cable-mc/cobblemon!2320
2026-06-30 08:08:37 +00:00
Gertimoshka 0aaed4bb84 Fixed issue where it would still put you on burn screen even with no tm selected 2026-06-30 06:03:56 +03:00
ewwww 3779b4c0b3 updated assets 2026-06-29 17:42:21 -04:00
ewwww 74aaa16a0d physical attack animation for graveler + eye locators for alolan graveler 2026-06-29 07:01:18 -04:00
ewwww 332ef2fddd diglett physical attack 2026-06-29 06:30:21 -04:00
ewwww f29c5c5f6d new animations for sandshrew 2026-06-29 05:24:17 -04:00
ewwww c46375aafb new animations for nidoran male, female, and nidorina 2026-06-29 05:23:54 -04:00
Watuneni iteiteandWeblate a5e16ccf65 Translated using Weblate (Japanese)
Currently translated at 98.7% (9349 of 9467 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/ja/
2026-06-29 08:24:38 +00:00
ewwww 4cc83560e8 kakuna animations 2026-06-29 01:53:20 -04:00
ewwww a7f4ef8449 mountable duraludon and archaludon (stats not final) 2026-06-29 01:25:42 -04:00
ewwww edaafa2263 work in progress i'm sleep deprived 2026-06-28 08:28:18 -04:00
ewwww 0162bdae5f added new animations for poliwhirl 2026-06-27 18:54:44 -04:00
阿鱼andWeblate da82eb8d61 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 94.9% (8993 of 9467 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/zh_Hans/
2026-06-27 11:50:29 +00:00
ewwww 34fc434883 implemented new battle animations for happiny 2026-06-27 05:51:30 -04:00
ewwww 74949a02de yungoos poser tweak 2026-06-27 05:51:04 -04:00
ewwww 1617c1b087 added zubat physical animation 2026-06-27 04:57:03 -04:00
ewwww 4b1c180538 added poliwrath walk animation 2026-06-27 04:56:50 -04:00
ewwww cba6f51706 implemented new yungoos & gumshoos animations 2026-06-27 03:46:00 -04:00
ewwww 9b9fbedaf7 Merge remote-tracking branch 'origin/implement_pokemon' into implement_pokemon 2026-06-26 19:27:45 -04:00
ewwww 8c3acd9a0e 'angery' typo 2026-06-26 18:23:48 -04:00
CaptainLennie 4ab52cac0e Merge remote-tracking branch 'origin/implement_pokemon' into implement_pokemon 2026-06-26 19:28:24 +02:00
CaptainLennie 68805a5dd1 Fixed tentacool using ground animations while swimming on the surface (and updated to JSON poser) 2026-06-26 19:28:10 +02:00
Jerzykv 5a0b4e8f99 Alolan Vulpix portrait tweak 2026-06-26 14:03:11 +02:00
Jerzykv 3e9d3a307f Implemented animations for Rellor and Rabsca 2026-06-26 13:59:14 +02:00
ewwww 7c4d3ecb71 tweaked aerodactyl's walkspeed 2026-06-26 07:30:01 -04:00
ewwww e91fd5596a implemented new vulpix animations 2026-06-26 07:29:29 -04:00
ewwww f9d218adf8 forgot something 2026-06-25 05:46:04 -04:00
ewwww 05d70b28e7 monitor screen updates 2026-06-25 05:41:30 -04:00
ewwww 6755462eb0 added new animations for noctowl 2026-06-25 05:39:58 -04:00
ewwww 7ef3facac8 added new animations for drowzee and hypno 2026-06-25 04:07:39 -04:00
Watuneni iteiteandWeblate 2dc93f3336 Translated using Weblate (Japanese)
Currently translated at 96.7% (9158 of 9467 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/ja/
2026-06-24 10:16:38 +00:00
ewwww b7c16324bd misc texture fixes 2026-06-24 04:05:06 -04:00
阿鱼andWeblate e8864418d4 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 94.9% (8992 of 9467 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/zh_Hans/
2026-06-23 22:49:29 +00:00
Polymeta 7ccd0bbe11 Merge branch 'multiplayer_mount_sync' into 'main'
Multiplayer mount sync

Closes #2023

See merge request cable-mc/cobblemon!2315
2026-06-22 12:23:42 +00:00
ewwww e1cc9c7aba added new animations for Togetic 2026-06-22 02:45:55 -04:00
ewwww 79e821a438 added new animations for Staryu and Starmie 2026-06-22 01:08:45 -04:00
Polymeta d289880cc8 Merge branch 'tmm-fixes-n-changes' into 'main'
TMM Fixes and Changes

See merge request cable-mc/cobblemon!2316
2026-06-20 19:43:21 +00:00
ewwww 19dd57feed form name corrections 2026-06-20 13:16:12 -04:00
Paul 6609c7d038 Added held_item_visible pokemonproperty 2026-06-20 22:29:14 +10:00
Paul 88afe05c16 Fixed NPE's when block entities aren't attached to berry blocks at time of ticking, closes #2020 2026-06-20 18:01:52 +10:00
ewwww e739b57a08 grammar. 2026-06-20 01:22:04 -04:00
Gertimoshka 99aa25e1bf I forgor 2026-06-19 17:50:52 +03:00
Gertimoshka 76faa50035 Fixes, tmm multiplayer syncing and cleanup 2026-06-19 17:42:50 +03:00
aeroeng15 8ce989cb6b Changelog 2026-06-18 19:03:45 -07:00
aeroeng15 02030950aa Force passenger updates 2026-06-18 18:53:36 -07:00
阿鱼andWeblate 82b418d54d Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 94.9% (8993 of 9467 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/zh_Hans/
2026-06-18 21:12:39 +00:00
Polymeta 6148b58fdc Merge branch 'qa-fixes-84' into 'main'
Qa fixes 84

See merge request cable-mc/cobblemon!2314
2026-06-17 11:17:33 +00:00
ewwww 2044762b72 various poser alterations that accidentally got reverted 2026-06-17 05:33:34 -04:00
ewwww 77117e83c7 implemented (non-riding) animations & corrected scales for Duraludon & Archaludon 2026-06-17 05:33:21 -04:00
Carmendar 55f4e6e738 Goodra ride anim adjustments 2026-06-17 00:57:18 -05:00
Faintful 1e4936aeac Add changelog 2026-06-16 20:40:08 +02:00
Faintful 15ea72e777 Fixed Smoked Tail Curry returning a wooden bowl when consumed 2026-06-16 20:38:56 +02:00
Polymeta 3c3d4e4552 [skip-ci] changelogging 2026-06-16 17:43:50 +00:00
Polymeta 796e416578 Merge branch 'fix-auto-third-person-mod-compat' into 'main'
Add check for remember ride camera config when dismounting

Closes #2012

See merge request cable-mc/cobblemon!2308
2026-06-16 17:37:08 +00:00
lionandPolymeta 7608dfde94 Add check for remember ride camera config when dismounting 2026-06-16 17:37:07 +00:00
Polymeta b2b871617a Merge branch 'qa-fixes-85' into 'main'
Qa fixes 85

See merge request cable-mc/cobblemon!2313
2026-06-16 17:19:16 +00:00
Faintful bc4c8d13b7 Fix Panpour consuming a held item when evolving with a Water Stone 2026-06-16 17:07:36 +02:00
Faintful 0f9c51f7dd Fixed full heal stackable block not dropping full heals 2026-06-16 16:05:06 +02:00
Polymeta 2c2623e0f9 Merge branch 'summary-and-pokedex-profile-translations' into 'main'
Add profile translation and scale properties specific to the Pokédex and summary

See merge request cable-mc/cobblemon!2309
2026-06-16 13:44:41 +00:00
lionandPolymeta 8ec85e7d2f Add profile translation and scale properties specific to the Pokédex and summary 2026-06-16 13:44:41 +00:00
Paul d5a08314eb Merge remote-tracking branch 'origin/lang-updates' 2026-06-16 20:36:49 +10:00
Paul 062c32be2a Correct the parsing of phases in habitat GUI (they aren't moon phases) 2026-06-16 20:33:54 +10:00
阿鱼andWeblate 09590b49cd Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 94.9% (8988 of 9467 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/zh_Hans/
2026-06-16 10:14:47 +00:00
Polymeta 420cbd2c99 Merge branch 'fix-pvn-fainted-party-battle' into 'main'
Fix PvN battle start with fainted parties

See merge request cable-mc/cobblemon!2311
2026-06-16 09:45:36 +00:00
Jongho Hong 0380013f37 Add changelog entry 2026-06-16 18:41:43 +09:00
阿鱼andWeblate 6c1fcc103a Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 94.7% (8973 of 9467 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/zh_Hans/
2026-06-16 09:14:38 +00:00
阿鱼andWeblate 59b01c3988 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 94.7% (8971 of 9467 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/zh_Hans/
2026-06-16 08:58:39 +00:00
阿鱼andWeblate 678fa2d0ce Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 94.6% (8961 of 9467 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/zh_Hans/
2026-06-16 08:28:14 +00:00
Jongho Hong 94abd79923 Fix PvN battle start with fainted parties 2026-06-16 17:22:50 +09:00
阿鱼andWeblate 0a1931aaae Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 94.6% (8958 of 9467 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/zh_Hans/
2026-06-16 08:21:26 +00:00
阿鱼andWeblate 85d76dcc29 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 94.5% (8952 of 9467 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/zh_Hans/
2026-06-16 08:07:26 +00:00
阿鱼andWeblate bd0a9ef654 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 94.4% (8944 of 9467 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/zh_Hans/
2026-06-16 07:27:07 +00:00
阿鱼andWeblate 7a702e276c Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 94.2% (8926 of 9467 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/zh_Hans/
2026-06-16 05:41:55 +00:00
阿鱼andWeblate 3f9a2825cb Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 94.2% (8921 of 9467 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/zh_Hans/
2026-06-16 05:30:18 +00:00
阿鱼andWeblate d1462bc27b Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 93.9% (8892 of 9467 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/zh_Hans/
2026-06-16 05:05:07 +00:00
阿鱼andWeblate 211b14dbd0 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 93.5% (8852 of 9467 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/zh_Hans/
2026-06-16 04:59:55 +00:00
阿鱼andWeblate 47e83003c3 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 93.4% (8850 of 9467 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/zh_Hans/
2026-06-16 04:59:34 +00:00
阿鱼andWeblate 59134c4212 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 93.4% (8849 of 9467 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/zh_Hans/
2026-06-16 04:32:46 +00:00
阿鱼andWeblate 44b434562c Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 93.4% (8847 of 9467 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/zh_Hans/
2026-06-15 20:32:05 +00:00
Faintful 7af9b0854a Fixed Status Cure items not returning a bottle after use 2026-06-15 17:55:22 +02:00
Hiroku 344b0750f9 Merge branch 'implement_pokemon' into 'main'
more QA fixes

See merge request cable-mc/cobblemon!2310
2026-06-15 04:26:30 +00:00
ewwww 10d9d97c11 restored broken or missing seat locators for Ariados, Bastiodon, Dhelmise, Dondozo, Drifblim, Girafarig, and Klinklang 2026-06-15 00:06:56 -04:00
Paul 94bcfba076 Phase count should be derived, not set 2026-06-14 22:10:46 +10:00
RedGenesectNinja 69a75ffcd4 Fixed broken Alola bias Exeggcute textures 2026-06-13 13:25:57 -05:00
阿鱼andWeblate cc1317dd06 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 93.4% (8845 of 9467 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/zh_Hans/
2026-06-13 07:46:03 +00:00
Polymeta e15ac73b1b Merge branch 'fix-enchanted-fossil-items' into 'main'
Fix crash when using enchanted items in the ressurection machine

Closes #1973

See merge request cable-mc/cobblemon!2307
2026-06-11 21:48:56 +00:00
lionandPolymeta 6c6576c117 Fix crash when using enchanted items in the ressurection machine 2026-06-11 21:48:55 +00:00
Polymeta ebdfa7edc0 Merge branch 'fix-pokemon-properties-nickname-parsing-to-json' into 'main'
Add pokémon nickname when serializing and deserializing to json on pokémon properties

Closes #1981

See merge request cable-mc/cobblemon!2306
2026-06-11 13:48:21 +00:00
lionandPolymeta 297e8eae77 Add pokémon nickname when serializing and deserializing to json on pokémon properties 2026-06-11 13:48:21 +00:00
Polymeta ea8179018d Merge branch 'modded-discs-compat' into 'main'
Add modded discs compatibility with disc shelves

See merge request cable-mc/cobblemon!2305
2026-06-11 08:20:18 +00:00
lionandPolymeta 14fccfae1d Add modded discs compatibility with disc shelves 2026-06-11 08:20:18 +00:00
Polymeta 26386638ad Merge branch 'PathingThresholds' into 'main'
Fixed wider pokemon being completely unable to hop up ledges

See merge request cable-mc/cobblemon!2304
2026-06-10 08:21:01 +00:00
JazzMcNade 5d1d99b64a Rolled back jump height change 2026-06-09 23:58:44 -05:00
RedGenesectNinja a3c5a6c377 Implemented Yamask fixes 2026-06-09 21:58:33 -05:00
Polymeta eb2a5837eb Merge branch 'oops-unsynced-tms' into 'main'
Sync TM Data

See merge request cable-mc/cobblemon!2303
2026-06-09 18:35:59 +00:00
Gertimoshka 93298d9a87 Sync TM Data 2026-06-09 20:48:35 +03:00
Watuneni iteiteandWeblate abb5346305 Translated using Weblate (Japanese)
Currently translated at 96.5% (9139 of 9467 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/ja/
2026-06-09 15:19:33 +00:00
Watuneni iteiteandWeblate 9466f66721 Translated using Weblate (Japanese)
Currently translated at 96.4% (9129 of 9467 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/ja/
2026-06-09 14:13:54 +00:00
Watuneni iteiteandWeblate 716ea55bc7 Translated using Weblate (Japanese)
Currently translated at 96.2% (9115 of 9467 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/ja/
2026-06-09 14:01:57 +00:00
Polymeta 4d1f46c37c remove unused config values
Signed-off-by: Polymeta <4726322-polymeta@users.noreply.gitlab.com>
2026-06-08 14:55:41 +01:00
ManriqueandWeblate 15f0ad1821 Translated using Weblate (Spanish)
Currently translated at 97.2% (9211 of 9467 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/es/
2026-06-08 08:42:34 +00:00
Polymeta a2101b5759 whoops
Signed-off-by: Polymeta <4726322-polymeta@users.noreply.gitlab.com>
2026-06-08 09:29:49 +01:00
Polymeta 187a190ec6 fix size categories not working properly on servers with non-default scales
Closes #2022

Signed-off-by: Polymeta <4726322-polymeta@users.noreply.gitlab.com>
2026-06-08 09:16:57 +01:00
JazzMcNade 0d433ff394 Fixed wider pokemon being completely unable to hop up ledges
Fixed pokemon not being able to hop up snow
2026-06-07 23:26:31 -05:00
Watuneni iteiteandWeblate a16975c750 Translated using Weblate (Japanese)
Currently translated at 96.1% (9105 of 9467 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/ja/
2026-06-07 15:19:10 +00:00
Watuneni iteiteandWeblate c0e6d87c40 Translated using Weblate (Japanese)
Currently translated at 96.1% (9105 of 9467 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/ja/
2026-06-07 12:39:38 +00:00
Watuneni iteiteandWeblate 91078b917e Translated using Weblate (Japanese)
Currently translated at 96.0% (9090 of 9467 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/ja/
2026-06-07 12:02:11 +00:00
ewwww b7e27fa52a Merge remote-tracking branch 'origin/implement_pokemon' into implement_pokemon 2026-06-05 21:10:08 -04:00
ewwww dc87ffd2a8 luvdisc faint fix 2026-06-05 21:09:49 -04:00
Polymeta d873399d05 Merge branch 'implement_pokemon' into 'main'
for merging when the last of the QA fixes are finished

See merge request cable-mc/cobblemon!2302
2026-06-05 08:28:27 +00:00
Jerzykv a7aab51e0d These didn't get in for some reason 2026-06-05 08:24:37 +02:00
ewwww e8e2057558 popplio t-pose fix 2026-06-04 23:51:06 -04:00
Polymeta 56b5dba911 Merge branch 'stoobid-aram' into 'main'
Stoobid Aram, Actually Fixed the Processor this time

See merge request cable-mc/cobblemon!2301
2026-06-04 22:51:01 +00:00
Aram f0a66458e5 Stoobid Aram, Actually Fixed the Processor this time 2026-06-05 00:31:55 +02:00
ewwww dba6a38f9e Merge remote-tracking branch 'origin/implement_pokemon' into implement_pokemon 2026-06-04 13:07:42 -04:00
ewwww 342c0041e9 UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUGH 2026-06-04 13:07:27 -04:00
阿鱼andWeblate cbeda361d4 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 93.3% (8835 of 9467 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/zh_Hans/
2026-06-04 15:12:59 +00:00
Hiroku a811b3347c Merge branch 'implement_pokemon' into 'main'
Implement pokemon

See merge request cable-mc/cobblemon!2300
2026-06-04 10:53:32 +00:00
Polymeta 80e593f5c6 Merge branch 'fix-/locate-lie' into 'main'
Fixed the HeightRangeProcessor

See merge request cable-mc/cobblemon!2297
2026-06-04 10:43:12 +00:00
ewwww ff617348fe implemented arbok remodel 2026-06-04 06:00:31 -04:00
ewwww 1adecbf5f6 fixed incorrect "Head" naming for gallade 2026-06-04 04:37:32 -04:00
ewwww 29dbb13a0e cramorant poser tweaks 2026-06-04 04:11:06 -04:00
ewwww 67e03ecebd ditto poser tweaks 2026-06-04 04:10:57 -04:00
ewwww 215f48bdc7 musharna placeholder sleep 2026-06-04 04:03:05 -04:00
ewwww d4beab1bfb jynx poser tweaks 2026-06-04 04:02:56 -04:00
ewwww f2c21ec902 smoochum remodel 2026-06-04 04:02:46 -04:00
ewwww c9f3912677 updated omanyte and omastar's posers 2026-06-03 22:39:36 -04:00
ewwww c21b7d1a7d marked cherubi line as implemented + tweaked changelog 2026-06-03 19:59:45 -04:00
ewwww 26068694ad grafaiai animations 2026-06-03 07:15:38 -04:00
Polymeta c86d8f0696 Merge branch '1.8-move-effects-funny' into 'main'
1.8-move-effects-funny

See merge request cable-mc/cobblemon!2299
2026-06-03 09:55:40 +00:00
ewwww 16468059e4 oopsies forgot a few 2026-06-03 03:57:22 -04:00
ewwww 54dbe4769e changelog 2026-06-03 03:51:33 -04:00
321RetroGamer 82019c3722 1.8 MOVE STUFF (real)
NEW MOVES:
- Blizzard
- Disarming Voice
- Dragon Breath
- Dragon Rage
- Drain Punch
- Fairy Wind
- Fire Fang
- Gust
- Horn Drill (effect by Gesteeyy)
- Hydro Pump
- Ice Fang
- Leafage
- Leaf Storm
- Light Screen
- Night Shade
- Play Rough
- Reflect
- Rock Slide
- Sonic Boom
- Sucker Punch
- Supersonic
- Thunder Fang

ANIMATION .JSONS:
- Play Rough

TWEAKS:
- Confusion
- Eruption
- Flamethrower
- Hypnosis
- Poison Fang
- Protect
- Psychic
- Sing
- Spore
- String Shot
- Tail Whip
- Thunder Wave
- Water Pulse

FIXES:
- Dragon Claw (Action Effect Tweaks)
- Fire Punch (Action Effect Tweaks)
- Flame Burst (Delta Fixes)
- Flame Charge (Action Effect Tweaks)
- Frost Breath (Glow Fixes)
- Ice Punch (Action Effect Tweaks, Glow Fixes)
- Icy Wind (Action Effect Tweaks, Glow Fixes)
- Mud Sport (Glow Fixes)
- Quick Attack (Glow Fixes)
- Rage Powder (Action Effect Tweaks, Fixed Missing Texture Directory)
- Razor Leaf (Glow Fixes)
- Sand Attack (Action Effect Tweaks)
- Scratch (Glow Fixes)
- Shadow Claw (Action Effect Tweaks)
- Tackle (Glow Fixes)
- Thunder (Fixed Missing Texture Directory)
- Thunder Punch (Action Effect Tweaks)
- Water Gun (Glow Fixes)
- Water Sport (Glow Fixes)

MISCELLANEOUS:
- Shellder Line Anim/Poser Edits (Protect Signature Showcase)
2026-06-03 01:40:41 -05:00
阿鱼andWeblate 079a2fb50d Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 93.3% (8835 of 9467 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/zh_Hans/
2026-06-03 06:11:14 +00:00
ewwww 78f0951345 (proper) Ditto remodel 2026-06-03 00:27:04 -04:00
Paul 96aaab29e2 Changelog for lang 2026-06-03 11:55:47 +10:00
Paul b1def44953 Merge remote-tracking branch 'origin/implement_pokemon' 2026-06-03 11:55:30 +10:00
Paul e2e38add1d Merge remote-tracking branch 'origin/lang-updates' 2026-06-03 11:54:38 +10:00
ewwww 1db0b0709a animation tweaks 2026-06-02 05:41:51 -04:00
ewwww c3ce3db387 implemented Turtonator remodel 2026-06-02 05:41:38 -04:00
ewwww b5e6fd3816 e 2026-06-01 23:20:38 -04:00
MeAlam1 5b5dcddb25 Fixed the HeightRangeProcessor 2026-06-01 20:16:27 +02:00
ewwww 0158524bff oops. 2026-06-01 07:11:35 -04:00
ewwww 2611e311a7 luvdisc poser conversion + new animations 2026-06-01 06:47:42 -04:00
ewwww 17061691a1 corrected Feraligatr profile scale 2026-06-01 05:16:36 -04:00
ewwww 9c6d7ddfef implemented Tyranitar remodel 2026-06-01 05:16:23 -04:00
Polymeta e8119198c1 Merge branch 'type_alpha_drops' into 'main'
Alphas also drop items based on the pokemon types

See merge request cable-mc/cobblemon!2295
2026-05-31 08:58:53 +00:00
Hiroku 55c0e3e8a0 Merge branch 'IceTypeSnowImmunity' into 'main'
Added powdered snow immunity to ice types

Closes #1809

See merge request cable-mc/cobblemon!2293
2026-05-31 02:07:20 +00:00
PaulFreck 70443bc7b0 added optional tag for powdered snow immunity 2026-05-30 08:26:41 -05:00
Hiroku acb166b5b9 Merge branch 'implement_pokemon' into 'main'
Implement merge to main

See merge request cable-mc/cobblemon!2296
2026-05-30 06:17:46 +00:00
Carmendar 462c361998 No more eepy Seedot line in party/PC 2026-05-30 00:51:58 -05:00
Carmendar 76c90fb1ae Merge branch 'main' into implement_pokemon 2026-05-30 00:49:53 -05:00
Carmendar 27e11dee87 Gen3 alpha eyes 2026-05-30 00:40:24 -05:00
Paul d7c8b8dd62 Alphas also drop items based on the pokemon types 2026-05-30 14:15:00 +10:00
RedGenesectNinja eb12ccf6d0 Updated changelog 2026-05-29 18:52:22 -05:00
mystixmew e7b58edcd1 fix: resolve Linux compatibility issue in Getch class
msvcrt platform detection was broken - the try/except ImportError in
__init__ never triggered since the import attempt already happened at
module level. Replaced with a _has_msvcrt boolean flag set at import
time to correctly route Linux to _getch_unix. Also fixed _getch_unix
to return ch.encode() so key comparisons behave consistently across
platforms.
2026-05-28 17:43:18 -04:00
Polymeta ca5c2ba381 Merge branch 'shiny-volume-tweaks' into 'main'
Update sounds.json and changelog documentation

See merge request cable-mc/cobblemon!2294
2026-05-28 14:15:12 +00:00
SterrezoandPolymeta 8aa538d8e7 Update sounds.json and changelog documentation 2026-05-28 14:15:11 +00:00
Polymeta 1bd33a0635 Merge branch 'main' into implement_pokemon
# Conflicts:
#	common/src/main/resources/assets/cobblemon/lang/en_us.json
2026-05-28 15:13:23 +01:00
Polymeta ff9ca4ee09 Merge branch 'implementation-vibe-check' into 'main'
Added a script to automatically find implementation issues

See merge request cable-mc/cobblemon!2290
2026-05-28 14:10:57 +00:00
ewwww 1def8fcd1a oops 2026-05-28 06:14:50 -04:00
ewwww d53603ec49 futureproofing 2026-05-28 05:50:28 -04:00
Sterrezo 5362995fbb Added checks for wing flap sound keyframes 2026-05-27 14:23:26 +02:00
PaulFreck e2d0b12f94 small change to how freezing works 2026-05-26 20:01:58 -05:00
PaulFreck b32c2cb81c added powdered snow immunity to ice types 2026-05-26 19:48:29 -05:00
Sterrezo 98a7240191 Lenient spellcheck 2026-05-27 02:08:11 +02:00
Sterrezo 84adc0e1cb Minor oopsie 2026-05-27 01:55:55 +02:00
Sterrezo 3ab2dfa0b3 Anti-optimizations 2026-05-27 01:47:28 +02:00
Polymeta d67669a278 Merge branch 'smol-structure-crash-fix' into 'main'
Structure crash fix

See merge request cable-mc/cobblemon!2292
2026-05-26 22:12:37 +00:00
Sterrezo 2a85dee373 Fixed structure file names 2026-05-26 22:23:15 +02:00
Sterrezo 86e8238230 Grammar 2026-05-26 20:16:31 +02:00
Sterrezo bdc7b5a504 Small correction 2026-05-26 20:10:07 +02:00
Sterrezo f3c165d282 Added geo and detailed locator parity checks 2026-05-26 20:04:04 +02:00
Sterrezo 9caf8376bc Made this thing easier to use 2026-05-26 17:53:17 +02:00
Polymeta 8661f7a01e Merge branch 'z-fighting-b-gone' into 'main'
Pokedex Z-Fighting Begone

See merge request cable-mc/cobblemon!2289
2026-05-26 15:17:55 +00:00
Polymeta e933a03e92 Merge branch 'Habitat-Blocks-pt2' into 'main'
drifting icebergs, volcanic plumes, sketal falls, strange fungal dwellings,...

See merge request cable-mc/cobblemon!2291
2026-05-26 15:12:31 +00:00
Watuneni iteiteandWeblate 982fc054a9 Translated using Weblate (Japanese)
Currently translated at 98.5% (9183 of 9320 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/ja/
2026-05-26 07:06:18 +00:00
Watuneni iteiteandWeblate cb73bfb31b Translated using Weblate (Japanese)
Currently translated at 98.3% (9170 of 9320 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/ja/
2026-05-26 06:47:54 +00:00
Slippy 5b84c2c8a0 drifting icebergs, volcanic plumes, sketal falls, strange fungal dwellings, and lush cenotes have habitat blocks. Adjusted the rates of the nether habitats once again. 2026-05-25 12:28:04 -05:00
Sterrezo 9f998d92e6 Added a script to automatically find issues 2026-05-25 17:55:36 +02:00
Test b835bfe596 dex geo, deepslate texture 2026-05-25 03:10:46 -04:00
dhi_holo 757e3d48cb Update pokedex_red_model.json 2026-05-25 05:41:25 +10:00
dhi_holo 2fbf77dd65 Update pokedex_red_model.json 2026-05-25 05:22:41 +10:00
dhi_holo bd451bf951 Pokedex Z-Fighting Begone 2026-05-25 04:20:44 +10:00
geumuandWeblate d88a9dda92 Translated using Weblate (Korean)
Currently translated at 100.0% (9320 of 9320 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/ko/
2026-05-24 14:05:54 +00:00
Watuneni iteiteandWeblate 86c2282cf8 Translated using Weblate (Japanese)
Currently translated at 97.8% (9120 of 9320 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/ja/
2026-05-24 09:11:09 +00:00
Paul ac85cddeb6 Merge remote-tracking branch 'origin/main' 2026-05-24 14:41:27 +10:00
Paul a9c2373979 Fix moveset initialization on clients (it should use a dummy moveset) 2026-05-24 14:41:14 +10:00
Watuneni iteiteandWeblate 6ac8523cf5 Translated using Weblate (Japanese)
Currently translated at 97.2% (9060 of 9320 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/ja/
2026-05-23 17:05:17 +00:00
ManriqueandWeblate acb0aa854e Translated using Weblate (Spanish)
Currently translated at 99.8% (9310 of 9320 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/es/
2026-05-23 17:05:16 +00:00
Polymeta d5cff3ba06 Merge branch 'Ghimmighoul' into 'main'
Made forcebattle identify pokemon

See merge request cable-mc/cobblemon!2288
2026-05-23 07:35:35 +00:00
Paul Freck 8e22538707 Made forcebattle identify pokemon 2026-05-23 01:51:16 -04:00
Hiroku f161699b6a Merge branch '1.8-qa-fixes-#4' into 'main'
Alpha pokemon level matching is more reliable when fishing and using pokesnacks

Closes #35

See merge request cable-mc/cobblemon!2287
2026-05-23 04:44:17 +00:00
ewwww fdafb1e64a updated en_us 2026-05-22 21:35:48 -04:00
Hiroku b0119e32c5 Merge branch 'Habitats-Blocks-pt1' into 'main'
Abandoned Fortress, Chorus Briar & Quartz Spikes habitats have habitat blocks

See merge request cable-mc/cobblemon!2286
2026-05-23 00:43:35 +00:00
Slippy 58bab4b94b Abandoned Fortress, Chorus Briar & Quartz Spikes habitats have habitat blocks 2026-05-22 12:29:30 -05:00
Polymeta a91bf60ff8 pokemon that get fished now get marked as "seen" in pokedex
Closes #2015

Signed-off-by: Polymeta <4726322-polymeta@users.noreply.gitlab.com>
2026-05-22 18:05:49 +01:00
Polymeta 2d4c419216 remove unused override for chests
Closes #2016

Signed-off-by: Polymeta <4726322-polymeta@users.noreply.gitlab.com>
2026-05-22 18:01:10 +01:00
plastered_crab 981f7307e6 Alpha pokemon level matching is more reliable when fishing and using pokesnacks 2026-05-22 08:54:01 -07:00
Polymeta c04345a789 Merge branch 'autocorrect' into 'main'
autocorrect

See merge request cable-mc/cobblemon!2284
2026-05-22 08:07:26 +00:00
Sterrezo 93e84e6ffd autocorrect 2026-05-22 09:17:24 +02:00
Polymeta cc6305bfec Merge branch 'qa-63' into 'main'
Fixed QA 63 for 1.8 / Ally-move turn skip

See merge request cable-mc/cobblemon!2283
2026-05-21 09:54:41 +00:00
CraterandPolymeta 7d38efaa50 Fixed QA 63 for 1.8 / Ally-move turn skip 2026-05-21 09:54:40 +00:00
Polymeta 9a3f5a605a Merge branch 'fix/particle-shader' into 'main'
Fix use the default minecraft shader instead of our own ( don't want to make...

See merge request cable-mc/cobblemon!2282
2026-05-21 09:51:30 +00:00
RedGenesectNinja bd525c8740 Implemented the rest of the Gen 4 alpha eyes 2026-05-21 04:30:28 -05:00
terrainwax b9922057ce Fix use the default minecraft shader instead of our own ( don't want to make the custom pipeline for Iris just for a 0.5 cutout XD ) 2026-05-21 10:58:11 +02:00
Polymeta d9c765ca53 Merge branch 'hydrapple-fix' into 'main'
Zero scaled locators don't get alpha eye effects, fixes hydrapple

See merge request cable-mc/cobblemon!2280
2026-05-21 08:39:49 +00:00
Polymeta 96c3f7764e Merge branch 'CloseSummary' into 'main'
Added ability to close summary and starter screen with summary button.

See merge request cable-mc/cobblemon!2274
2026-05-21 08:38:55 +00:00
Polymeta 255930751a Merge branch '1.8-qa-fixes-#3' into 'main'
Prevent Tera Blast from getting chosen when rolling for TM moves in general...

Closes #58

See merge request cable-mc/cobblemon!2278
2026-05-21 08:38:22 +00:00
Polymeta d3f32ee645 Merge branch 'mimic-block-json-list-additions' into 'main'
Mimic block json list additions

See merge request cable-mc/cobblemon!2281
2026-05-21 08:37:40 +00:00
Slippy e444206a55 and again 2026-05-21 02:51:30 -05:00
ewwww 209dee1d25 . 2026-05-21 03:48:37 -04:00
Slippy e58acd646f spelling & grammatical errors fixed 2026-05-21 02:45:25 -05:00
Slippy bdcc05aa78 added a bunch of blocks to the habitat block mimic list 2026-05-21 02:07:20 -05:00
Hiroku bb899118ef Merge branch '1.8-qa-fixes-#4' into 'main'
1.8 qa fixes #4

Closes #4

See merge request cable-mc/cobblemon!2279
2026-05-21 06:40:37 +00:00
Paul 71585174c0 Fixed an inconveniently small input max length for mimic block id 2026-05-21 16:39:44 +10:00
ewwww 1eedc4862a Merge remote-tracking branch 'origin/implement_pokemon' into implement_pokemon 2026-05-21 00:17:40 -04:00
ewwww b1fbf9ca02 PYRO BALLING 2026-05-21 00:17:28 -04:00
Paul 3449c98b56 Zero scaled locators don't get alpha eye effects, fixes hydrapple 2026-05-21 13:53:20 +10:00
ewwww 5fda445274 cinderace tweak 2026-05-20 23:08:09 -04:00
plastered_crab 60aa991d55 Special moves are no longer searchable in the Search by Move Name function of the dex 2026-05-20 16:42:44 -07:00
plastered_crab 8da0fc34c6 Alphas drop rewards based on their level 2026-05-20 15:41:05 -07:00
plastered_crab 41c55d80a8 "Search By Drops" works for Seen Pokemon now too 2026-05-20 14:05:01 -07:00
plastered_crab 09dfbccb8e Legacy moves are no longer searchable in the Search by Move Name function of the dex 2026-05-20 13:53:19 -07:00
Jerzykv ce0265e954 Goodra animation tweaks 2026-05-20 22:38:56 +02:00
plastered_crab a66d263dd8 Add langs for Data Monitor Shiny and Alpha chance for Config 2026-05-20 12:33:06 -07:00
plastered_crab 5a929e3901 Prevent Tera Blast from getting chosen when rolling for TM moves in general (also for alphas getting the move) 2026-05-20 12:25:03 -07:00
ManriqueandWeblate da1654d9aa Translated using Weblate (Spanish)
Currently translated at 99.7% (9293 of 9320 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/es/
2026-05-20 16:10:05 +00:00
ManriqueandWeblate 27132031cd Translated using Weblate (Spanish)
Currently translated at 99.6% (9292 of 9320 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/es/
2026-05-20 16:09:24 +00:00
GenotypeXD cdc4a571b6 Merge remote-tracking branch 'origin/implement_pokemon' into implement_pokemon 2026-05-20 06:26:07 -05:00
GenotypeXD e8bc138e5d Gen 6 Alphas 2026-05-20 06:25:27 -05:00
ManriqueandWeblate 038d239f95 Translated using Weblate (Spanish)
Currently translated at 98.7% (9208 of 9320 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/es/
2026-05-20 11:20:21 +00:00
Polymeta d95db24426 bump packsquash
Signed-off-by: Polymeta <4726322-polymeta@users.noreply.gitlab.com>
2026-05-20 11:54:29 +01:00
Hiroku a64cbb7e8a Merge branch '1.8-more-qa-fixea' into 'main'
- Show SEEN pokemon in dex filters for Rideable and Learnable TM Moves

See merge request cable-mc/cobblemon!2277
2026-05-20 10:52:10 +00:00
Watuneni iteiteandWeblate 9b2a1dc065 Translated using Weblate (Japanese)
Currently translated at 96.9% (9035 of 9320 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/ja/
2026-05-20 10:26:50 +00:00
ManriqueandWeblate 3c222a3349 Translated using Weblate (Spanish)
Currently translated at 97.1% (9052 of 9320 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/es/
2026-05-20 10:26:49 +00:00
Paul e2ba1dc575 Cleanup for pokedex GUI stuff 2026-05-20 20:01:56 +10:00
Polymeta f7e381924e Merge branch 'sneasler-ride-fix' into 'main'
Fixed basket sneasler causing crashes upon riding

See merge request cable-mc/cobblemon!2276
2026-05-20 09:43:30 +00:00
RedGenesectNinja a1035608c9 Merge remote-tracking branch 'origin/implement_pokemon' into implement_pokemon 2026-05-20 04:06:02 -05:00
RedGenesectNinja 2345565e38 Implemented more Gen 4 alpha eyes and a remodel for Chatot 2026-05-20 04:05:16 -05:00
plastered_crab f4c2a5197c why can't I create an MR 2026-05-20 01:41:33 -07:00
ewwww 620002c165 chopped off gastly's tongue & poked zubat's eyes out 2026-05-20 01:45:14 -04:00
Paul 361a8fcbe1 Fixed basket sneasler causing crashes upon riding 2026-05-20 13:18:05 +10:00
Polymeta e179e044ef Merge branch 'fix-cobblemon-boat-renderer' into 'main'
Fix cobblemon boat renderer

See merge request cable-mc/cobblemon!2275
2026-05-19 15:53:50 +00:00
Sterrezo d89224a684 FIxed incorrectly named sound events for Galarian Ponyta and Rapidash cries 2026-05-19 14:15:05 +02:00
Faintful f55d8737ba Add changelog 2026-05-18 19:57:00 +02:00
Faintful 336180656e Fix Cobblemon boat renderer registration for non-chest boats 2026-05-18 18:37:46 +02:00
ewwww 856eb2a1bd pyro balling 2026-05-18 06:33:20 -04:00
Paul Freck 620589681d Added ability to close summary and starter screen with summary button. 2026-05-18 05:44:12 -04:00
Polymeta 8359b1ade1 Merge branch 'complex-spawn-buckets' into 'main'
Rebuilt spawn buckets to be controlled by the spawner, allowing new buckets in specific contexts, and flattened habitat configuration classes

See merge request cable-mc/cobblemon!2267
2026-05-17 23:54:13 +00:00
TeggyandWeblate 136d7c08b8 Translated using Weblate (Spanish)
Currently translated at 94.2% (8786 of 9320 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/es/
2026-05-17 16:28:35 +00:00
Jerzykv ddc03766bb Implemented alpha eyes/locators of Galar and Hisui 2026-05-17 17:08:25 +02:00
ewwww 81dccf9c07 various fixes 2026-05-17 08:05:04 -04:00
Watuneni iteiteandWeblate ea93b8c1d8 Translated using Weblate (Japanese)
Currently translated at 96.8% (9024 of 9320 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/ja/
2026-05-17 09:41:51 +00:00
Hiroku 8018c1142a Merge branch 'ability-capsule-returns-empty-bottle' into 'main'
Add conditional giveOrDropItemStack() call for returning empty bottles

See merge request cable-mc/cobblemon!2255
2026-05-17 06:56:27 +00:00
Hiroku cfca238573 Merge branch 'data-compatibility' into 'main'
Some Mod Compatibility

See merge request cable-mc/cobblemon!2269
2026-05-17 06:56:01 +00:00
Hiroku e3cf367e45 Merge branch 'riding-when-not-supposed-to-fix' into 'main'
Same fix for mounting a recalling a pokemon, but better

See merge request cable-mc/cobblemon!2268
2026-05-17 06:54:19 +00:00
Hiroku b9b01af451 Merge branch 'fix/fabric-publication-pom' into 'main'
Fix publication pom to include transitive dependencies now in JIJ

See merge request cable-mc/cobblemon!2271
2026-05-17 06:51:39 +00:00
Watuneni iteiteandWeblate 1abe39db3c Translated using Weblate (Japanese)
Currently translated at 96.6% (9012 of 9320 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/ja/
2026-05-17 02:13:26 +00:00
TeggyandWeblate 4e7cdb6266 Translated using Weblate (Spanish)
Currently translated at 94.2% (8786 of 9320 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/es/
2026-05-17 02:13:25 +00:00
Carmendar 79b13acdc6 Gen7 alpha eyes 2026-05-16 20:43:04 -05:00
terrainwax c68f637b70 Fix publication pom to include transitive dependencies now in JIJ 2026-05-16 21:23:27 +02:00
Polymeta d44126179a Merge branch 'fix/neoforge-shader-init' into 'main'
Fix Neoforge shader initialization

See merge request cable-mc/cobblemon!2270
2026-05-16 17:37:47 +00:00
terrainwax 432b350d98 Fix Neoforge shader initialization 2026-05-16 18:45:48 +02:00
Faintful 26677420dd Add changelog 2026-05-16 11:55:48 +02:00
dhi_holo a1487e4ee5 Merge branch 'main' into data-compatibility 2026-05-16 19:46:53 +10:00
Sterrezo 78b2a7d721 Same fix for mounting a recalling a pokemon, but better 2026-05-16 11:42:34 +02:00
dhi_holo d4a3dfdb07 Phase 1 Complete
Added basic support for Create, Supplementaries/Supplementaries Squared/Amendments/Moonlight, Arts and Crafts, and Farmer's Delight (NeoForge and Fabric) in a variety of ways
2026-05-16 19:18:25 +10:00
Paul 0f3dcb760e Rebuilt spawn buckets to be controlled by the spawner, allowing new buckets in specific contexts, and flattened habitat configuration classes 2026-05-16 16:34:20 +10:00
ewwww 0ffd6fad90 gen 2 locators wip, pushing for now 2026-05-16 01:47:17 -04:00
geumuandWeblate 3c9661dfd3 Translated using Weblate (Korean)
Currently translated at 100.0% (9320 of 9320 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/ko/
2026-05-16 04:58:00 +00:00
Watuneni iteiteandWeblate 520f522f3c Translated using Weblate (Japanese)
Currently translated at 96.6% (9012 of 9320 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/ja/
2026-05-16 04:58:00 +00:00
TeggyandWeblate 113ae1f749 Translated using Weblate (Spanish)
Currently translated at 94.2% (8785 of 9320 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/es/
2026-05-16 04:57:58 +00:00
ewwww 61bf5ffab1 feraligatr poser update 2026-05-15 23:40:09 -04:00
Hiroku 0e1b59fb25 Merge branch 'riding-when-not-supposed-to-fix' into 'main'
Prevent riding when Pokemon is being sent out or retrieved

See merge request cable-mc/cobblemon!2266
2026-05-16 01:09:42 +00:00
Sterrezo 3565015039 Remove the ability to send one self into the void and crash the game 2026-05-16 02:36:56 +02:00
Hiroku 218b90860b Merge branch 'implement_pokemon' into 'main'
implement_pokemon

See merge request cable-mc/cobblemon!2264
2026-05-15 23:03:46 +00:00
Polymeta a59573073f Merge branch 'sterr/sound' into 'main'
TMM and TM sound implementation + miscellaneous sound tweaks

See merge request cable-mc/cobblemon!2265
2026-05-15 21:52:17 +00:00
Sterrezo 6475d7d732 Fixed TM items playing unintended sounds 2026-05-15 23:38:37 +02:00
Sterrezo c467e98345 Update sounds.json 2026-05-15 21:04:47 +02:00
Sterrezo 6b206cfaaf TM Machine now stops playing sounds when broken 2026-05-15 20:57:13 +02:00
Sterrezo 8aac4c294f More TMM work and new TM sounds 2026-05-15 19:36:58 +02:00
Sterrezo 2e330076b8 Merge branch 'main' into sterr/sound 2026-05-15 18:20:57 +02:00
Jerzykv e1cd217290 Hisuian Zoroark fixes 2026-05-15 18:05:33 +02:00
Gustavo PuerariandWeblate 87da3e83a0 Translated using Weblate (Portuguese (Brazil))
Currently translated at 97.5% (9090 of 9320 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/pt_BR/
2026-05-15 14:36:53 +00:00
geumuandWeblate c325d0215a Translated using Weblate (Korean)
Currently translated at 99.6% (9290 of 9320 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/ko/
2026-05-15 14:36:50 +00:00
TeggyandWeblate 8afb4e6d16 Translated using Weblate (Spanish)
Currently translated at 93.7% (8742 of 9320 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/es/
2026-05-15 14:36:47 +00:00
dhi_holo 60f00ca34d Merge branch 'main' into data-compatibility 2026-05-16 00:10:15 +10:00
dhi_holo 416a2ac390 Create Farmer's Split
Added first pass of inbuilt support for Create, and split Farmer's Delight compat between two jsons for proper compatibility on the two loaders
2026-05-16 00:08:36 +10:00
ManriqueandWeblate 0ffff6f4af Translated using Weblate (Spanish)
Currently translated at 93.7% (8736 of 9320 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/es/
2026-05-15 13:06:40 +00:00
Polymeta 690ada8271 Merge branch 'my-goodness-more-fixes' into 'main'
There are more damn 1.8 QA fixes

See merge request cable-mc/cobblemon!2256
2026-05-15 08:27:44 +00:00
Polymeta b1b06f19b2 Merge branch 'click-to-cry' into 'main'
Play Pokemon cries from summary screen

See merge request cable-mc/cobblemon!2252
2026-05-15 08:25:30 +00:00
dhi_holo 5bc41245ad Merge branch 'main' into data-compatibility 2026-05-15 15:49:52 +10:00
Paul 490fa91ce7 Removed fossil structure tag as we don't use structures for fossil stuff anymore 2026-05-15 14:18:17 +10:00
Gertimoshka 8606d6928d Changes and Changelog 2026-05-15 07:08:09 +03:00
Hiroku 5897b43564 Merge branch 'sounds-unlaggifier' into 'main'
Fix specific quirk of CancelableSoundInstance causing lagspike when far away from a loaded block that creates it

See merge request cable-mc/cobblemon!2248
2026-05-15 03:47:48 +00:00
Gertimoshka 9fd8d32215 Changelog 2026-05-15 06:46:34 +03:00
dhi_holo 03c278229b Merge branch 'main' into data-compatibility 2026-05-15 13:34:54 +10:00
dhi_holo 8ce3322105 New Screen Who This 2026-05-15 13:34:40 +10:00
Paul 364d084584 Small miscellaneous touchups including from thetechgo's MR 2026-05-15 13:01:26 +10:00
Paul 916e6de1d2 Fixed client's "sound" function not taking a volume property as the second argument but requiring one to specify pitch (whack) 2026-05-15 12:03:21 +10:00
ewwww 0b9e706a36 NIDO NIDO BEAMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM 2026-05-14 21:57:38 -04:00
Paul 6d4f529fc0 Some lang updates in changelog 2026-05-15 11:54:50 +10:00
Paul 015de548d3 Merge remote-tracking branch 'origin/main' 2026-05-15 11:53:11 +10:00
Paul 04ca03b3a5 Merge remote-tracking branch 'origin/lang-updates' 2026-05-15 11:53:01 +10:00
Hiroku c7c145ab78 Merge branch 'scrolling-texture-emissive-fix' into 'main'
Fixed scrolling texture layer not working with emissive.

See merge request cable-mc/cobblemon!2260
2026-05-15 01:48:31 +00:00
JadedArts a376863953 One last tweak to Draco Meteor's visuals 2026-05-14 12:28:32 -05:00
Sterrezo 2e68c3fc44 Lowered the volume of Zebstrika's cry 2026-05-14 16:53:49 +02:00
Sterrezo 36f2eee7f9 Oh right, the sounds.json 2026-05-14 16:52:33 +02:00
Sterrezo 71ac29ba8b Merge branch 'implement_pokemon' of https://gitlab.com/cable-mc/cobblemon into implement_pokemon 2026-05-14 16:48:55 +02:00
Sterrezo 781c82230e I want to get off Draco Meteor's wild ride 2026-05-14 16:48:33 +02:00
Jerzykv c58d49ebab fixed hisuian samurott exploding the game 2026-05-14 16:39:49 +02:00
dhi_holo fd8d5630f4 Ya Like Compatibility? 2026-05-14 21:28:28 +10:00
Jerzykv a86b11fdd5 implemented alpha eyes/locators of Paldea 2026-05-14 13:12:09 +02:00
Jerzykv 829dca9d99 Merge remote-tracking branch 'origin/implement_pokemon' into implement_pokemon 2026-05-14 12:43:04 +02:00
Jerzykv 0f0368f3bd Maushold fixes 2026-05-14 12:42:49 +02:00
ewwww 6533030d36 oh brother 2026-05-14 06:21:38 -04:00
ewwww 0efb0d9767 remaining gen 1 eye locators 2026-05-14 06:15:17 -04:00
Paul 8151f9b3e6 Handle the scraping of multipliers more dynamically too, using the Dictionary tab 2026-05-14 20:11:24 +10:00
RedGenesectNinja 4e8ffd3558 Fixed Bidoof's cry not playing a sound 2026-05-14 03:31:41 -05:00
Paul b88873fbc3 Slight upgrade to herds that they support leader-only entries, added scraper for herd data, deleted example herd 2026-05-14 18:10:17 +10:00
RedGenesectNinja dba1ab26a5 I forgot to implement Bidoof's new animations 2026-05-14 02:53:22 -05:00
ewwww cc2295d629 updated models with locators for maushold, added alpha eyes for veluza and dondozo 2026-05-14 03:26:48 -04:00
ewwww 4d3d8d1607 updated models with (eye) locators for:
poliwag, poliwhirl, poliwrath, machop, machoke, machamp, bellsprout, weepinbell, victreebel, tentacool, geodude, graveler, golem, ponyta, rapidash, slowpoke, slowbro, farfetch'd, doduo, dodrio, seel, grimer, muk, shellder, cloyster, gastly, haunter, onix, krabby, kingler, voltorb, electrode, and exeggutor
2026-05-14 03:26:20 -04:00
RedGenesectNinja 1d09360844 Implemented some Gen 4 alpha eyes and remodels for Bidoof and Cranidos 2026-05-14 01:03:46 -05:00
Polymeta 079e75d828 Merge branch 'alpha-moveset-fix' into 'main'
Fixed alpha pokemon not using full movesets

See merge request cable-mc/cobblemon!2263
2026-05-13 10:10:51 +00:00
Paul a3567ead04 Merge remote-tracking branch 'origin/main' into alpha-moveset-fix 2026-05-13 18:18:24 +10:00
Paul f4fef2855b Fixed alpha pokemon not using full movesets 2026-05-13 18:18:13 +10:00
Hiroku 6f614eb02e Merge branch 'implement_pokemon' into 'main'
Implement pokemon

See merge request cable-mc/cobblemon!2232
2026-05-13 08:11:53 +00:00
Paul 72b82858b3 Merge remote-tracking branch 'origin/main' into Habitat-Block-Implementation 2026-05-13 17:16:45 +10:00
Hiroku 361047c309 Merge branch 'Habitat-Block-Implementation' into 'main'
Habitat block implementation

See merge request cable-mc/cobblemon!2261
2026-05-13 06:58:56 +00:00
Paul 18f43f72ad Fixed multiplayer joins failing due to interactions with no cooldown field not loading defaults properly 2026-05-13 16:46:48 +10:00
Paul cbb409b057 Translatable lang for all the habitat editor fields 2026-05-13 16:07:18 +10:00
Paul f8cec09f70 Resolve some conflicts with habitat JSONs and made lang keys for all the to-be-implemented ones 2026-05-13 15:33:44 +10:00
Paul 5579975b46 Merge remote-tracking branch 'origin/main' into Habitat-Block-Implementation
# Conflicts:
#	common/src/main/resources/data/cobblemon/habitat_pools/abandoned_fortress.json
#	common/src/main/resources/data/cobblemon/habitat_pools/chorus_briar.json
#	common/src/main/resources/data/cobblemon/habitat_pools/crimson_fungal_dwelling.json
#	common/src/main/resources/data/cobblemon/habitat_pools/drifting_icebergs.json
#	common/src/main/resources/data/cobblemon/habitat_pools/quartz_spikes.json
#	common/src/main/resources/data/cobblemon/habitat_pools/skeletal_fall.json
#	common/src/main/resources/data/cobblemon/habitat_pools/strange_fungal_dwelling.json
#	common/src/main/resources/data/cobblemon/habitat_pools/volcanic_plume.json
#	common/src/main/resources/data/cobblemon/habitat_pools/warped_fungal_dwelling.json
2026-05-13 14:53:29 +10:00
CaptainLennie 5a57f41fbb Fixed snivy's back problems 2026-05-12 15:52:00 +02:00
CaptainLennie 1845faf9ad Updated samurott textures 2026-05-12 15:48:54 +02:00
Polymeta 0e93682457 Merge branch 'updated-spawns-and-drops' into 'main'
Scrapes for spawns and drops and habitat pools

See merge request cable-mc/cobblemon!2262
2026-05-12 09:06:32 +00:00
ewwww cef69f478d fixed alpha eyes for rattata, raticate, raichu, sandshrew, & sandslash
added locators for nidoran♀, nidorina, nidoqueen, nidoran♂ , nidorino, vulpix (both forms), ninetales (both forms), jigglypuff, wigglytuff, oddish, gloom, vileplume, paras, parasect, venonat, venomoth, diglett (both forms), dugtrio (both forms), meowth (all forms), persian (both forms), psyduck, golduck, mankey, primeape, and growlithe
2026-05-12 04:55:45 -04:00
Paul 5ea7bc9c48 Updated spawn scraper to do habitats too and fixed some drop scrapes 2026-05-12 18:15:22 +10:00
Paul bfc8ace83a Updated spawn scraper to use google doc and rescraped spawns and drops 2026-05-12 16:13:55 +10:00
Paul e0f93fd797 Added herdLevelRange property in herds to do what the levelRange used to, levelRange is now a clamping around un-offset spawn level 2026-05-12 16:13:40 +10:00
Slippy ba13414ada Changed the biome tags of quartz spikes and strange fungal dwellings 2026-05-12 00:36:02 -05:00
Slippy 66c63d54db added end stone to habitat block mimic list 2026-05-12 00:29:19 -05:00
Slippy 9e836bcc3b added habitat blocks to drifting icebergs habitat 2026-05-12 00:23:04 -05:00
Slippy 27fb1f6c66 Implementing Placeholder Habitat Block Jsons 2026-05-11 19:08:40 -05:00
Tyzillion 7f60885f92 I dum dum and did not account for breeze wind render type not allowing emissive. Made it so that if the layer has emissive enabled it uses the energy swirl render type instead. 2026-05-11 18:48:07 -04:00
Sterrezo cb7f6d7bba Updated TM Machine sounds (again), separated the starting sound with a loop 2026-05-11 20:15:54 +02:00
Polymeta a3498fe03b Merge branch 'small-fix' into 'main'
Remove Unused ClientDataSynchronizer

See merge request cable-mc/cobblemon!2240
2026-05-11 14:46:26 +00:00
Polymeta af4af3395c Merge branch 'two-sorting-tweaks' into 'main'
Two Sorting Tweaks

See merge request cable-mc/cobblemon!2259
2026-05-11 14:29:57 +00:00
ewwww 3ab07ecbca added cries to sandshrew + proper alpha eyes for sandslash 2026-05-11 05:26:17 -04:00
dhi_holo b96eccbf2f Changed Regional Delicacy sorting to match dex order 2026-05-11 18:08:46 +10:00
dhi_holo afa7426116 Update CobblemonItemGroups.kt
Fixed Type Gem Block order
2026-05-11 16:15:13 +10:00
ewwww a5ace52cb5 typo 2026-05-10 22:43:32 -04:00
Sterrezo 9f3940bb31 Volume rebalancing 2026-05-10 22:55:35 +02:00
ewwww 8a8c131a44 Primarina size fix 2026-05-10 16:39:59 -04:00
ewwww 8b0fba4201 SANDSHREW REMODEL (and locators) 2026-05-10 06:56:25 -04:00
Hiroku e1e04b19bf Merge branch 'fix-collecting-honey-from-saccharine-leaf-block-with-full-inventory' into 'main'
Refactor addItem() call to giveOrDropItemStack()

Closes #2009

See merge request cable-mc/cobblemon!2253
2026-05-10 10:23:19 +00:00
Hiroku a04beb1ce8 Merge branch 'fix-remove-mulch-from-berry-tree' into 'main'
Fix remove mulch from berry tree

Closes #2011

See merge request cable-mc/cobblemon!2258
2026-05-10 10:22:41 +00:00
ewwww bd9aea7c59 pikachu + raichu updated locators 2026-05-10 05:01:12 -04:00
Sterrezo 757e3a7ff7 Burn sound now stops when crafting TMs is done 2026-05-10 10:37:19 +02:00
Paul 66d03651f9 Added q.failed to move instruction action effects 2026-05-10 13:23:10 +10:00
Faintful 3c1577d58f Add changelog 2026-05-10 02:06:45 +02:00
Faintful dd7d562228 Add changelog 2026-05-10 01:56:52 +02:00
Faintful a01ac32e54 Fix setMulch() not being called in useWithoutItem() 2026-05-10 01:38:43 +02:00
Sterrezo 5c0ae854bf Fixed TM inserting sound playing twice, more volume tweaks 2026-05-09 19:22:02 +02:00
Sterrezo 55c189b749 TM Craft now plays from the block + volume tweaks to the TM Machine 2026-05-09 19:11:49 +02:00
Gertimoshka b5b81fa1aa Implemented the TMM sounds 2026-05-09 19:19:54 +03:00
Sterrezo eda58859ce Fix empty tm machine sounds 2026-05-09 17:33:58 +02:00
Sterrezo 3888a48cb0 Tweaks to block sound positions and the /pc command 2026-05-09 16:20:52 +02:00
ewwww c9b609a3f8 rattata + raticate locators (idgaf if raticate looks a little wonky for now IT'S GETTING REMODELED ANYWAY) 2026-05-09 06:55:57 -04:00
Sterrezo 70fb7c87ad Wip implementation of TMM sounds 2026-05-09 12:45:48 +02:00
Sterrezo a24189b816 Volume tweaks to display cases and evolution stone blocks 2026-05-09 12:05:42 +02:00
Gertimoshka c0d80634a4 Regional Food are now attempted to be consumed first, before applying use on, shifting will skip the consuming 2026-05-08 13:37:52 +03:00
Gertimoshka b52e4de85c Pokerod Bobber will promtly self destruct if the bait of used rod is changed 2026-05-08 13:26:21 +03:00
Gertimoshka 7d37a98a58 Aprijuice will be usable on pokemon with Max Ride stats if they decrease stat, as well as checking for stat to not decrease below allowed 2026-05-08 11:27:45 +03:00
Hiroku a424796aa8 Merge branch 'fix/particle-material-batching' into 'main'
Fix particle culling and shader wiring for per-material batching

See merge request cable-mc/cobblemon!2254
2026-05-08 06:12:28 +00:00
Faintful 8518be0d44 Add conditional giveOrDropItemStack() call for returning empty bottles 2026-05-07 20:35:41 +02:00
terrainwax 24760270bd Fix particle culling and shader wiring for per-material batching 2026-05-07 20:13:36 +02:00
Faintful 19f9490274 Refactor addItem() call to giveOrDropItemStack() 2026-05-07 18:56:02 +02:00
ewwww 93a94f04a1 a portion of the gen 1 locator fixes
bulbasaur, ivysaur, venusaur, charmander, charmeleon, charizard, squirtle, wartortle, blastoise, caterpie, metapod, butterfree, weedle, kakuna, beedrill, pidgey, pidgeotto, pidgeot, spearow, fearow, & ekans
2026-05-07 05:44:20 -04:00
CaptainLennie 97eac48cd7 Alpha locator'd emolga and updated its model 2026-05-06 22:39:01 +02:00
CaptainLennie 2c31f002b2 Unova alpha fixes part 5 2026-05-06 22:16:33 +02:00
Polymeta 4f0eb16ab0 Merge branch 'interact-wheel-qol' into 'main'
Pressing the inventory key now closes the interact wheel gui

See merge request cable-mc/cobblemon!2247
2026-05-06 06:20:00 +00:00
Polymeta 5004b61967 Merge branch 'Structure-Fixes-Part-4' into 'main'
Structure fixes part 4

See merge request cable-mc/cobblemon!2251
2026-05-06 06:16:34 +00:00
MyslippyandPolymeta cf137efa02 Structure fixes part 4 2026-05-06 06:16:34 +00:00
Breezyasha 862c0bda89 update changelog 2026-05-06 00:17:19 -04:00
Gertimoshka 868874b06d Stop some sounds from causing lag from constantl being created properly, then being removed on the same tick later 2026-05-05 13:53:23 +03:00
Sterrezo 068e4a1c92 Pressing the inventory key now closes the interact wheel gui 2026-05-05 08:55:26 +02:00
Breezyasha 267f2aa5a8 Merge branch cobblemon:main into click-to-cry 2026-05-05 03:31:40 +00:00
Polymeta 333d8fa732 Merge branch 'sterr/sound' into 'main'
Couple of sound tweaks

See merge request cable-mc/cobblemon!2245
2026-05-04 19:43:06 +00:00
Sterrezo e8d4e406d5 Update CHANGELOG.md 2026-05-04 18:39:53 +02:00
Sterrezo 9e5c296309 More sound tweaks and fixes to type gems 2026-05-04 18:38:46 +02:00
Sterrezo 69dc89b04f Replaced the apricorn harvesting sound with a new placeholder 2026-05-04 18:14:35 +02:00
Sterrezo dd31fb1a51 Lowered the volume of berry harvesting sound 2026-05-04 17:54:39 +02:00
Sterrezo 9b3a729b3c Type gem block and cluster sound update 2026-05-04 17:53:46 +02:00
Polymeta ed732429b9 Merge branch 'pokedex-firmware-update' into 'main'
Fix to 1.8 breaking older version dex data and failing to load it

See merge request cable-mc/cobblemon!2244
2026-05-04 09:47:45 +00:00
Gertimoshka 8d27394665 Fix to 1.8 breaking older version dex data and failing to load it 2026-05-04 11:58:30 +03:00
Hiroku 943c421b1d Merge branch 'porygon-monitor-fix' into 'main'
Porygon Bug Fixes

See merge request cable-mc/cobblemon!2212
2026-05-04 01:35:56 +00:00
MeAlam1andPolymeta cc9541c146 make neoforge generate normal worlds without crashing agin 2026-05-04 00:36:31 +01:00
CeeJay 538f72c474 Merge branch 'main' into porygon-monitor-fix 2026-05-03 19:34:31 -04:00
CaptainLennie c72ab20cfa Merge remote-tracking branch 'origin/implement_pokemon' into implement_pokemon 2026-05-03 22:26:42 +02:00
CaptainLennie 3cfc915b1a Unova alpha fixes part 4 2026-05-03 22:15:35 +02:00
Jerzykv b8541486d4 Implemented Smoliv line remodels 2026-05-03 21:16:42 +02:00
Jerzykv c69b38454e Fixed tiny error in Talonflame's animations 2026-05-03 20:59:11 +02:00
CaptainLennie 0e5787b8ab Unova alpha fixes part 3 2026-05-03 20:54:17 +02:00
plastered_crab 082be6f2d0 - Show SEEN pokemon in dex filters for Rideable and Learnable TM Moves
- Fix Rideable dex filter to show all rideable pokemon if SEEN or OWNED
2026-05-03 11:49:25 -07:00
plastered_crab 398f14efd5 Reveal drops and move info on Seen / Scanned Pokemon too 2026-05-03 11:15:43 -07:00
Polymeta 4ba33c2a80 neoforge can boot into singleplayer again
Signed-off-by: Polymeta <40173118+Polymeta@users.noreply.github.com>
2026-05-03 17:37:09 +01:00
CaptainLennie e8ace8ba05 Unova alpha fixes part 2 2026-05-03 13:05:35 +02:00
CaptainLennie 1a78625111 Unova Model & locator fixes part 1 2026-05-03 11:55:24 +02:00
CaptainLennie 596c2b95b4 Merge remote-tracking branch 'origin/implement_pokemon' into implement_pokemon 2026-05-03 11:07:19 +02:00
CaptainLennie 38648111a6 Updated torchic locators 2026-05-03 11:07:08 +02:00
JadedArts 149b8f27e6 Draco Meteor is no longer backwards 2026-05-02 18:35:14 -05:00
Hiroku dc78e40941 Merge branch 'fix/disable-culling-in-snowstorm' into 'main'
fix: disable culling for SnowstormParticle

See merge request cable-mc/cobblemon!2239
2026-05-02 23:24:11 +00:00
Polymeta ca7e2054fe Merge branch '1.8-qa-fixes-#2' into 'main'
1.8 qa fixes #2

Closes #2

See merge request cable-mc/cobblemon!2241
2026-05-02 20:43:11 +00:00
Polymeta 14ea73332f Merge branch 'Structure-Fixes-Part-3' into 'main'
Round 3 of structure fixes. Rates adjusted for fossil structures and nether...

See merge request cable-mc/cobblemon!2242
2026-05-02 20:42:07 +00:00
ewwww 91433d7e13 Merge remote-tracking branch 'origin/implement_pokemon' into implement_pokemon 2026-05-02 15:49:06 -04:00
ewwww 85aadbabe9 i need 2 leave this somewhere , raichu alpha eyes texture 2026-05-02 15:48:44 -04:00
Slippy 8fed14e706 Round 3 of structure fixes. Rates adjusted for fossil structures and nether habitats. Fixed holes in deep roots. Fixed one strange fungal dwelling getting cut off by world generation due to size. Changed the step at which preserved skeleton and submerged spike generates so that they actually generate. I swear to god, if the enhydro agate doesnt generate this time, I don't know what else to do. Changed the biome tag of fungal dwelling habitat. 2026-05-02 12:31:56 -05:00
RedGenesectNinja e64c1487cf Restored Ninjask's ability to do barrel rolls 2026-05-02 00:58:49 -05:00
dhi_holo 2c16e5c20d Relic Coin Sack Map Colour 2026-05-02 11:26:19 +10:00
dhi_holo 21505bc5de Update CobblemonItemGroups.kt
Added some items to some vanilla tabs to hint at functions to player, and make some items easier to find
2026-05-02 10:52:22 +10:00
dhi_holo a365aca9ca Cluster Map Colours
We didn't do this, Minecraft does, correcting behaviour now
2026-05-02 10:13:27 +10:00
dhi_holo 19b70e1fbb Colour Tweaks
Tweaked some colours to feel a bit closer. Not perfect, but probably as close to it as we can get with the existing palettes
2026-05-02 10:04:01 +10:00
Plastered_Crab e1ec69f4cf Give Type Gem blocks unique map colors 2026-05-01 15:35:21 -07:00
Plastered_Crab c23e506570 Override culling distance of HabitatBlock so it acts more like terrain blocks. 2026-05-01 15:09:34 -07:00
Plastered_Crab 28a4805cd3 Delete unneeded file 2026-05-01 14:54:08 -07:00
Plastered_Crab 8d3a895591 Merge branch 'main' into 1.8-qa-fixes-#2
# Conflicts:
#	common/src/main/kotlin/com/cobblemon/mod/common/block/entity/DiscShelfBlockEntity.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/item/group/CobblemonItemGroups.kt
2026-05-01 14:31:06 -07:00
Plastered_Crab e8089d6a5d Clean up and optimize some TM Shelf logic 2026-05-01 14:20:41 -07:00
Plastered_Crab 88988c21f1 TM Shelf rendering and rotation fixes 2026-05-01 13:17:14 -07:00
Plastered_Crab cf4409e61d Switch Sound Source of Disk Rack to be RECORDS instead of BLOCKS 2026-05-01 12:24:23 -07:00
Plastered_Crab 516343406c Stop false exception when spawning a pokemon 2026-05-01 11:54:16 -07:00
Plastered_Crab 5ecbf33a6b Fix corrupted player data crash when mount pokemon dies 2026-05-01 11:15:15 -07:00
JadedArts 4d866f6207 More Draco Meteor Fixes
Tweaked ring color gradient
Made crater rocks affected by environment lighting
Fixed meteors playing even on miss
2026-05-01 12:21:56 -05:00
MeAlam1 e81418836e Remove Unused ClientDataSynchronizer 2026-05-01 17:44:57 +02:00
terrainwax 03786a9845 fix: stick to bedrock spec about material 2026-05-01 05:40:15 +02:00
terrainwax d199e372ca fix: disable culling for SnowstormParticle ( all particle ar not always facing camera so we need to render theirs back if we see fps drop for large number of particle we should consider adding a if to camera mod that are not facing the camera ) 2026-05-01 05:19:00 +02:00
Polymeta 8022bfefc8 Merge branch 'command-anim' into 'main'
[Enhancement] Let NPCBattleActors trigger the "Command" animation in battle

See merge request cable-mc/cobblemon!2152
2026-04-30 23:39:25 +00:00
Konoha DandPolymeta eb82d6d6a9 [Enhancement] Let NPCBattleActors trigger the "Command" animation in battle 2026-04-30 23:39:25 +00:00
Polymeta 5be8fdd03d close #1997
Signed-off-by: Polymeta <40173118+Polymeta@users.noreply.github.com>
2026-05-01 00:00:04 +01:00
CaptainLennie 3d779e637b Merge remote-tracking branch 'origin/implement_pokemon' into implement_pokemon 2026-05-01 00:59:52 +02:00
CaptainLennie bd0ad89971 Implemented shedinja, skwovet & greedent animations 2026-05-01 00:59:37 +02:00
Polymeta 0a0532c8cc Merge branch 'trade_friendship' into 'main'
Caching trade friendships to player data

Closes #1898

See merge request cable-mc/cobblemon!2119
2026-04-30 22:55:22 +00:00
Polymeta 586ced7bfb Merge branch 'main' into 'implement_pokemon'
# Conflicts:
#   common/src/main/resources/data/cobblemon/recipe/metal_alloy.json
2026-04-30 22:43:58 +00:00
aeroeng15 e1551ba70b MR Updates 2026-04-30 15:41:28 -07:00
Polymeta 9e05ef3e8c Merge branch 'alpha-bait-changes' into 'main'
Size Modifying Bait effect

See merge request cable-mc/cobblemon!2237
2026-04-30 21:55:18 +00:00
Charzard4261andPolymeta ea1608c8d2 Size Modifying Bait effect 2026-04-30 21:55:18 +00:00
Sterrezo 218f2c67d3 The real draco meteor was friends we made along the way (more sound tweaks) 2026-04-30 20:14:11 +02:00
Polymeta 045ddb30ca Merge branch 'Structure-Fixes-Round-2' into 'main'
Series 2 of 1.8 Structure Fixes

See merge request cable-mc/cobblemon!2238
2026-04-30 17:40:19 +00:00
Slippy bf3e26874f Never updated the fossil structure nbts. Whoops 2026-04-30 01:57:35 -05:00
Slippy bfbdadb519 Make surface habitats sliiiightly more common 2026-04-30 01:52:59 -05:00
Slippy 6b2bd64eec Maybe this will get enhydro agates to generate? 2026-04-30 01:46:10 -05:00
Slippy 59e300582c Chorus Briars way too common 2026-04-30 01:37:28 -05:00
Slippy dd75b898a6 skeletal falls a little too rare. brought it up a bit 2026-04-30 01:35:17 -05:00
Slippy b3bd2e26cd Rates for some habitats ended up being way too low 2026-04-30 01:32:53 -05:00
Slippy 475f8de2e6 Increased odds of a second piece for the fae_mounds 2026-04-30 00:49:32 -05:00
Slippy 096785d7ec added grass, water and fire pledge to jungle temple, nether fortresse and shipwreck chest loot. 2026-04-30 00:46:24 -05:00
Slippy c09c85ffd8 Fixed deep crypt ruins not summoning the warden 2026-04-30 00:39:22 -05:00
Slippy 9f5acfbf62 Adjusted generation rates for all ruin and habitat features and upped the chance to find the enhydro agate. 2026-04-30 00:25:50 -05:00
Slippy d0ddf3bb11 Fixed root nurseries cutting off parts of vanilla trees when generating 2026-04-30 00:18:41 -05:00
Slippy 50624a4e34 Fixed deep sea placeholder nests being replaced with air, not water. Fixed biome tags for natural lightning rod and sandpit clearing habitats. 2026-04-30 00:14:13 -05:00
Slippy 19733e53c9 Fixed bones for skeletal_fall habitats facing the wrong ways 2026-04-30 00:01:37 -05:00
Slippy 277e72912c fixed natural terrain generating in what's supposed to be the air pockets of the structures of fungal dwellings 2026-04-29 23:53:21 -05:00
Breezyasha 59b0397ea4 Merge branch cobblemon:main into click-to-cry 2026-04-30 04:22:08 +00:00
Breezyasha aadb78149c changelog 2026-04-30 00:19:51 -04:00
Slippy 23c80bb82c Fixed shipwreck coves not having structure voids and hopefully fixed the habitats tag 2026-04-29 22:56:10 -05:00
Test 143f9dba3c re-add tm center overlay 2026-04-29 23:45:05 -04:00
aeroeng15 2fb019ce8a Check the right field! 2026-04-29 19:45:46 -07:00
aeroeng15 487b59f7b5 Fix compile issues 2026-04-29 19:23:21 -07:00
aeroeng15 b06c2253ae MR Updates 2026-04-29 19:14:33 -07:00
CaptainLennie 3305874dd4 Implemented sewaddle & swadloon animations 2026-04-30 00:31:32 +02:00
CaptainLennie 2f688291dc Implemented leavanny animations 2026-04-29 23:20:50 +02:00
Polymeta 457c2ab84d Merge branch 'unlag-your-tmm-slots' into 'main'
Fix occasionally slots 'lagging' and not reading your input properly

See merge request cable-mc/cobblemon!2236
2026-04-29 20:36:15 +00:00
CaptainLennie 1f099b231c Fixed talonflame line walk speeds & flygon flight sounds 2026-04-29 21:48:35 +02:00
JadedArts c1ccc718cc Fixes to particles
Renamed explosion_floorscorch.png and explosion_floorscorch_big.png to floorscorch.png and floorscorch_big.png and moved to the generic folder under a new folder "scorch" and updated Explosion and Draco Meteor particles accordingly.

Fixed issue in flamethrower_actor that caused drag to be able to be infinite.
2026-04-29 12:22:40 -05:00
Gertimoshka 972d09e920 Fix occasionally slots 'lagging' and not reading your input properly 2026-04-29 19:30:13 +03:00
Jade 74df81006b Slightly reduced delay at the start of Draco Meteor 2026-04-29 15:23:27 +00:00
Sterrezo e7a87e299c First draft of draco meteor sound implementation 2026-04-29 14:25:56 +02:00
Polymeta c0bef49e2c [skip-ci] changelog
Signed-off-by: Polymeta <40173118+Polymeta@users.noreply.github.com>
2026-04-29 09:29:16 +01:00
Polymeta 44c9ca3c6b Merge branch 'advancing-advancements-returns-in-1.8' into 'main'
Advancing Advancements into 1.8

See merge request cable-mc/cobblemon!2223
2026-04-29 08:27:14 +00:00
dhi_holo d02fe990f6 Typos 2026-04-29 16:51:12 +10:00
dhi_holo 53e133ab94 Update use_mint.json
Fixed requirements
2026-04-29 16:35:33 +10:00
ewwww c688e9f80c Merge remote-tracking branch 'origin/implement_pokemon' into implement_pokemon 2026-04-28 23:02:47 -04:00
ewwww ac1897b41a updated stat increase/decrease particles and added alpha boost particles 2026-04-28 23:02:01 -04:00
ewwww 40e8f4efa5 added eye locators to Nidoking's model 2026-04-28 23:01:34 -04:00
ewwww e00165aafb added animation for Draco Meteor 2026-04-28 23:01:14 -04:00
dhi_holo 7d7c4fa3e2 Final Root is Named 2026-04-29 12:12:47 +10:00
dhi_holo 3c5c4b9cd0 Audio Sequencer
New Tutorial Advancement Time!
2026-04-29 12:07:29 +10:00
aeroeng15 a83546a1da Changelog shenanigans 2026-04-28 18:43:20 -07:00
aeroeng15 af6405b078 Revert "Changelog shenanigans"
This reverts commit ae5021a851.
2026-04-28 18:42:58 -07:00
aeroeng15 ae5021a851 Changelog shenanigans 2026-04-28 18:41:22 -07:00
aeroeng15 ebbe4bb0e1 Re-null friendship after restoration 2026-04-28 18:39:42 -07:00
aeroeng15 ebe93f531c Restore file 2026-04-28 18:39:42 -07:00
aeroeng15 e489bcde07 Change from player-based to pokemon-based storage 2026-04-28 18:39:42 -07:00
aeroeng15 64a3f2dd28 Fix after rebase 2026-04-28 18:39:42 -07:00
aeroeng15 ba15ca3d02 Changelog 2026-04-28 18:39:41 -07:00
aeroeng15 4b79d51f7b Cache management while players are offline 2026-04-28 18:39:41 -07:00
aeroeng15 4c68b0f837 Caching trade friendships to player data 2026-04-28 18:39:41 -07:00
Breezyasha b2015c9cd8 Play pokemon cry in summary screen 2026-04-28 21:26:08 -04:00
dhi_holo eaf0d7ec80 It's Not That Big A Commit-mint
New Mint advancement to be a better tutorial and a more fitting role
2026-04-29 10:09:36 +10:00
GenotypeXD d0b796f777 Changelog Fixes 2026-04-28 19:07:25 -05:00
GenotypeXD 83488ec728 Merge remote-tracking branch 'origin/implement_pokemon' into implement_pokemon
# Conflicts:
#	common/src/main/resources/assets/cobblemon/textures/pokemon/0124_jynx/jynx_alpha.png
#	common/src/main/resources/assets/cobblemon/textures/pokemon/0729_brionne/brionne_alpha.png
2026-04-28 19:02:01 -05:00
GenotypeXD b3d387d8da Implemented Jynx Remodel, Popplio line Remodel, and Fletchling line animations 2026-04-28 19:00:42 -05:00
dhi_holo d9770b17f0 Potion Advancement Improved 2026-04-29 08:58:30 +10:00
dhi_holo b9b4b1c2e7 Merge branch 'main' into advancing-advancements-returns-in-1.8 2026-04-29 08:03:14 +10:00
dhi_holo 13f33f935c Update en_us.json 2026-04-29 08:03:03 +10:00
Apion 3fbcfe842d Merge branch '1.8-structure-fixes' into 'main'
Remoeved the old habitat test structure, added tags for habitats and the new...

See merge request cable-mc/cobblemon!2234
2026-04-28 21:57:10 +00:00
Slippy d5503f7fa9 rocky tidepools should generate now 2026-04-28 16:05:58 -05:00
Slippy fd3e599636 Remoeved the old habitat test structure, added tags for habitats and the new structures and the new shipwreck cove. One freshwater pond's weight was set to 100 by accident. set to 1 now. 2026-04-28 15:55:43 -05:00
Slippy a70a258e64 Upped the rates of some pieces generating in shaded rocks and snowy burrows 2026-04-28 15:36:29 -05:00
Slippy 8121cb4e87 Fixed volcanic plumes, skeletal falls and strange fungal dwellings not generating 2026-04-28 15:30:41 -05:00
Slippy a1ef50a8ec Hopefully this makes rocky outcrop, parched pog and lush pog generate 2026-04-28 15:21:18 -05:00
Polymeta c9c5488be7 Merge branch 'type-gem-feature-gaslighting-max-fix' into 'main'
Fix to Type Gem Feature having a chance to cause an infinite loop during generation, stalling world gen

See merge request cable-mc/cobblemon!2233
2026-04-28 18:46:06 +00:00
Slippy f356dd98b2 Hopefully this fixes the chests in the shipwreck coves 2026-04-28 13:24:32 -05:00
Gertimoshka ce7e465d99 Fix Type Gem Feature Generation Gaslightight causing an infinite loop, stalling world gen 2026-04-28 20:06:00 +03:00
CaptainLennie 902c6751c5 Added milotic ride animations 2026-04-28 15:22:22 +02:00
Polymeta 463d341965 [skip-ci] changelog
Signed-off-by: Polymeta <40173118+Polymeta@users.noreply.github.com>
2026-04-28 13:19:09 +01:00
CaptainLennie 4088f144e4 Fixed mantine's ride sounds 2026-04-28 13:57:09 +02:00
CaptainLennie 3e592b21f1 Fixed honchkrow's ride sounds & added new wing flap sounds 2026-04-28 13:48:08 +02:00
CaptainLennie b1186c8033 Merge remote-tracking branch 'origin/implement_pokemon' into implement_pokemon 2026-04-28 13:21:52 +02:00
CaptainLennie d038f63024 Fixed crobat's ride sounds & added new wing flap sounds 2026-04-28 13:21:26 +02:00
dhi_holo b5a0866b31 Merge branch 'main' into advancing-advancements-returns-in-1.8 2026-04-28 21:02:53 +10:00
dhi_holo 6b1d17ea5d namespace correction 2026-04-28 21:00:24 +10:00
Polymeta 49fe33f9db Merge branch 'sterr/log-cleaning' into 'main'
Return of the log

See merge request cable-mc/cobblemon!2231
2026-04-28 10:57:56 +00:00
Sterrezo 7a3088eb59 Unbroke everything and fixed Alolan Sandslash as well 2026-04-28 12:30:43 +02:00
Polymeta 32ff4557a7 Merge branch 'main-crab-1.8-fixes' into 'main'
1.8 fixes from QA Doc

See merge request cable-mc/cobblemon!2230
2026-04-28 10:27:30 +00:00
CaptainLennie de51d2b1b2 Updated drampa's poser 2026-04-28 12:25:49 +02:00
CaptainLennie 3c3aa3d4a3 Updated aerodactyl locators & changelog 2026-04-28 12:19:51 +02:00
Sterrezo 50e4829b79 Fixed Sandslash's missing cry crashing the game 2026-04-28 12:17:46 +02:00
Sterrezo e4b3136bc9 Removed a nonexistent sound from a sound event 2026-04-28 12:06:22 +02:00
Sterrezo 0815a93ee0 Merge branch 'main' into sterr/log-cleaning 2026-04-28 12:03:15 +02:00
ewwww ebdd06a4a9 added hisui bias bergmite model 2026-04-28 05:56:02 -04:00
ewwww 82fd4bae08 goomy, dartrix, and rowlet hisui bias updates 2026-04-28 05:17:58 -04:00
ewwww 277a7dc32b added mime jr galar bias 2026-04-28 04:36:57 -04:00
ewwww f00d578f64 updated dewott hisui bias 2026-04-28 04:36:40 -04:00
ewwww ea9fba72ec added metal alloy recipe 2026-04-28 04:36:23 -04:00
ewwww 4654c3c2b8 updated oshawott hisui bias 2026-04-28 04:36:12 -04:00
ewwww b4496b30a9 updated petilil hisui bias 2026-04-28 04:36:01 -04:00
ewwww 431662b237 updated exeggcute alola bias 2026-04-28 04:35:42 -04:00
ewwww 1299214d61 updated koffing galar bias 2026-04-28 04:35:26 -04:00
ewwww c5c2c3a059 updated quilava hisui bias 2026-04-28 04:35:05 -04:00
ewwww 64b7970cb5 updated cyndaquil hisui bias 2026-04-28 04:34:51 -04:00
ewwww ce6c777c4e updated cubone alola bias 2026-04-28 04:34:19 -04:00
ewwww 284b032dd8 updated pichu alola bias 2026-04-28 04:33:42 -04:00
ewwww 23d70ab1fe updated pikachu alola bias 2026-04-28 04:33:07 -04:00
Slippy 9414cc096a Several Structure fixes 2026-04-28 02:48:29 -05:00
dhi_holo 7f7774ce90 Advancement Cleanup 2026-04-28 17:14:41 +10:00
dhi_holo 6fde014c67 Advancement Refactor Time!
Drastic reorganisation of the Advancements tab and folder, which will remove all progress on advancements obtained previously, as well as removing some advancements deemed unneeded.
2026-04-28 16:31:31 +10:00
ewwww 3340239440 took garchomp to therapy so it no longer sleep t-poses 2026-04-27 22:27:29 -04:00
ewwww e513d52c3d fixed nidoking's walk speed 2026-04-27 21:59:26 -04:00
dhi_holo ba54401c49 Update root_geological.json 2026-04-28 10:56:26 +10:00
dhi_holo 2d4723d981 Disc Shelf Block Texture Cleanup
Moved the textures out of the main block folder for consistency
2026-04-28 10:40:10 +10:00
dhi_holo d91292cfb6 Update CHANGELOG.md
Moved data from Changelog-1.8 to Changelog
2026-04-28 09:28:34 +10:00
dhi_holo 7156c99b92 Merge branch 'main' into advancing-advancements-returns-in-1.8 2026-04-28 09:21:08 +10:00
dhi_holo 7320e3b9cc Update en_us.json 2026-04-28 09:19:59 +10:00
Plastered_Crab c217d6b754 Rebuild Alpha Pokemon Brain when spawned to assign alpha sensor for ones spawned with Baits 2026-04-27 13:05:56 -07:00
Plastered_Crab 87af7745ae Fill Alpha pokemon's blank moveset with random benched moves 2026-04-27 12:48:38 -07:00
Plastered_Crab 91005cf217 Change baby scaling of lvl 1 mons to be .9 instead of .8 2026-04-27 11:44:40 -07:00
Polymeta e888012b8b Merge branch 'implement_pokemon' into 'main'
Implement pokemon

See merge request cable-mc/cobblemon!2228
2026-04-27 17:22:57 +00:00
CaptainLennie 43fef815ab Fixed an issue with newly implemented mounts not working 2026-04-27 18:31:52 +02:00
CaptainLennie 0f55a28c65 Merge remote-tracking branch 'origin/implement_pokemon' into implement_pokemon 2026-04-27 17:14:41 +02:00
CaptainLennie 0e724118ff Implemented Galvantula animations 2026-04-27 17:14:07 +02:00
Polymeta 88e843b46c Merge branch 'main' into implement_pokemon
# Conflicts:
#	common/src/main/resources/assets/cobblemon/bedrock/pokemon/resolvers/0149_dragonite/0_dragonite_base.json
#	common/src/main/resources/assets/cobblemon/bedrock/pokemon/resolvers/0169_crobat/0_crobat_base.json
#	common/src/main/resources/assets/cobblemon/textures/pokemon/0028_sandslash/sandslash_alpha.png
#	common/src/main/resources/assets/cobblemon/textures/pokemon/0034_nidoking/nidoking_alpha.png
#	common/src/main/resources/assets/cobblemon/textures/pokemon/0227_skarmory/skarmory_alpha.png
#	common/src/main/resources/assets/cobblemon/textures/pokemon/0302_sableye/sableye_alpha.png
#	common/src/main/resources/assets/cobblemon/textures/pokemon/0303_mawile/mawile_alpha.png
#	common/src/main/resources/assets/cobblemon/textures/pokemon/0661_fletchling/fletchling_alpha.png
#	common/src/main/resources/assets/cobblemon/textures/pokemon/0662_fletchinder/fletchinder_alpha.png
#	common/src/main/resources/assets/cobblemon/textures/pokemon/0663_talonflame/talonflame_alpha.png
#	common/src/main/resources/assets/cobblemon/textures/pokemon/0932_nacli/nacli_alpha.png
#	common/src/main/resources/assets/cobblemon/textures/pokemon/0933_naclstack/naclstack_alpha.png
#	common/src/main/resources/assets/cobblemon/textures/pokemon/0934_garganacl/garganacl_alpha.png
#	common/src/main/resources/data/cobblemon/species/generation5/archeops.json
2026-04-27 15:42:51 +01:00
Polymeta 06a5e67617 tidy up changelog and fix version
Signed-off-by: Polymeta <40173118+Polymeta@users.noreply.github.com>
2026-04-27 15:39:25 +01:00
Polymeta 7b5eb7c869 Merge branch '1.8.0' into 'main'
time to get technical

See merge request cable-mc/cobblemon!2227
2026-04-27 14:03:08 +00:00
CaptainLennie cc283b200f Merge remote-tracking branch 'origin/implement_pokemon' into implement_pokemon 2026-04-27 15:10:56 +02:00
CaptainLennie 44779c68f5 Gave purrloin its neck back 2026-04-27 15:10:46 +02:00
Polymeta f43cd175ce Merge branch 'main' into implement_pokemon
# Conflicts:
#	common/src/main/resources/assets/cobblemon/lang/en_us.json
#	common/src/main/resources/data/cobblemon/species/generation4/gastrodon.json
2026-04-27 11:49:49 +01:00
Polymeta a6f725df02 license fix
Signed-off-by: Polymeta <40173118+Polymeta@users.noreply.github.com>
2026-04-27 11:31:37 +01:00
Polymeta 538bf148bc Merge branch 'tm-sprite-addon-compat' into '1.8.0'
Replaced TM rendering to use designated textures instead of dynamically colouring them, included addon support

See merge request cable-mc/cobblemon!2226
2026-04-27 08:54:17 +00:00
Polymeta df67a6659b change fallback to normal 2026-04-27 08:04:29 +00:00
Polymeta 84d5634b79 Merge branch 'fix-grepa-berry' into 'main'
Fix Grepa Berry sweetness value from 15 to 10 as per internal spreadsheet

See merge request cable-mc/cobblemon!2210
2026-04-27 08:00:44 +00:00
Paul f313e82004 ... Licenses? 2026-04-27 17:23:07 +10:00
Paul c9320ca019 Replaced TM rendering to use designated textures instead of dynamically colouring them, included addon support 2026-04-27 16:22:08 +10:00
Hiroku 58b932e35e Merge branch 'all-1.8-structure-but-again-maybe' into '1.8.0'
All 1.8 Structures

See merge request cable-mc/cobblemon!2225
2026-04-27 05:42:48 +00:00
dhi_holo db9634c254 Merge branch '1.8.0' into advancing-advancements-returns-in-1.8 2026-04-27 15:27:31 +10:00
Hiroku 9ff9329c21 Merge branch 'feat/add_trigger' into '1.8.0'
feat: add new trigger for advancement + example in docs

See merge request cable-mc/cobblemon!2221
2026-04-27 05:24:53 +00:00
dhi_holo b06628e6ba Geology Root 2026-04-27 15:24:31 +10:00
Paul e74012e2a7 Licenses 2026-04-27 15:23:38 +10:00
Paul b5cfcd5999 Changelog [skip-ci] 2026-04-27 15:21:24 +10:00
dhi_holo eccba938c7 Recipe Advancement Sorting Tweak 2026-04-27 14:46:22 +10:00
dhi_holo d6f71abb51 Advancement Sorting/Start of Cleanup 2026-04-27 14:29:19 +10:00
Paul 92f55cd23f Merge branch '1.8.0' into all-1.8-structure-but-again-maybe
# Conflicts:
#	common/src/main/kotlin/com/cobblemon/mod/common/entity/pokemon/PokemonEntity.kt
2026-04-27 13:49:50 +10:00
Paul 6dbd668856 Merge remote-tracking branch 'origin/main' into 1.8.0
# Conflicts:
#	common/src/main/kotlin/com/cobblemon/mod/common/client/gui/pokedex/widgets/PokemonInfoWidget.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/entity/pokemon/PokemonEntity.kt
2026-04-27 13:49:11 +10:00
Paul d762ee2e1b Merge remote-tracking branch 'origin/1.8.0' into all-1.8-structure-but-again-maybe 2026-04-27 13:47:16 +10:00
Paul ae87bb2423 Mending merge conflict stuff 2026-04-27 13:22:34 +10:00
Hiroku 7fd7abf7d6 Merge branch '1.8.0' into 'all-1.8-structure-but-again-maybe'
# Conflicts:
#   common/src/main/kotlin/com/cobblemon/mod/common/client/gui/pokedex/widgets/PokemonInfoWidget.kt
#   common/src/main/kotlin/com/cobblemon/mod/common/entity/pokemon/PokemonEntity.kt
2026-04-27 02:38:39 +00:00
Paul 13367df87b Merge remote-tracking branch 'origin/1.8.0' into refactor/decoupled-refined-molang-fn
# Conflicts:
#	common/src/main/kotlin/com/cobblemon/mod/common/api/molang/MoLangFunctions.kt
2026-04-27 12:27:41 +10:00
Slippy 2eb7dfdfa2 Injected all structure to the feature mixin code 2026-04-26 21:20:00 -05:00
Slippy bbb031d484 Injected all structure features 2026-04-26 21:18:36 -05:00
dhi_holo ad7bb84d5c Corrected Requirement 2026-04-27 11:56:14 +10:00
dhi_holo 69eb396229 Fixed my mistake 2026-04-27 11:35:21 +10:00
dhi_holo 06abdaf683 Merge remote-tracking branch 'origin/feat/add_trigger' into advancing-advancements-returns-in-1.8 2026-04-27 11:16:40 +10:00
dhi_holo 79e0c2f1bf Advancement Shuffle - Potion 2026-04-27 11:15:20 +10:00
Slippy d0b50bc2a8 Merge branch 'All-1.8-Structures' into all-1.8-structure-but-again-maybe 2026-04-26 18:52:47 -05:00
dhi_holo dbee413af5 Finalized Cleanup
New Advancement Names Completed
2026-04-27 09:52:25 +10:00
dhi_holo 21a1d839ae Merge branch '1.8.0' into advancing-advancements-returns-in-1.8 2026-04-27 09:40:24 +10:00
dhi_holo 353f7f6d33 Update en_us.json
New Advancement Names Completed
2026-04-27 09:36:34 +10:00
Test 1c5863877b Merge branch '1.8.0' of https://gitlab.com/cable-mc/cobblemon into 1.8.0 2026-04-26 18:32:24 -04:00
Test 374a6fa321 move size mark application to molang, update size display in summary 2026-04-26 18:31:37 -04:00
Test 33a350089f Merge branch 'starter-selection-aspect-fix' into '1.8.0'
Fix aspects not being copied for rendering the pokemon on the Starter Selection Pokemon Buttons

See merge request cable-mc/cobblemon!2224
2026-04-26 21:43:01 +00:00
dhi_holo 35b28075e4 Merge branch '1.8-gert-fixes' into 'advancing-advancements-returns-in-1.8'
Additional Gem Fixes and TM Shelf refactoring to Disc Shelf

See merge request cable-mc/cobblemon!2222
2026-04-27 07:41:58 +10:00
CaptainLennie 8066823186 Implemented new animations for torchic 2026-04-26 21:18:14 +02:00
CeeJay 9660e64dff Merge branch '1.8.0' into porygon-monitor-fix 2026-04-26 13:53:21 -04:00
Gertimoshka d2e95ceefd Fix aspects not being copied for rendering the pokemon on the Starter Selection Pokemon Buttons 2026-04-26 12:11:54 +03:00
CeeJay f992a9cf0f move sounds to client side, and make them Cancellable 2026-04-26 03:32:34 -04:00
Carmendar c36f6933aa Crobat riding and temp Skarmory ride stats. 2026-04-26 02:23:09 -05:00
Gertimoshka 54112f02b5 Fixed Pickblock and Silktouch Gem Clusters not storing data 2026-04-26 09:38:29 +03:00
Gertimoshka e98fc55dcb What? 2026-04-26 09:29:03 +03:00
Gertimoshka 2f907988fb Gem Clusters will have predefined stunted on the item to stop annoying stacking 2026-04-26 09:09:49 +03:00
Hiroku 8b350ddb4b Merge branch 'feature/weighted-choice-feature' into 'main'
feat: choice feature, but with weights!

See merge request cable-mc/cobblemon!2193
2026-04-26 06:06:59 +00:00
Hiroku cbf03289a6 Merge branch 'pledge-moves' into 'main'
Pledge combo move effects implemented

Closes #1988

See merge request cable-mc/cobblemon!2201
2026-04-26 06:05:24 +00:00
CraterandHiroku 57db94eb00 Pledge combo move effects implemented 2026-04-26 06:05:23 +00:00
Hiroku 70850d546d Merge branch 'perf/lazier' into 'main'
perf: make certain things lazier to reduce allocations

See merge request cable-mc/cobblemon!2209
2026-04-26 06:04:34 +00:00
Hiroku 5fe1dfbfff Merge branch 'CobwebImmunityForSpiderPokemon' into '1.8.0'
CobwebImmunityForSpiderPokemon

See merge request cable-mc/cobblemon!2217
2026-04-26 06:02:58 +00:00
dhi_holo c81494bec2 Update CHANGELOG-1.8.md 2026-04-26 15:56:02 +10:00
dhi_holo cd965961ae Update obtain_ancient_tm.json
Thank you Berber, for your diligent work cataloguing what TMs are needed for this
2026-04-26 15:53:14 +10:00
Gertimoshka 52238abe35 Finalize Refactor, Correct Gem placement Sound 2026-04-26 08:50:15 +03:00
dhi_holo 7594582520 Advancements Advanced
Need a list of the Ancient TMs and to merge with !2221 to complete and be ready to merge
2026-04-26 15:19:37 +10:00
Gertimoshka a240e4e48c Merge branch 'advancing-advancements-returns-in-1.8' into 1.8-gert-fixes 2026-04-26 08:08:35 +03:00
Gertimoshka 4dc279b664 Disc Shelf dont consume item on creative and TM Shelf refactor to Disc Shelf 2026-04-26 08:00:31 +03:00
Slippy 8b371127ed 1,000 files later... 2026-04-25 23:55:49 -05:00
dhi_holo b3e59b5151 Merge branch 'advancing-advancements-returns-in-1.8' of https://gitlab.com/cable-mc/cobblemon into advancing-advancements-returns-in-1.8 2026-04-26 14:18:29 +10:00
dhi_holo abfaec1d05 Advancement Advances 2026-04-26 14:17:46 +10:00
terrainwax e503ddbc69 add trigger for type gem + handler 2026-04-26 06:16:53 +02:00
terrainwax 643b43d8bc feat: add new trigger for advancement + example in docs 2026-04-26 05:34:56 +02:00
dhi_holo 5c5c236d1b Corrected Reference 2026-04-26 12:55:51 +10:00
dhi_holo ee4e9dd250 Fixed Missing Loot Table 2026-04-26 12:44:26 +10:00
dhi_holo 27cb0dc449 Deepslate Crystal Core Model Fix 2026-04-26 12:39:53 +10:00
Qther 7efd4e182d fix mistake in summation of segment length 2026-04-26 10:14:37 +08:00
dhi_holo 5781c18868 Matched to Refactor
Updated to match the Type Gem Refactor
2026-04-26 12:10:44 +10:00
dhi_holo b43e5e180e Merge branch '1.8.0' into advancing-advancements-returns-in-1.8 2026-04-26 12:02:57 +10:00
Hiroku be439dfc24 Merge branch 'type-gem-id-refactoring' into '1.8.0'
Type gem and deepslate core refactoring

See merge request cable-mc/cobblemon!2218
2026-04-26 01:40:46 +00:00
dhi_holo 913d11cccc Merge branch '1.8.0' into advancing-advancements-returns-in-1.8 2026-04-26 11:28:32 +10:00
Polymeta d6f208366e Merge branch 'sterr/sound' into '1.8.0'
Some block sounds and alpha cry tweaks

See merge request cable-mc/cobblemon!2220
2026-04-25 21:40:22 +00:00
CaptainLennie d82c4ed444 Implemented new animations for flygon 2026-04-25 23:32:36 +02:00
Sterrezo 6ddf2ee5f9 Merge branch '1.8.0' into sterr/sound 2026-04-25 23:14:41 +02:00
CaptainLennie 4f537a2b37 Merge remote-tracking branch 'origin/implement_pokemon' into implement_pokemon 2026-04-25 22:42:11 +02:00
CaptainLennie 5060762894 Implemented purrloin & liepard animations 2026-04-25 22:42:01 +02:00
GenotypeXD dbf42cb102 Nidoking Walkspeed 2026-04-25 15:25:38 -05:00
GenotypeXD db75ceefa8 Implemented Cherubi line (needs scaling) and nidoking animations 2026-04-25 15:23:48 -05:00
JazzMcNade abaec8778b Merge branch '1.8.0' into CobwebImmunityForSpiderPokemon 2026-04-25 15:03:38 -05:00
GenotypeXD f186f03f54 Merge remote-tracking branch 'origin/implement_pokemon' into implement_pokemon 2026-04-25 13:32:06 -05:00
GenotypeXD ad2949ceb1 Implemented Hisuian Avalugg 2026-04-25 13:31:09 -05:00
CaptainLennie ff79a17299 Fixed skarmory poser issues, implemented joltik animations & Updated changelog 2026-04-25 17:16:04 +02:00
Sterrezo ac169120d6 Added sounds to type gem blocks and clusters 2026-04-25 15:34:27 +02:00
Gertimoshka 3f6a4bbae4 Gem items are no longer "block items", and now you can clone gem clusters with appropriate stage and they show in creative tab 2026-04-25 16:34:05 +03:00
dhi_holo 6100252b3e Update CobblemonItemGroups.kt
Added Habitat Block to Operator Items
2026-04-25 20:27:08 +10:00
dhi_holo 27be7c6eaf Budding Visual Correction
We Forgot The Display Settings!
2026-04-25 19:45:18 +10:00
dhi_holo 18b3cf4236 Merge branch '1.8.0' into advancing-advancements-returns-in-1.8 2026-04-25 18:35:33 +10:00
Hiroku 194528b78d Merge branch 'habitats' into '1.8.0'
Added Habitat Blocks

See merge request cable-mc/cobblemon!2219
2026-04-25 08:09:23 +00:00
ewwww edd4d18150 corrected hydrapple's german name 2026-04-25 03:30:41 -04:00
Paul 8c7478d00a Phase 2 of cursed merge, Habitats now only extends 1.8.0 branch 2026-04-25 12:36:04 +10:00
Paul 5c18bfdad3 I'm attempting a cursed merge 2026-04-25 11:39:19 +10:00
dhi_holo 0e328b2166 Merge branch '1.8.0' into advancing-advancements-returns-in-1.8 2026-04-25 10:59:46 +10:00
Faintful e9fcb80d8c Refactor type gem core 2026-04-25 02:55:54 +02:00
Faintful 01b3b2952d Refactor psychic type gem cluster 2026-04-25 02:34:36 +02:00
Faintful f28db32356 Refactor psychic type gem block 2026-04-25 02:31:39 +02:00
Faintful dd5f2c2821 Refactor flying type gem cluster 2026-04-25 02:26:54 +02:00
Faintful 51a65e6cec Refactor flying type gem block 2026-04-25 02:23:29 +02:00
Faintful df1dc67cbb Refactor bug type gem cluster 2026-04-25 02:18:31 +02:00
Faintful dd81579d72 Refactor bug type gem block 2026-04-25 02:13:48 +02:00
JazzMcNade a2b62bea48 Fixed molang query function 2026-04-24 19:12:06 -05:00
Faintful c4323f79ba Refactor ghost type gem cluster 2026-04-25 02:08:35 +02:00
Faintful f1ac43c9c1 Refactor ghost type gem block 2026-04-25 02:04:51 +02:00
Faintful ce581de613 Refactor fighting type gem cluster 2026-04-25 01:55:42 +02:00
Faintful 176b5143f5 Refactor fighting type gem block 2026-04-25 01:51:17 +02:00
Faintful be94e1c8ad Refactor dark type gem cluster 2026-04-25 01:47:15 +02:00
Faintful bed13364c6 Refactor dark type gem block 2026-04-25 01:43:25 +02:00
Faintful 1fe392e57b Refactor fairy type gem cluster 2026-04-25 01:38:28 +02:00
Faintful 4391b5947e Refactor fairy type gem block 2026-04-25 01:35:04 +02:00
Faintful 499778dd21 Refactor dragon type gem cluster 2026-04-25 01:30:04 +02:00
Faintful 9c7af03837 Refactor dragon type gem block 2026-04-25 01:25:58 +02:00
Faintful db740d7b5d Refactor steel type gem cluster 2026-04-25 01:20:41 +02:00
Faintful 58a4123db2 Refactor steel type gem block 2026-04-25 01:16:42 +02:00
Faintful e10ccf2d1b Refactor ice type gem cluster 2026-04-25 01:10:53 +02:00
Faintful 25138beb88 Refactor ice type gem block 2026-04-25 01:07:56 +02:00
Faintful d72332a3cc Refactor rock type gem cluster 2026-04-25 01:04:10 +02:00
Faintful 8986220597 Refactor rock type gem block 2026-04-25 01:00:22 +02:00
Faintful e04e1db9d4 Refactor ground type gem cluster 2026-04-25 00:55:22 +02:00
Faintful 142ded7f61 Refactor ground type gem block 2026-04-25 00:51:27 +02:00
Faintful a9eaeed47f Refactor poison type gem cluster 2026-04-25 00:41:02 +02:00
Faintful de08562607 Refactor poison type gem block 2026-04-25 00:36:48 +02:00
Jackson Bowes 675855a22a Merge branch 'sterr/log-cleaning' into '1.8.0'
Fixed various log warnings

See merge request cable-mc/cobblemon!2215
2026-04-24 17:36:02 -05:00
SterrezoandJackson Bowes da24a40b7e Fixed various log warnings 2026-04-24 17:36:02 -05:00
Faintful 2049bf68b3 Refactor electric type gem cluster 2026-04-25 00:31:57 +02:00
Faintful 1aeb1e207b Refactor electric type gem block 2026-04-25 00:21:43 +02:00
Faintful a37edfaa19 Refactor water type gem cluster 2026-04-25 00:06:14 +02:00
Faintful 2d43bb518f Refactor water type gem block 2026-04-24 23:57:15 +02:00
Faintful e70b7a4d6e Refactor grass type gem cluster 2026-04-24 23:46:52 +02:00
dhi_holo 8f16e236e7 Merge branch '1.8.0' into advancing-advancements-returns-in-1.8 2026-04-25 07:45:04 +10:00
Sterrezo fce23a6898 Fixed block sound pitch and added sounds for weakness and blunder policies 2026-04-24 23:25:32 +02:00
Faintful 483589dbec Refactor grass type gem block 2026-04-24 23:15:54 +02:00
Test 0177860ebf monitor assets, fix reverted tm commit 2026-04-24 17:13:44 -04:00
Faintful 58b8c3676e Refactor fire type gem cluster 2026-04-24 23:03:53 +02:00
Faintful 32f6db33ae Refactor fire type gem block 2026-04-24 22:51:50 +02:00
Faintful d8af56cab1 Refactor normal type gem cluster 2026-04-24 20:17:42 +02:00
GenotypeXD e04437f3d3 Implemented Duraludon line, fixed Skarmory walk speed 2026-04-24 11:06:47 -05:00
Faintful 79aed2ac43 Refactor normal type gem block references 2026-04-24 18:04:31 +02:00
GenotypeXD db6e604420 Merge remote-tracking branch 'origin/implement_pokemon' into implement_pokemon 2026-04-24 11:02:31 -05:00
GenotypeXD 9b7856520f Implemented Lokix line 2026-04-24 09:50:22 -05:00
CaptainLennie 388b3891e5 Merge remote-tracking branch 'origin/implement_pokemon' into implement_pokemon 2026-04-24 16:31:52 +02:00
CaptainLennie 50742f298d Implemented riolu & lucario animations 2026-04-24 16:31:29 +02:00
GenotypeXD 9cf4177f31 Revert Pidgey Line Remodels due to anims 2026-04-24 08:37:59 -05:00
GenotypeXD 550383e275 Merge remote-tracking branch 'origin/implement_pokemon' into implement_pokemon 2026-04-24 08:36:38 -05:00
GenotypeXD 4f0f08213d Implemented Rolycoly Line 2026-04-24 08:36:09 -05:00
JazzMcNade 91042b5bb7 Spider Pokemon no longer slowed by cobweb blocks 2026-04-24 00:12:46 -05:00
Sterrezo 88261125c0 Update CHANGELOG-1.8.md 2026-04-24 03:36:53 +02:00
Sterrezo eb528e6534 Fixed redundant ride loop sounds causing log errors
They're probably still redundant, but I don't know for sure, so I'm keeping them here but with correct sound events
2026-04-24 03:35:52 +02:00
Sterrezo 2982ef1c30 Restored Galarian Ponyta's cry 2026-04-24 03:24:02 +02:00
Sterrezo 813c949216 Removed licenses to prevent log spam 2026-04-24 03:21:51 +02:00
CaptainLennie 4ba2563e92 Merge remote-tracking branch 'origin/implement_pokemon' into implement_pokemon 2026-04-24 00:40:35 +02:00
CaptainLennie 356f668067 Added wing flap sounds to aerodactyl 2026-04-24 00:40:18 +02:00
Sterrezo 85e2ccef63 How did that even happen 2026-04-23 23:08:26 +02:00
RedGenesectNinja 8b34bb0229 I forgot to include the rootbone in the posers 2026-04-23 15:28:30 -05:00
CaptainLennie c4999dc328 Implemented shellos east & west animations & tweaked skitty's shoulder position 2026-04-23 19:46:42 +02:00
CaptainLennie e484159a18 Implemented skitty animations :) 2026-04-23 18:14:28 +02:00
Sterrezo 4ca850d2e7 Added sounds to cleanse tags and spell tags 2026-04-23 16:54:21 +02:00
Sterrezo 3447caea22 Alpha cry tweaks 2026-04-23 16:36:21 +02:00
dhi_holo f66a94649b Revert Accidental Texture Backports
Mismatch of repos and running off autobrain
2026-04-23 23:21:55 +10:00
dhi_holo c495e967af Revert "Mipmap Fixes"
This reverts commit 73c9504d63.
2026-04-23 23:10:10 +10:00
dhi_holo 745bae1451 "Does the man want his appy slices??"
Saccharine Leaves can now drop the Applin Apples
2026-04-23 22:18:16 +10:00
dhi_holo 5fabc1bfaf Advancements Partially Named 2026-04-23 21:54:54 +10:00
dhi_holo 3aa6969fba Tag Growth
Increased the tagging to include new blocks
2026-04-23 21:44:33 +10:00
GenotypeXD 5ed69a17a4 Implemented Bisharp line 2026-04-23 06:20:13 -05:00
dhi_holo 73c9504d63 Mipmap Fixes 2026-04-23 20:30:47 +10:00
GenotypeXD 94f0796c44 Merge remote-tracking branch 'origin/implement_pokemon' into implement_pokemon 2026-04-23 05:12:30 -05:00
GenotypeXD 63ea4c1261 Implemented Seviper, Zangoose, and Stunky line 2026-04-23 05:11:41 -05:00
dhi_holo 63c352e5ca TYPOS 2026-04-23 19:51:49 +10:00
Hiroku 9a8c4a8630 Merge branch 'species_additions_patch' into 'main'
Change species additions loading to match wiki docs

Closes #1840

See merge request cable-mc/cobblemon!2151
2026-04-23 09:49:56 +00:00
dhi_holo 0f9df28a82 Fixed Some File Names 2026-04-23 19:33:07 +10:00
Hiroku 886242e13b Merge branch 'pokedex-genderless-layout-fix' into 'main'
Fix pokedex genderless variation layout, closes #1974

Closes #1974

See merge request cable-mc/cobblemon!2214
2026-04-23 09:26:31 +00:00
dhi_holo 303ef76bd0 Texture Updates
Lots of them. Holy Shit There's A Lot, Actually
2026-04-23 19:08:16 +10:00
GenotypeXD bfc6d8b446 Nidoking and Pidgey line tweaks 2026-04-23 04:02:01 -05:00
GenotypeXD af24f5acbe Nacli Line remodels, Mawile+Sableye Remodels 2026-04-23 04:00:43 -05:00
GenotypeXD 3986781a74 Skarmory Remodel+Animations 2026-04-23 03:58:18 -05:00
RedGenesectNinja a16d374ff3 Fixed text for the ability Wandering Spirit not showing up properly in battle 2026-04-23 03:48:35 -05:00
gisketch f224f32495 Fix pokedex genderless variation layout 2026-04-23 16:35:21 +08:00
RedGenesectNinja d31e65ea93 Implemented Galarian Yamask, Runerigus and the remodels for Yamask and Cofagrigus 2026-04-23 03:30:06 -05:00
dhi_holo 9e27c1ec85 Update metal_alloy.json
grr underscores
2026-04-23 16:25:15 +10:00
dhi_holo b02edb7f78 Merge branch '1.8.0' into advancing-advancements-returns-in-1.8 2026-04-23 16:13:04 +10:00
dhi_holo 04b0915290 Advancement Icon Files
Adds an Advancement Icon
2026-04-23 16:12:48 +10:00
Nick aaa1338150 Merge branch '1.8.0-biggest-fix-ever' into '1.8.0'
Get 1.8 to compile please

See merge request cable-mc/cobblemon!2213
2026-04-22 23:06:44 -07:00
plastered_crab e2243feee1 Craziest fix you have ever seen you probably shouldn't even look 2026-04-22 22:20:01 -07:00
dhi_holo c26bd59c21 Update metal_alloy.json
Typo fix
2026-04-23 15:14:39 +10:00
GenotypeXD b83f605da3 Merge remote-tracking branch 'origin/implement_pokemon' into implement_pokemon 2026-04-23 00:09:10 -05:00
dhi_holo f7d2776f7d Merge branch '1.8.0' into advancing-advancements-returns-in-1.8 2026-04-23 14:58:22 +10:00
dhi_holo 18ad6006ca Metal Alloy
Now with a Temporary Recipe!
2026-04-23 14:57:30 +10:00
dhi_holo 46ba44545c QADoc 24a
Evolutionary Item Drops, plus Changelog for QA Doc 24
2026-04-23 14:52:21 +10:00
Jackson Bowes cc446cb36e Merge branch 'sigma-pokemon' into '1.8.0'
Add alpha pokemon

See merge request cable-mc/cobblemon!2186
2026-04-22 22:50:41 -05:00
Jackson Bowes 91e5ad88ab Merge branch '1.21.1-tm-fixes' into '1.8.0'
Fixes for bugs found by QA team for 1.8

See merge request cable-mc/cobblemon!2211
2026-04-22 22:44:46 -05:00
dhi_holo 89a8a702c1 QADoc 24b
Added the 30 brushings, will changelog alongside 24a

Also fixed a typo
2026-04-23 13:10:14 +10:00
RedGenesectNinja 7a6a374acc Implemented Indeedee 2026-04-22 21:24:03 -05:00
Test 60d18e6522 fix pollenpuff json, add back icon on move hover 2026-04-22 21:47:27 -04:00
dhi_holo fc438520ba QADoc 25 and 26 2026-04-23 11:47:23 +10:00
dhi_holo 00836d8e51 New Advancements, Piece 1 2026-04-23 11:41:14 +10:00
GenotypeXD e1290682f8 Implemented Nidoking Remodel 2026-04-22 15:38:46 -05:00
GenotypeXD d82998bbeb Implemented Alolan Sandshrew line and Sandslash model tweaks 2026-04-22 13:49:24 -05:00
GenotypeXD 3cb5b6fd3f Implemented Pidgey Line Remodels 2026-04-22 13:19:20 -05:00
GenotypeXD e692afe86a Implemented Rockruff Line 2026-04-22 12:49:10 -05:00
Jerzykv 61680b9f21 implemented Goomy line animations 2026-04-22 19:00:01 +02:00
Plastered_Crab 0a52e70027 Merge branch '1.8.0' into sigma-pokemon
# Conflicts:
#	CHANGELOG-1.8.md
#	common/src/main/kotlin/com/cobblemon/mod/common/api/mark/Mark.kt
2026-04-22 09:15:08 -07:00
dhi_holo 8a06113b5e Attempt at PlantTypeGem Advancement Criteria
Issue for more information: #2002
In theory, I think this works, but I don't understand the Advancement Handler enough to finish this into a functional advancement trigger
2026-04-22 19:01:12 +10:00
dhi_holo 77397929cb TM Shelf Missing Data
Added in all missing data files related to the TM Shelf, and added Damaged Monitor and TM Machine to the Machines tags
2026-04-22 18:06:47 +10:00
dhi_holo 402973f814 Update CobblemonItemGroups.kt
Fixed order inconsistency
Added Missed Blocks
2026-04-22 17:41:40 +10:00
dhi_holo 89d5660a5f Update relic_coin_pouch_case.json
Fixed Missing Texture Error
2026-04-22 14:42:05 +10:00
Plastered_Crab 8d513618d3 Remove isAlpha property from PokemonHerdSpawnDetail.kt 2026-04-21 15:57:06 -07:00
CeeJay 8b5bc78b5a Merge branch '1.8.0' into porygon-monitor-fix 2026-04-21 10:59:47 -04:00
CeeJay 1cfa1ce9fd new glitching sound for Dubious Disc in monitor 2026-04-21 02:23:33 -04:00
RedGenesectNinja f52ce88756 Implemented Applin, Flapple, Appletun, Dipplin and Hydrapple. Updated changelog as well 2026-04-20 23:55:24 -05:00
Plastered_Crab a5b7e335db Rescrape TM Data for final changes 2026-04-20 17:11:28 -07:00
Faintful b9f46447b5 Fix Grepa Berry sweetness value from 15 to 10 as per internal spreadsheet 2026-04-20 15:59:54 +02:00
Qther f57050e4e3 perf: make certain things lazier to reduce allocations 2026-04-20 20:55:02 +08:00
Hiroku e504ba4dc7 Merge branch 'sterr/sound/1.8' into '1.8.0'
Move sound implementation

See merge request cable-mc/cobblemon!2207
2026-04-20 08:28:14 +00:00
Sterrezo 52036deb06 Changelog 2026-04-20 10:27:11 +02:00
Paul 08f3adceb0 Merge remote-tracking branch 'origin/1.8.0' into sterr/sound/1.8 2026-04-20 18:17:58 +10:00
Paul 115493c3a4 Merge remote-tracking branch 'origin/main' into 1.8.0 2026-04-20 18:14:40 +10:00
Hiroku c160545cf1 Merge branch 'patch-1' into 'main'
Fixed Sleep Clause

See merge request cable-mc/cobblemon!2206
2026-04-20 04:20:24 +00:00
Sterrezo 66d9e0ad9b Merge branch 'main' into sterr/sound/1.8 2026-04-20 03:43:02 +02:00
Sterrezo 9e7e116528 Move sound implementation 2026-04-20 03:41:23 +02:00
Sterrezo 89fa5c7837 Added and updated move sound assets 2026-04-20 01:47:03 +02:00
Hiroku 8bd9d113dc Merge branch 'perf/stores' into 'main'
perf: remove unnecessary copies in PCStore and reduce indirection in PokemonStore#get

See merge request cable-mc/cobblemon!2205
2026-04-19 23:37:43 +00:00
redmageman d7718b7f3e Updated SLEEP_CLAUSE to use the correct string that is recognized by showdown. 2026-04-19 15:59:57 -05:00
Qther 49944a073b perf: remove unnecessary copies in PCStore and reduce indirection in PokemonStore#get 2026-04-19 23:57:57 +08:00
Test 90183cb81e clean up moves 2026-04-19 01:37:09 -04:00
Test 1f81c42294 clean up moves 2026-04-19 01:33:30 -04:00
Hiroku a7ed6400b2 Merge branch 'Added-mark-ordering-via-index-number' into 'main'
Added new Sort Order field to sort marks by

See merge request cable-mc/cobblemon!2204
2026-04-19 01:26:37 +00:00
Dragonwhisper92 188b504575 Merge branch 'main' into Added-mark-ordering-via-index-number
# Conflicts:
#	common/src/main/kotlin/com/cobblemon/mod/common/client/gui/summary/widgets/screens/marks/MarksWidget.kt
2026-04-19 02:19:43 +01:00
Dragonwhisper92 e59d5ee6f3 Added new Sort Order field to sort marks by 2026-04-19 01:56:23 +01:00
Hiroku ea4d170756 Merge branch 'feature/starter-screen-category-order' into 'main'
feat: Starter screen category order

See merge request cable-mc/cobblemon!2196
2026-04-19 00:23:10 +00:00
Gitoido d7c3107635 chore: proper credits in AbstractChoiceSpeciesFeatureProvider.kt 2026-04-19 02:32:36 +03:00
Gitoido ef8a5ce76b refactor: clean up repeat func in OpenStarterUIPacket.kt 2026-04-19 02:30:06 +03:00
Hiroku 85d2d4aca8 Merge branch 'revert-adbfa160' into 'main'
Revert "Merge branch 'Added-mark-ordering-via-index-number' into 'main'"

See merge request cable-mc/cobblemon!2203
2026-04-18 23:04:47 +00:00
Hiroku 72a9b82bd9 Revert "Merge branch 'Added-mark-ordering-via-index-number' into 'main'"
This reverts merge request !2202
2026-04-18 22:57:45 +00:00
Hiroku adbfa16076 Merge branch 'Added-mark-ordering-via-index-number' into 'main'
Changed mark order to use indexNumber then namespace, rather than just namespace

See merge request cable-mc/cobblemon!2202
2026-04-18 21:56:22 +00:00
Dragonwhisper92 8055aed5ab Changed mark order to use indexNumber then namespace, rather than just namespace 2026-04-18 21:46:15 +01:00
Paul 95c0055932 Fixed NPC battle lock caused by non-turn induced switching 2026-04-18 16:18:38 +10:00
Hiroku d553257060 Merge branch 'patch-4' into 'main'
Fix Tatami Mat missing proper footstep sounds

See merge request cable-mc/cobblemon!2174
2026-04-18 06:05:27 +00:00
Hiroku 3069ae9722 Merge branch 'Update-ItemDrops-to-allow-data-components' into 'main'
Added Data Component support for species drops

See merge request cable-mc/cobblemon!2188
2026-04-18 05:05:20 +00:00
Paul ed05d7b754 Remove config that should not have been committed 2026-04-18 11:47:31 +10:00
Paul 2c546f00b3 gitignore common config 2026-04-18 11:47:11 +10:00
Paul f407051c4b lil changelog [skip-ci] 2026-04-18 11:41:17 +10:00
Hiroku 9f179bb573 Merge branch 'main' into 'main'
added chatter npc behaviour, script and associated lang files

See merge request cable-mc/cobblemon!2194
2026-04-18 01:33:44 +00:00
Sterrezo 36d8c3520d Bunch of tweaks to alpha cries 2026-04-18 00:38:40 +02:00
Polymeta 6105d15a03 Merge branch 'battle-lockup-fix' into 'main'
Battle lockup fix

See merge request cable-mc/cobblemon!2199
2026-04-17 12:23:40 +00:00
Polymeta 1176af0641 Merge branch 'vera-bait-changes' into 'main'
Bait Changes

See merge request cable-mc/cobblemon!2189
2026-04-17 12:23:18 +00:00
Charzard4261andPolymeta ad958f91fe Bait Changes 2026-04-17 12:23:18 +00:00
Sterrezo 4e821962e3 Added a looping sound for a dubious disc being used 2026-04-16 11:20:55 +02:00
CeeJay 962720a12c fix issues with breaking monitor during porygon process 2026-04-16 02:41:59 -04:00
RedGenesectNinja e580d5abb1 Implemented Snom and Frosmoth 2026-04-15 22:54:18 -05:00
Jackson Bowes f9821ad698 Merge branch 'porygon-update' into '1.8.0'
New Porygon Method

See merge request cable-mc/cobblemon!2200
2026-04-15 18:15:37 -05:00
CeejayandJackson Bowes ad35bf1f8a New Porygon Method 2026-04-15 18:15:36 -05:00
Paul 02baa3f44f Changelog 2026-04-14 18:20:34 +10:00
Paul 1cc4be5d28 Merge remote-tracking branch 'origin/main' into battle-lockup-fix 2026-04-14 18:19:54 +10:00
Paul f10e617203 Fixed a battle lock that occurs when a force switch is received a tick before the associated update 2026-04-14 18:19:31 +10:00
Test e41a6d7c7d Merge branch '1.21.1-tm-fixes' of https://gitlab.com/cable-mc/cobblemon into 1.21.1-tm-fixes 2026-04-12 21:28:36 -04:00
Watuneni iteiteandWeblate a1b6bd79d2 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-04-11 21:33:38 +00:00
Plastered_Crab 3528f0bec0 Merge branch '1.21.1-tm-fixes' into sigma-pokemon 2026-04-10 16:28:41 -07:00
Plastered_Crab dff6c3dc5c EV Increase Items and PP Up Items now give back glass bottles 2026-04-10 16:04:31 -07:00
Plastered_Crab 96b234a313 TM Machine no longer treats Tutor moves as learnable in the menu 2026-04-10 15:51:18 -07:00
Plastered_Crab c97b94dcc2 TM Machine no longer treats Tutor moves as learnable in the menu 2026-04-10 15:47:42 -07:00
Plastered_Crab 87c8ae373b Add Sweet Heart item 2026-04-10 15:24:57 -07:00
Plastered_Crab ed94d2bd1a Type gems do not keep age data from clusters anymore allowing them to stack 2026-04-10 14:45:41 -07:00
Plastered_Crab d7ac0128a7 Add ticksElapsed resets for key pressed and mouse clicking and scrolling to keep ScreenSaver at bay 2026-04-10 13:58:48 -07:00
Plastered_Crab 4c35714dfe Fix TM recipes that require held items 2026-04-10 13:16:26 -07:00
Gitoido 660636034b chore: CHANGELOG.md 2026-04-09 11:02:40 +03:00
Gitoido f54ed2924d refactor: unneeded sorting 2026-04-09 10:53:00 +03:00
Gitoido a432854023 feat: datapack order field for starter category 2026-04-09 10:44:13 +03:00
Gitoido 40760f2c74 refactor: extracted common choice feature provider code to abstract class, updated related implementations 2026-04-09 10:29:42 +03:00
Jolihan566 ae65b2c2b1 fixed 2026-04-07 20:53:48 +10:00
Jolihan566 d917e81804 fix variable name 2026-04-07 18:23:03 +10:00
Jolihan566 67a468a006 added chatter npc behaviour, script and associated lang files 2026-04-07 18:17:56 +10:00
Gitoido 9ad39ffd8f build: a big tiny bit of rebase 2026-04-05 16:50:02 +03:00
Gitoido e96958e1b7 chore: updated CHANGELOG.md 2026-04-05 15:14:08 +03:00
Gitoido f168e319a2 feat: choice feature, but with weights! 2026-04-05 14:59:54 +03:00
RedGenesectNinja bc23445cbc Implemented Audino and updated changelog 2026-04-04 19:14:52 -05:00
RedGenesectNinja 58fed2361f Implemented Wurmple, Silcoon, Beautifly, Cascoon and Dustox 2026-04-04 16:52:17 -05:00
Test 19a6bf28e4 wall updates 2026-04-04 16:34:00 -04:00
Test 7ea2746c2b wall unlock molang 2026-04-04 10:34:19 -04:00
Test 38b6322649 wall unlock molang 2026-04-04 10:33:29 -04:00
Test e37e73f530 Merge branch 'sigma-pokemon' of https://gitlab.com/cable-mc/cobblemon into sigma-pokemon 2026-04-04 04:04:54 -04:00
Test 4f2fefe2bd box wall 2026-04-04 04:04:05 -04:00
jackowes a1d4f499e0 remove the hardcoded alpha Eye Particle spawning and move it over to the [AspectParticleMap] 2026-04-03 18:26:57 -05:00
jackowes e7389bf129 Remove seat offset calculation. This is now done live in [LocalPlayerMixin.java] through [cobblemon$updatePassengerPosition] 2026-04-03 17:38:37 -05:00
jackowes 79a6cb5a1d Rename AlphaEyeRenderer and no longer rely on set list of eye locators (I'm looking at you magnezone and your 3 eyes). Also Scale relative to largest hitbox dimension. 2026-04-03 15:11:30 -05:00
Jackson Bowes 9e4720b233 Merge branch 'S+' into '1.8.0'
Rewrote our Height Range Structure Prevention Mixin into a Processor for addon devs to use

See merge request cable-mc/cobblemon!2190
2026-04-03 14:42:43 -05:00
AramandJackson Bowes 426cd50bb1 Rewrote our Height Range Structure Prevention Mixin into a Processor for addon devs to use 2026-04-03 14:42:43 -05:00
jackowes 51bc9b9c67 more alpha eyes. 2026-04-03 14:25:13 -05:00
jackowes 9439070325 fix to mounted player renderer axis. still issues 2026-04-03 14:07:18 -05:00
jackowes cbe9356723 Fix to alpha update packet 2026-04-03 14:06:50 -05:00
jackowes 60baf23baa Sync occupied seats from Server->Client. Server decides who sits where!! 2026-04-03 14:06:31 -05:00
jackowes be6d4f80d8 Revert "Merge branch '1.8.0' into sigma-pokemon"
This reverts commit df660329df, reversing
changes made to 641c91d335.
2026-04-03 10:43:04 -05:00
Plastered_Crab df660329df Merge branch '1.8.0' into sigma-pokemon 2026-04-03 08:17:22 -07:00
Test 0d33618e83 Merge branch '1.21.1-tm-fixes' into '1.8.0'
TM fixes, pokedex move screen updates

See merge request cable-mc/cobblemon!2191
2026-04-03 04:51:51 +00:00
Test 0803906f30 disk asset 2026-04-02 22:42:08 -04:00
Test 2c26046a3c rmv unused method 2026-04-02 21:15:55 -04:00
Plastered_Crab 641c91d335 Merge branch '1.21.1-tm-fixes' into sigma-pokemon 2026-04-02 17:20:53 -07:00
Test bdab3d04cb update tinting, cluster hitboxes 2026-04-02 20:08:05 -04:00
Test 59488974d6 update tmm json 2026-04-01 22:52:48 -04:00
Dragonwhisper92andHazar df6f200b63 Added Data Component support for species drops 2026-04-01 20:35:25 +00:00
Test 3f0561456f unused imports 2026-03-31 23:57:56 -04:00
Test 5279767829 merge 2026-03-31 23:52:26 -04:00
Test e3f8aacd9e Merge branch 'tmfix' into 1.21.1-tm-fixes
# Conflicts:
#	common/src/main/kotlin/com/cobblemon/mod/common/CobblemonBlocks.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/block/TypeGemClusterBlock.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/client/gui/tmmachine/TMMachineScreen.kt
2026-03-31 23:20:17 -04:00
Test d381dd0d21 remove unnecessary TypeGemBlock, refactor monitor assets 2026-03-31 23:00:44 -04:00
Plastered_Crab 02f3d87bc6 Merge branch '1.21.1-tm-fixes' into sigma-pokemon
# Conflicts:
#	common/src/main/kotlin/com/cobblemon/mod/common/api/tms/TMMoveManager.kt
2026-03-31 13:40:43 -07:00
Plastered_Crab 2dad3c3197 Fix Type Gem Cluster bugs 2026-03-31 13:38:21 -07:00
Plastered_Crab ea8e70d0fa Fix Type Gem Cluster bugs 2026-03-31 13:36:01 -07:00
Plastered_Crab 64717be354 Add lang files for the Type Gem Blocks, Clusters and Deepslate Crystal Core 2026-03-31 11:34:13 -07:00
Plastered_Crab bc9314b9d9 Add Baby Doll Eyes to TM list 2026-03-30 16:49:34 -07:00
Plastered_Crab 541f2dac40 Remove changes to TMMachineScreen about the Screensaver 2026-03-30 16:22:19 -07:00
Plastered_Crab adba69c675 TM Machine visually shows disc in it if there is a TM in the output slot too 2026-03-30 16:08:27 -07:00
Plastered_Crab ab831a2d9d Default TMs now show in Move Dex as Unlocked 2026-03-30 16:07:58 -07:00
Plastered_Crab faa939986a TM Machine screensaver to kick in after 1 minute idling and goes away when moving the mouse 2026-03-30 15:32:53 -07:00
Plastered_Crab b651bf1ded Fix fully evolved pokemon not tracking unlocked moves as well as Discovered TM moves in the Pokedex Move Dex 2026-03-30 15:09:04 -07:00
Plastered_Crab 8eb77cfc97 Fix hitboxes of Type Gem Clusters 2026-03-30 14:50:11 -07:00
GenotypeXD a51c8ae6d1 implemented Fletchling line remodels 2026-03-30 14:25:37 -05:00
Jackson Bowes 5809b07443 Update 1.8 changelog for alphas 2026-03-30 11:11:42 -05:00
Jackson Bowes 3fb4ca05fe Update file CHANGELOG-1.8.md 2026-03-30 10:55:28 -05:00
jackowes 19323143e5 swellow testing code be gone and mark change 2026-03-29 23:39:07 -05:00
jackowes 89de0c6392 it took me 3 hours to find this issue. Im and idiot 2026-03-29 21:51:09 -05:00
jackowes ddddfec219 fix rider positioning and remove poseoffsets from all files and be explicit about the seat locator name in the json. 2026-03-29 19:32:48 -05:00
jackowes b3c6d205ab initial changes to allow for conditional seats. (test example with swellow. need to remember to remove it) 2026-03-29 16:55:04 -05:00
Plastered_Crab b1e2eec156 Merge remote-tracking branch 'origin/sigma-pokemon' into sigma-pokemon 2026-03-27 16:30:32 -07:00
Plastered_Crab 46bb33a95f Fix TM Move Manager to check for moveset of added mons 2026-03-27 16:30:07 -07:00
jackowes 39b169082c Finalize alpha sizing. Fix alpha eye bloom rendering 2026-03-27 14:54:50 -05:00
Plastered_Crab c13e9fb35d Merge remote-tracking branch 'origin/sigma-pokemon' into sigma-pokemon 2026-03-27 08:21:21 -07:00
Plastered_Crab 5cc7dfa353 Alpha pokemon level matching uses stat boost particles now instead of test ones 2026-03-27 08:20:07 -07:00
jackowes d4dab7b88a fix foot sliding due to scaling 2026-03-26 18:48:40 -05:00
Plastered_Crab 6b697a7be1 Alphas spawn with 2 TM Moves instead of 4 2026-03-26 15:01:14 -07:00
Plastered_Crab 90fbe3be49 Merge remote-tracking branch 'origin/sigma-pokemon' into sigma-pokemon 2026-03-26 12:41:04 -07:00
Plastered_Crab 50dd1b154d Change Shiny and ALpha rates on config for Honey and Fossil Machine 2026-03-26 12:40:38 -07:00
Watuneni iteiteandWeblate 83eb483f0b 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-03-26 06:45:59 +00:00
Tyzillion ea3e389c41 Added alpha rewards tier lootpools and loot spawning molang functionality. 2026-03-26 00:18:14 -04:00
jackowes 10ed864325 Add in other eye effects and add in ride scale limiter 2026-03-25 23:08:01 -05:00
jackowes 0e9013c75e alpha eye bloom. Needs work if its gonna be used 2026-03-25 22:39:46 -05:00
Polymeta e54b22409a Merge branch 'clamp-structure-height' into '1.8.0'
Allow Slippy to define a range in which the structure will spawn

See merge request cable-mc/cobblemon!2185
2026-03-25 23:20:08 +00:00
Plastered_Crab 65afff1c3c Merge branch '1.8.0' into sigma-pokemon
# Conflicts:
#	common/src/main/kotlin/com/cobblemon/mod/common/client/render/models/blockbench/PosableModel.kt
2026-03-25 15:54:14 -07:00
Plastered_Crab 230a2db160 Alpha Pokemon to spawn with 4 random TM moves from their learnset 2026-03-25 15:50:39 -07:00
Plastered_Crab 0fdadc90e8 Alpha Pokemon level matching to players does not go below the pokemon's min evolution requirement 2026-03-25 15:33:20 -07:00
MeAlam1 e03a3abe1d Update CHANGELOG-1.8.md 2026-03-25 23:33:03 +01:00
MeAlam1 497f832995 Update StructureMixin.java 2026-03-25 23:29:42 +01:00
Plastered_Crab ecd71fe077 Alpha pokemon do not get affected by baby scale 2026-03-25 14:09:24 -07:00
Plastered_Crab 9c5a04495d Changes to herding system for alphas so they are prioritized 2026-03-25 14:01:11 -07:00
Plastered_Crab 6d3ddece03 Level Matching of Alphas based on nearest players 2026-03-25 11:30:31 -07:00
Plastered_Crab 99a0e83962 Added Shiny Chance and Alpha Chance to Honey Slathered Trees 2026-03-25 10:02:09 -07:00
Plastered_Crab 7572530a36 Added Shiny Chance and Alpha Chance to Fossil Machine 2026-03-25 09:36:13 -07:00
Hiroku 8ee0d904ed Merge branch '1.21.1-TMs' into '1.8.0'
Merge TMs into 1.8 FINALLY

See merge request cable-mc/cobblemon!1853
2026-03-25 11:24:07 +00:00
Watuneni iteiteandWeblate d8498d7a37 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-03-25 11:05:22 +00:00
Paul 291196eda7 Removed unused mixin 2026-03-25 20:30:07 +10:00
Hiroku b94e6d65b9 Merge branch '1.8.0' into '1.21.1-TMs'
# Conflicts:
#   CHANGELOG-1.8.md
#   common/src/main/kotlin/com/cobblemon/mod/common/pokemon/Pokemon.kt
#   common/src/main/kotlin/com/cobblemon/mod/common/world/feature/CobblemonFeatures.kt
2026-03-25 10:23:42 +00:00
Watuneni iteiteandWeblate 3693e7eec0 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-03-25 05:21:29 +00:00
Plastered_Crab 7f9ed14be7 Herd spawns can be designated held items 2026-03-24 18:48:21 -07:00
Plastered_Crab f3e6e5a94c Alpha Pokémon always retaliate if attacked 2026-03-24 18:12:32 -07:00
Plastered_Crab 325c4093eb Adjust Alpha sizes 2026-03-24 18:02:02 -07:00
Plastered_Crab 2510b23401 Add Alpha spawning via herd spawn system 2026-03-24 17:21:58 -07:00
Plastered_Crab d4b6f6e55e Pull down Showdown changes for Alpha battles 2026-03-24 15:50:04 -07:00
Watuneni iteiteandWeblate 60c9f5d054 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-03-24 20:51:43 +00:00
Plastered_Crab 3d38dc2c99 Add Alpha Pokemon Bait effect 2026-03-23 18:28:54 -07:00
Plastered_Crab 6cc384abbb Size Marks assigned if exactly min or max size variation 2026-03-23 10:19:56 -07:00
jackowes 205ec6a228 name change for sendout scaling 2026-03-22 22:25:14 -05:00
Paul 943625056a Fixed alpha and baby scaling not being respected in various places 2026-03-23 13:04:29 +10:00
jackowes 06e0bbc502 bring in alpha eyes pngs and add the utility script that did it 2026-03-22 19:26:02 -05:00
jackowes d83d5cd3da make sure the alpha eyes textures not being found doesn't cause issues 2026-03-22 18:49:09 -05:00
jackowes 6215f8afa5 Add utility script that populates all pokemon resolvers with their alpha_eyes texture entry. Script has been run as you can see :) 2026-03-22 18:47:41 -05:00
jackowes 60fdd3325e remove duplicate registration 2026-03-22 17:26:41 -05:00
Paul eedcdafcbe Removed SpeciesLevel data file in favour of expanding the pokedex data 2026-03-22 14:46:44 +10:00
jackowes b39068283f better initial defualts for reverb length 2026-03-21 22:27:12 -05:00
jackowes 34c4cc1579 alpha cry pitch down and reverb. Beginning of alpha eye trail rendering. Adjust config defaults for alpha sizes to be larger (mechanic design discussion) 2026-03-21 22:16:09 -05:00
washashu0905andWeblate e1541a3512 Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 98.2% (8898 of 9061 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/zh_Hant/
2026-03-22 01:23:31 +00:00
jackowes b2e1558e03 Make the aspect field for marks a list instead 2026-03-21 14:34:26 -05:00
Paul 34595e01a9 Simplified some TM stuff 2026-03-21 22:33:29 +10:00
Paul 60b9ca7b7f Fixed a lol woopsy 2026-03-21 19:21:07 +10:00
Paul 83aea117c6 TM bits of cleanup and some fixes 2026-03-21 16:52:56 +10:00
washashu0905andWeblate 1c1c3f51bb Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 97.0% (8792 of 9061 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/zh_Hant/
2026-03-20 20:39:49 +00:00
jackowes 90bd717d7b switch alpha eye rendering to aspects. still need to move eye particles over to not be hardcoded. 2026-03-19 22:16:01 -05:00
Plastered_Crab 78b348329c Add more clusters to world genned type gem clusters 2026-03-17 19:17:35 -07:00
Plastered_Crab b64013c995 Type Gem Cluster world gen fix 2026-03-17 18:30:13 -07:00
Plastered_Crab 85003c9829 Get TM Unlocking on Level Up working again - Needs review 2026-03-17 14:12:53 -07:00
Plastered_Crab d9133e854a Clean up TM move sync 2026-03-17 13:13:04 -07:00
阿鱼andWeblate 500f1f53a4 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-03-15 22:11:24 +00:00
Watuneni iteiteandWeblate 9ed10bb217 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-03-15 03:33:00 +00:00
Watuneni iteiteandWeblate 2f6d4313e7 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-03-13 18:46:43 +00:00
Plastered_Crab 05afe191e6 Add new textures for Data Monitor screens 2026-03-10 15:24:57 -07:00
Plastered_Crab e3b5067f31 Last Bug for the TM Machine squashed 2026-03-10 12:05:16 -07:00
Plastered_Crab bfa2d470f0 remove a few config checks 2026-03-10 11:34:47 -07:00
Plastered_Crab 53c0b28deb kill terablast 2026-03-10 11:33:59 -07:00
阿鱼andWeblate d640a04fa6 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-03-10 18:05:39 +00:00
Plastered_Crab 5e9208d898 Fix small typos 2026-03-10 09:19:19 -07:00
Plastered_Crab 23a91ec2c9 Rescrape TMs to be current 2026-03-10 09:06:15 -07:00
Plastered_Crab 9998a328e3 Edit TM scraper 2026-03-10 09:02:38 -07:00
Plastered_Crab 9f07747cac Cleanup Obtainment methods for TMs 2026-03-10 09:02:22 -07:00
Plastered_Crab a7998bcec5 Cleanup Obtainment methods for TMs 2026-03-10 09:01:59 -07:00
Plastered_Crab 5983b29e9c Added Changelog 2026-03-09 17:54:39 -07:00
Plastered_Crab 749f441913 Merge branch 'main' into 1.21.1-TMs 2026-03-09 17:41:11 -07:00
Plastered_Crab dabbcceb9c Add Configs for having TMs be infinite use 2026-03-09 17:08:24 -07:00
Plastered_Crab 11f8313fc3 Add Configs for unlocking all TM and Level Up Moves and for Pokedex and TM Machine 2026-03-09 14:27:27 -07:00
Plastered_Crab 32b813620b Fix TM Machine Screen Back button to be more readable 2026-03-09 14:25:39 -07:00
Plastered_Crab 8147067b2e Fix Disk Rack West / East interaction 2026-03-09 08:39:31 -07:00
Plastered_Crab 24c6544e83 Sound Engine mixin to not have high octave pitches become flattened 2026-03-06 11:27:57 -08:00
geumuandWeblate 7749f346b5 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-03-06 16:37:11 +00:00
Micky a2fe6364cd Fix Tatami Mat missing proper footstep sounds 2026-03-06 10:02:22 +00:00
Plastered_Crab b422ee4d29 Disk Jockeyyyyyyyy 2026-03-05 14:41:56 -08:00
Plastered_Crab a83867e153 When Data Monitor breaks it drops the stored disk, but not when moved by piston 2026-03-05 13:11:10 -08:00
Plastered_Crab 523973d2c0 Data monitor consumes the disk from player hand in Survival 2026-03-05 12:47:43 -08:00
Plastered_Crab 746160fa18 Disk Shelf works with Comparators and output a signal based on how many slots are filled 2026-03-05 12:06:05 -08:00
Plastered_Crab 837ba9679b Fix inverted columns and interaction with Disk Shelf 2026-03-05 11:35:33 -08:00
Plastered_Crab db7a319441 Invert Hopper interaction slots and storage array index 2026-03-05 11:00:14 -08:00
Plastered_Crab e284032c7e Give TM command allows for specifying quantity now 2026-03-05 10:05:17 -08:00
Plastered_Crab 3db9dd02f2 Disk Shelf works with Hoppers now 2026-03-05 08:54:30 -08:00
Plastered_Crab e680ec8790 If TM Shelf gets destroyed it drops stored disks 2026-03-04 16:05:57 -08:00
Plastered_Crab dc4f831e02 Fix slot interaction zones in North and South directions 2026-03-04 15:44:42 -08:00
Plastered_Crab b3a00c40b5 Adjust Slot brightness for Disk Shelf 2026-03-04 15:18:50 -08:00
Plastered_Crab f56fb0f50a Add new assets for TM Shelf disks 2026-03-04 14:27:12 -08:00
Plastered_Crab ec732bc03d Fix alignment issues and Lighting issues for TM Shelf 2026-03-04 13:42:43 -08:00
Plastered_Crab 229abd4a13 Fix lighting on rendered slot items 2026-03-04 11:46:18 -08:00
Plastered_Crab 7e92c17178 Fix WIP assets for TM Shelf disks 2026-03-04 11:17:21 -08:00
Plastered_Crab 77aa3208a0 Fix interaction zones on TM Shelf 2026-03-04 10:14:47 -08:00
wajosalo21xandWeblate a29bc68663 Translated using Weblate (Spanish (Ecuador))
Currently translated at 98.3% (8908 of 9061 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/es_EC/
2026-03-03 21:07:51 +00:00
阿鱼andWeblate 1358380905 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-03-03 21:07:51 +00:00
Jerzykv a03090d0da Merge remote-tracking branch 'origin/implement_pokemon' into implement_pokemon 2026-03-03 20:46:40 +01:00
Jerzykv d9d5229a1f forgot this again 2026-03-03 20:46:22 +01:00
Polymeta 34e64da0c6 Merge branch 'sigma-pokemon' into 'sigma-pokemon'
Alpha boost implementation

See merge request cable-mc/cobblemon!2114
2026-03-02 23:38:04 +00:00
Plastered_Crab b2ea715195 Update with main and add new Type Gem assets 2026-03-02 12:49:17 -08:00
wajosalo21xandWeblate 2679885fb4 Translated using Weblate (Spanish (Ecuador))
Currently translated at 98.3% (8908 of 9061 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/es_EC/
2026-02-28 19:45:51 +00:00
阿鱼andWeblate 278c5d8e81 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-02-28 19:45:50 +00:00
gruxor 7327ae14fd Implemented ActionEffectInstruction for StartInstruction, relocated resource 2026-02-28 04:38:03 -05:00
Weblate a55916998b 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-02-27 02:46:24 +00:00
Patch Notes GuyandWeblate cca2d54682 Translated using Weblate (Spanish (Ecuador))
Currently translated at 0.0% (0 of 0 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/es_EC/
2026-02-27 02:44:12 +00:00
Weblate f5bd6a4054 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-02-27 02:40:18 +00:00
Patch Notes GuyandWeblate 13466815e5 Added translation using Weblate (Spanish (Ecuador)) 2026-02-27 02:40:15 +00:00
Polymeta 35e4aafe99 Merge branch 'main' into 1.8.0 2026-02-26 15:46:01 +00:00
Plastered_Crab eab6fa9b40 Merge branch 'main' into 1.21.1-TMs 2026-02-25 13:43:40 -08:00
Watuneni iteiteandWeblate e871047cf1 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-02-25 21:37:45 +00:00
Kenji_64 ea4af39853 New mounts unlocked: Drampa and Archeops! 2026-02-25 20:33:44 +01:00
Jerzykv 1440ed692e Litleo blink fix 2026-02-25 18:00:29 +01:00
Jerzykv 444657a468 Implemented Skitty and Delcatty 2026-02-25 17:59:54 +01:00
Nico MerenqandWeblate a1de8c95f6 Translated using Weblate (Russian)
Currently translated at 79.5% (7206 of 9061 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/ru/
2026-02-24 17:47:11 +00:00
geumuandWeblate eb94bdb9c2 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-02-21 11:40:10 +00:00
arvid6andWeblate 509c2365bb Translated using Weblate (Spanish)
Currently translated at 94.0% (8522 of 9061 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/es/
2026-02-20 23:12:50 +00:00
arvid6andWeblate 6271476ed3 Translated using Weblate (Spanish)
Currently translated at 93.2% (8445 of 9061 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/es/
2026-02-20 10:57:20 +00:00
arvid6andWeblate f5cec10e3e Translated using Weblate (Spanish)
Currently translated at 93.2% (8445 of 9061 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/es/
2026-02-20 10:13:25 +00:00
Watuneni iteiteandWeblate b6f20c1d75 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-02-19 06:59:35 +00:00
geumuandWeblate 750d583770 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-02-17 20:41:32 +00:00
arvid6andWeblate 05f0b439a8 Translated using Weblate (Spanish)
Currently translated at 91.9% (8332 of 9061 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/es/
2026-02-17 20:41:32 +00:00
geumuandWeblate 1cb4ffd02f 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-02-17 17:11:34 +00:00
geumuandWeblate 8600d026c3 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-02-17 17:02:57 +00:00
ewwww 8140dd773e oopy 2026-02-17 05:45:52 -05:00
ewwww 23717a634c eng lang text tweaks, changed some pokedex entries, patched up typing errors and inconsistencies 2026-02-17 05:34:42 -05:00
ewwww c966e93f22 tweaks to pangoro + added new method for getting dragonite's mailbag cosmetic 2026-02-17 04:33:08 -05:00
ewwww f49c01916a added pancham & pangoro 🐼 2026-02-17 00:48:41 -05:00
Zack the GhastandWeblate 4e24c764de Translated using Weblate (Portuguese (Portugal))
Currently translated at 70.1% (6355 of 9061 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/pt_PT/
2026-02-16 10:51:45 +00:00
Plastered_Crab 98de423f91 Add giveTM command 2026-02-14 01:22:15 -08:00
ewwww 89c2fb49cd implemented zubat, golbat, and crobat remodels + fixed croagunk's walk speed 2026-02-14 04:19:16 -05:00
Aramandgruxor ae05be2ce2 Slippy can Cook now! 2026-02-14 00:35:17 -05:00
Paulandgruxor 5f2984a3d0 Fixed woopsies in changelog 2026-02-14 00:35:17 -05:00
Paulandgruxor de41fdf871 Fixed multi-spawns in a single pass using the same bucket for all of them 2026-02-14 00:35:17 -05:00
Paulandgruxor af491f02a2 Added more molang expressions to a bunch of composed pool properties, fixed some bugs 2026-02-14 00:35:17 -05:00
Paulandgruxor e40a3331e2 Added egg move selector 2026-02-14 00:35:17 -05:00
Paulandgruxor 6dac494a0f more doco changes [skip-ci] 2026-02-14 00:35:17 -05:00
Paulandgruxor 246ddc7a54 Change silly default example weight to the actual default weight 2026-02-14 00:35:17 -05:00
Paulandgruxor f7c560db78 Rearrange doco 2026-02-14 00:35:17 -05:00
Paulandgruxor bae7ad5ce1 Added npcAspects condition for party pool entries 2026-02-14 00:35:17 -05:00
Paulandgruxor 2e59fa4f68 Documentation 2026-02-14 00:35:17 -05:00
Paulandgruxor 474cf1c6db Added last_suitable_offensive move selector, added alpha moveset builder 2026-02-14 00:35:17 -05:00
Paulandgruxor 8cd46a5a49 Stack all the cobblemon:move_weights.json from any datapacks onto one big map, like tags 2026-02-14 00:35:16 -05:00
Paulandgruxor 382bf67866 Added more advanced moveset and party construction for NPCs 2026-02-14 00:35:16 -05:00
Plastered_Crab c7d93ebfc5 Merge branch '1.8.0' into sigma-pokemon 2026-02-13 21:13:58 -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
Plastered_Crab e7cd9237f6 Have Move Dex only show Level Up, TM, and Egg moves 2026-02-13 19:43:49 -08:00
Plastered_Crab 84e22c68c7 Add white background for move list area on move Dex and add lang tooltips for filters 2026-02-13 19:16:36 -08:00
Plastered_Crab 300f2fc53c Add new type symbols, add dividing line 2026-02-13 15:43:18 -08:00
Plastered_Crab 2dfb88467b Added new filters to the Pokedex. More work on showing undiscovered/discovered level up moves per species in Move Dex 2026-02-13 13:45:56 -08:00
Plastered_Crab 589aab3b1a Move Dex adjustments 2026-02-13 11:50:27 -08:00
Plastered_Crab e17ca3a422 Clean up some of the Move Dex text 2026-02-13 11:07:58 -08:00
Plastered_Crab 0153846c7b Moves in Move Dex are hidden per species until discovered 2026-02-13 10:37:21 -08:00
arvid6andWeblate 192d40a475 Translated using Weblate (Spanish)
Currently translated at 91.9% (8328 of 9061 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/es/
2026-02-13 15:54:44 +00:00
geumuandWeblate 8c86bb636d 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-02-13 12:12:26 +00:00
arvid6andWeblate 5dc43a8d58 Translated using Weblate (Spanish)
Currently translated at 91.8% (8318 of 9061 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/es/
2026-02-13 12:12:25 +00:00
arvid6andWeblate 68a3d7e3b1 Translated using Weblate (Spanish)
Currently translated at 91.8% (8318 of 9061 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/es/
2026-02-13 10:26:11 +00:00
Plastered_Crab f598f8d645 Secondary sorting for Move Dex 2026-02-12 21:03:48 -08:00
Plastered_Crab 8e3e047646 EVEN MORE Progress on the Move Dex 2026-02-12 19:28:40 -08:00
Plastered_Crab 551858df57 MORE Progress on the Move Dex 2026-02-12 14:42:39 -08:00
Plastered_Crab a7e3f4a7a1 Progress on the Move Dex 2026-02-12 11:15:52 -08:00
Plastered_Crab 94d64bb5c6 Progress on the Move Dex 2026-02-12 08:36:06 -08:00
gruxor 002e68b599 Remove unnecessary fail lang, change remaining one to "start" 2026-02-11 20:53:51 -05:00
gruxor 2ac2a57e12 Alpha boost implementation 2026-02-11 20:53:51 -05:00
gruxor b84002d142 Callback changes/restoration 2026-02-11 19:56:20 -05:00
Zack the GhastandWeblate 8f4b2c3c0a Translated using Weblate (Portuguese (Portugal))
Currently translated at 69.9% (6334 of 9061 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/pt_PT/
2026-02-11 23:49:07 +00:00
arvid6andWeblate 6645cb68f7 Translated using Weblate (Spanish)
Currently translated at 91.7% (8316 of 9061 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/es/
2026-02-11 23:49:06 +00:00
Plastered_Crab e569acc648 Merge remote-tracking branch 'origin/1.21.1-TMs' into 1.21.1-TMs
# Conflicts:
#	common/src/main/kotlin/com/cobblemon/mod/common/CobblemonNetwork.kt
2026-02-11 13:58:05 -08:00
Plastered_Crab 7c374b6e29 Tweaks to proceed with main merge to TMs 2026-02-11 13:56:22 -08:00
Plastered_Crab 3c128d9009 Merge branch 'main' into 1.21.1-TMs
# Conflicts:
#	common/src/main/kotlin/com/cobblemon/mod/common/CobblemonNetwork.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/api/storage/player/GeneralPlayerData.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/api/storage/player/adapter/PlayerDataJsonBackend.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/api/storage/player/adapter/PlayerDataMongoBackend.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/api/storage/player/client/ClientGeneralPlayerData.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/client/CobblemonClient.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/client/gui/toast/CobblemonToast.kt
2026-02-11 13:40:44 -08:00
Plastered_Crab f5321a34c3 Merge branch 'main' into 1.21.1-TMs
# Conflicts:
#	common/src/main/kotlin/com/cobblemon/mod/common/CobblemonNetwork.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/api/storage/player/GeneralPlayerData.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/api/storage/player/adapter/PlayerDataJsonBackend.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/api/storage/player/adapter/PlayerDataMongoBackend.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/api/storage/player/client/ClientGeneralPlayerData.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/client/CobblemonClient.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/client/gui/toast/CobblemonToast.kt
2026-02-11 12:23:37 -08:00
Plastered_Crab f96ea92a4c Merge branch 'main' into sigma-pokemon
# Conflicts:
#	common/src/main/kotlin/com/cobblemon/mod/common/net/messages/client/spawn/SpawnPokemonPacket.kt
2026-02-11 00:08:52 -08:00
Plastered_Crab a1e10bf3b1 Pokemon that spawn as an alpha are given and assigned the Alpha Mark which is set as the active mark. Mark being present controls the eye overlay and particles 2026-02-11 00:06:23 -08:00
Plastered_Crab eccb4bb7af Add Post Spawn Event and callback 2026-02-11 00:04:18 -08:00
Plastered_Crab 254d5e1343 Alpha eye particles 2026-02-10 21:37:04 -08:00
Zack the GhastandWeblate 4c5f330f2a Translated using Weblate (Portuguese (Portugal))
Currently translated at 69.4% (6289 of 9061 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/pt_PT/
2026-02-11 02:22:03 +00:00
arvid6andWeblate 00d445b793 Translated using Weblate (Spanish)
Currently translated at 91.5% (8296 of 9061 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/es/
2026-02-11 02:22:01 +00:00
Plastered_Crab a3cb3e8d9e oops staged only half the files 2026-02-10 14:49:31 -08:00
Plastered_Crab 69354fac58 Alphas got them red eyes boi 2026-02-10 14:47:07 -08:00
Plastered_Crab d40f3599b9 Pokemon with different size variation scale back to 1.0 scale when shoulder mounted and Alphas cannot be shoulder mounted 2026-02-10 08:09:22 -08:00
geumuandWeblate cd236c2dea 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-02-10 10:12:12 +00:00
Iván Martín Quinteiro JourdanandWeblate aebf40f78c Translated using Weblate (Spanish)
Currently translated at 89.4% (8107 of 9061 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/es/
2026-02-10 10:12:11 +00:00
arvid6andWeblate 52b28fb73f Translated using Weblate (Spanish)
Currently translated at 89.4% (8107 of 9061 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/es/
2026-02-10 10:12:11 +00:00
Plastered_Crab 531ed8b827 Pokemon grow in size from level 1 to 10 as if they are aging 2026-02-09 21:27:11 -08:00
Plastered_Crab fc844fca9e Pokemon spawn with size variation and Dex Scanner reveals that info 2026-02-09 14:20:05 -08:00
Plastered_Crab 23bfa090d2 Alpha Pokemon Size Variation driven by hitbox size and configs 2026-02-09 12:25:36 -08:00
Plastered_Crab 2754bfc525 Data Monitor ejects disk out from monitor correctly 2026-02-09 09:02:49 -08:00
Zack the GhastandWeblate 9b75f20fff Translated using Weblate (Portuguese (Portugal))
Currently translated at 68.9% (6250 of 9061 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/pt_PT/
2026-02-09 11:15:58 +00:00
Plastered_Crab 3d1aecce13 Data Monitor to eject disk outwards and also unlock TM upon ejection 2026-02-09 00:30:31 -08:00
Nico MerenqandWeblate 56b1fc1149 Translated using Weblate (Russian)
Currently translated at 78.9% (7154 of 9061 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/ru/
2026-02-08 16:22:17 +00:00
阿鱼andWeblate 662ca83a60 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-02-08 10:52:27 +00:00
Nico MerenqandWeblate d80ff055f5 Translated using Weblate (Russian)
Currently translated at 77.4% (7015 of 9061 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/ru/
2026-02-08 10:52:26 +00:00
arvid6andWeblate 898f48cf8f Translated using Weblate (Spanish)
Currently translated at 86.8% (7871 of 9061 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/es/
2026-02-08 10:52:24 +00:00
aeroeng15 3bd5d4849c Changelog 2026-02-07 20:44:59 -07:00
aeroeng15 9519b51c8e Change species additions loading to match wiki docs 2026-02-07 20:42:17 -07:00
Kenji_64 c78e884e9e Some poser fixes on Charcadet line 2026-02-07 20:35:15 +01:00
geumuandWeblate 1688dd42b3 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-02-07 03:20:44 +00:00
Kenji_64 e98ba597dd Fixed poser interpolation issues on Tinkaton, Cinderace and Bronzong 2026-02-05 17:20:32 +01:00
Kenji_64 7c93834b2c Fixed a missing pixel on Annihilape's texture 2026-02-05 17:18:19 +01:00
Plastered_Crab 38cd081ad6 Data Monitor to eject disk if player interacts with empty hand or non-disk item 2026-02-04 13:50:57 -08:00
Plastered_Crab 54a14ab805 Add new TM sync from move function for better performance when checking newly learned moves. 2026-02-04 13:49:37 -08:00
Plastered_Crab 633b45287c Sync TM moves upon new move added to a pokemon, and remove redundant sync checks on evolve and level up. 2026-02-04 13:36:28 -08:00
Plastered_Crab 3619f42090 Changes to Fossil machine Multi block to eject disks if the data monitor with one inserted becomes a Fossil Machine 2026-02-03 20:26:39 -08:00
Plastered_Crab 695453ffdb Changes to data monitor to allow disks to be placed inside to change the screen to learn TMs and change the screen texture 2026-02-03 20:25:09 -08:00
Kenji_64 b67bfca556 Implemented Porygon line model edits 2026-02-01 15:43:47 +01:00
Kenji_64 0fe8caf88f Pichu and Pikachu can swim again 2026-02-01 14:49:44 +01:00
Kenji_64 1b4360f0c6 Fix for Magnezone's shiny emissive in the resolver displaying incorrectly 2026-02-01 14:49:30 +01:00
Instrafe b5bb385106 Implemented remodels for Goomy, Sliggoo, and Goodra 2026-01-31 12:07:09 -05:00
geumuandWeblate c4e8fe9c74 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-31 15:46:02 +00:00
Zack the GhastandWeblate 3ecaf2dd13 Translated using Weblate (Portuguese (Portugal))
Currently translated at 68.7% (6227 of 9061 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/pt_PT/
2026-01-31 01:39:31 +00:00
geumuandWeblate 281afd74e6 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-31 01:39:30 +00: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
Plastered_Crab dd7066e8fa Sync New Tms after Level Up and Evolving 2026-01-29 12:34:08 -08:00
Plastered_Crab 416f003927 Remove debugging from Type Gem clusters 2026-01-29 10:44:13 -08:00
Plastered_Crab 3be3dc3de2 Add TM Data Sync upon login via scheduled task 2026-01-29 10:43:29 -08:00
Plastered_Crab a8f273737d Fix all default unlocked TMs 2026-01-26 12:41:02 -08:00
Plastered_Crab a185805b3f Fix scraper to scrape locked vs default TMs properly 2026-01-26 12:40:10 -08:00
Plastered_Crab defab6eaff Brief edit to TM scraper to properly scrape default TMs 2026-01-26 12:29:39 -08:00
Plastered_Crab 72fc1f1fb9 Fix the visual stage of the Type Gem Cluster Item Entity when dropped (with silk touch for example) 2026-01-26 11:53:58 -08:00
Plastered_Crab f96c69ab54 Unlock TMM recipe when interacting with the TMM without knowing the recipe 2026-01-26 11:48:08 -08:00
Plastered_Crab d51039dbb8 Merge branch 'main' into 1.21.1-TMs
# Conflicts:
#	common/src/main/kotlin/com/cobblemon/mod/common/client/CobblemonClient.kt
#	common/src/main/resources/data/minecraft/tags/block/mineable/pickaxe.json
2026-01-26 10:21:42 -08:00
Instrafe 6d69b91243 Shrank Blitzle, it was too big for its own good 2026-01-26 11:54:22 -05:00
Polymeta a12aee34d9 Merge branch 'main' into implement_pokemon 2026-01-26 16:40:27 +00:00
Sterrezo 7bcf47fc35 Corrected Darumaka's cry sound keyframe 2026-01-25 13:01:08 +01: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
Paul 0752ab3cac Fixed woopsies in changelog 2026-01-22 22:23:01 +10: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
Guilherme Pereira 17cab186d9 Merge branch '1.21.1-TMs' of gitlab.com:cable-mc/cobblemon into 1.21.1-TMs 2026-01-14 16:09:42 -03:00
Guilherme Pereira e00136052d add python tm scraping script and add support for tags in tm recipes 2026-01-14 16:09:18 -03:00
Plastered_Crab b23237ca9a Merge branch 'main' into 1.21.1-TMs 2026-01-14 10:32:32 -08: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
plastered_crab 36456bfb0d Merge branch 'main' into 1.21.1-TMs 2025-12-28 14:35:43 -08:00
plastered_crab d9661c356f Merge remote-tracking branch 'origin/1.21.1-TMs' into 1.21.1-TMs 2025-12-28 14:31:38 -08:00
Test a66fad69cf idle screen 2025-12-23 22:26:37 -05:00
Test 95488ac54b Merge branch '1.21.1-TMs' of https://gitlab.com/cable-mc/cobblemon into 1.21.1-TMs 2025-12-23 16:19:12 -05:00
Test 19f2b71273 idle screen 2025-12-23 16:18:43 -05:00
Guilherme Pereira ba6e136a0b add fabric data generator, move gem blocks loot tables from code to jsons 2025-12-23 14:55:10 -03:00
Guilherme Pereira 28ac437987 gem blocks shenanigans 2025-12-22 16:42:27 -03:00
Plastered_Crab a4935f19bb TMs with the "none" obtainment method are shown in the TM Machine by default 2025-12-21 18:17:26 -08:00
plastered_crab c3e470f1de Merge branch 'main' into 1.21.1-TMs 2025-12-20 20:41:59 -08:00
Plastered_Crab 4139337f85 Remove Batch TM button, but make it so Batching TMs works via redstone signal now. 2025-12-19 09:09:47 -08:00
Plastered_Crab 25bc2dea93 Merge remote-tracking branch 'origin/1.21.1-TMs' into 1.21.1-TMs 2025-12-18 15:23:19 -08:00
Plastered_Crab 9dc3884ea6 Modify and enhance TM Machine Automation batch processes 2025-12-18 15:22:57 -08:00
Guilherme Pereira 89d95c6ab8 Merge branch '1.21.1-TMs' of gitlab.com:cable-mc/cobblemon into 1.21.1-TMs 2025-12-18 18:30:30 -03:00
Guilherme Pereira 7b70aa5a1e add /technicalmachine check command 2025-12-18 18:30:18 -03:00
Plastered_Crab 8191b4d9b6 fix Thunder TM recipe 2025-12-18 09:21:02 -08:00
Guilherme Pereira 84534fd041 add /technicalmachine command 2025-12-17 18:06:03 -03:00
Guilherme Pereira e6e1446eb1 merge all tm toasts into one if a player learn more than one tm at once 2025-12-16 21:01:47 -03:00
plastered_crab 39fbadc4fb Can Silk Touch Type Gem clusters of all stages now 2025-12-15 15:28:12 -08:00
plastered_crab 3c2a9c1dfd Overhaul of the Type Gem Core block growth system (hopefully more performant too) 2025-12-15 15:05:11 -08:00
plastered_crab 921fcbe477 Fix TM Machine and Blank TM recipe unlocks 2025-12-15 13:58:37 -08:00
plastered_crab c90b6c86ab Type Gems and Type Gem Clusters can be placed on any surface for decoration 2025-12-15 13:00:48 -08:00
plastered_crab 3ecf25502b Remove old recipes and add new recipes for Type gem things 2025-12-15 12:54:09 -08:00
plastered_crab b808112e17 Type Gem clusters can be silk touched to decorate with their various stages 2025-12-15 12:29:06 -08:00
plastered_crab 1b2d31db03 Pistons break the Type Gem Clusters to give the right amount of Type Gems 2025-12-15 12:09:07 -08:00
plastered_crab c9f8445d14 Fortune enchantment affects drops from Type Gem cluster blocks and type gem blocks 2025-12-15 12:03:35 -08:00
plastered_crab acd879ebef Alter Type Gem Clusters to drop new amount of type gems based on growth stage 2025-12-15 11:34:25 -08:00
plastered_crab f6889fd8ea Change TypeGemCoreBlock max connected gems before going dormant to 7 2025-12-15 11:25:08 -08:00
plastered_crab 21ccbef6c9 Fix TM Machine and Blank TM recipe to unlock after getting an Amethyst Shard 2025-12-15 11:16:11 -08:00
plastered_crab 9349e6a668 Fix TM Machine recipe 2025-12-15 11:12:27 -08:00
plastered_crab 28a7fe6a04 Marge Main to TM Branch 2025-12-15 11:07:44 -08:00
plastered_crab 18e1ed79ef Merge branch 'main' into 1.21.1-TMs
# Conflicts:
#	common/src/main/kotlin/com/cobblemon/mod/common/CobblemonNetwork.kt
#	common/src/main/resources/assets/cobblemon/lang/en_us.json
2025-12-15 10:56:51 -08: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
Paul 87a36020f6 Added a bunch of alpha pokemon functionality, bunch temp 2025-12-12 16:13:03 +10:00
Paul 22733e7117 Added more advanced moveset and party construction for NPCs 2025-12-08 19:31:48 +10:00
plastered_crab 117afcea32 Merge remote-tracking branch 'origin/1.21.1-TMs' into 1.21.1-TMs
# Conflicts:
#	common/src/main/kotlin/com/cobblemon/mod/common/CobblemonBlocks.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/CobblemonNetwork.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/api/types/ElementalTypes.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/data/CobblemonDataProvider.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/pokemon/evolution/controller/ClientEvolutionController.kt
2025-11-21 19:45:56 -08:00
plastered_crab 3f89750ee5 Merge main to TM Branch 2025-11-21 19:43:35 -08:00
plastered_crab d88be7ae05 Merge branch 'main' into 1.21.1-TMs
# Conflicts:
#	common/src/main/kotlin/com/cobblemon/mod/common/CobblemonBlocks.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/CobblemonItemComponents.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/CobblemonNetwork.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/api/types/ElementalTypes.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/data/CobblemonDataProvider.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/item/group/CobblemonItemGroups.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/world/feature/CobblemonPlacedFeatures.kt
2025-11-21 19:32:38 -08:00
Nadja Reitzenstein 24245331db Merge branch 'main' into 1.21.1-TMs
* main: (322 commits)
  changes to /npcdelete uuid prameter and console support
  Translated using Weblate (Japanese)
  Translated using Weblate (Japanese)
  Enforce minimum depth requirement for swim wander, fix mistake in omnipathnav
  Remember the last camera type used for a mount type and switch to it if the config is enabled
  Wait that wasn't meant to still be in there
  API and config and controller options for infinite stamina
  rm unused function
  fix stat color
  Removed an unused sound from sounds.json
  Migrated all the other controllers to support the global config
  Migrate global ride controller settings to use a different solution
  Added global controller settings for riding, moved jet over to it
  add pokémon fullness to pokémon properties
  fix poke puff tooltip and mild multiplier #1711 #1710
  Add offset setting for determining surface level
  Change sprint modifier expression, adjust acceleration formula
  Change how reloadability is checked for /reload, maybe this will fix server stuff
  Persist stamina between dismount and mount
  rm unused imports
  ...
2025-10-01 12:15:20 +02:00
Nadja Reitzenstein d6d10d33e3 Fix file licenses 2025-09-19 18:11:16 +02:00
Nadja Reitzenstein 4d88c9b383 Fix small typos 2025-09-19 17:07:26 +02:00
Nadja Reitzenstein a3f597c589 Minimise the Gitlab-shown diff by undoing formatting changes
This commit will *absolutely* be reverted before we merge, but it helps with reviewing because gitlab doesn't filter whitespaces changes well.
2025-09-19 17:07:26 +02:00
Nadja Reitzenstein 2a3d88c12e Remove stray println 2025-09-19 16:33:44 +02:00
dhi_holoandNadja Reitzenstein 9561f47337 Small Asset Updates
(cherry picked from commit 4bfca0da43)
2025-09-19 16:28:04 +02:00
Nadja Reitzenstein f02c92db22 Merge branch 'main' into 1.21.1-TMs
* main: (62 commits)
  tweak default stat ranges for some flying behaviours
  Added math.sign and math.copy_sigh molang dep update
  Grain Improvements
  update fabric-permissions-api to 0.3.1
  Behaviour tweaks
  Update mochis.json
  IV Drip
  Ride settings editor
  Fix in air dismount
  Fix riding waterwalk
  swap out textures
  Remove unnecessary check on resource
  Changelog [skip-ci]
  Forgor camera offsets for extra seats
  Bronzong ready to scrape.
  Fix double lid on campfire pot open sprites
  Rename CookingPotColor to CampfirePotColor
  Add color property in CampfirePotItem
  Sync cooking pot button color with open / closed state
  Add cooking pot open sprites
  ...
2025-09-19 15:44:49 +02:00
Nadja Reitzenstein 181ef5d50e No-Fixes and formatting 2025-09-19 14:26:31 +02:00
plastered_crab 870397ebb9 Merge branch 'main' into 1.21.1-TMs
# Conflicts:
#	common/src/main/resources/assets/cobblemon/lang/en_us.json
2025-09-08 21:30:19 -07:00
plastered_crab 0ed413070d Merge branch 'main' into 1.21.1-TMs 2025-08-25 21:58:27 -07:00
plastered_crab f66f5ffdf9 Get TMs up to date with main 2025-08-16 20:01:12 -07:00
plastered_crab ca280a7b3e Merge branch 'main' into 1.21.1-TMs
# Conflicts:
#	common/src/main/kotlin/com/cobblemon/mod/common/CobblemonBlocks.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/client/CobblemonClient.kt
2025-08-16 19:45:45 -07:00
plastered_crab 85284bff9d Get TMs up to date with main 2025-08-10 17:01:53 -07:00
plastered_crab fa4d33f725 Merge branch 'main' into 1.21.1-TMs
# Conflicts:
#	common/src/main/kotlin/com/cobblemon/mod/common/api/types/ElementalTypes.kt
2025-08-10 16:55:57 -07:00
plastered_crab 4ce42cdf6d edits to ElementalType.kt 2025-07-29 17:12:14 -07:00
plastered_crab 1b8562ead8 edits to ElementalType.kt 2025-07-29 16:09:25 -07:00
plastered_crab b9d9b906fb Merge branch 'main' into 1.21.1-TMs
# Conflicts:
#	common/src/main/kotlin/com/cobblemon/mod/common/api/pokemon/moves/Learnset.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/api/types/ElementalType.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/client/CobblemonClient.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/item/group/CobblemonItemGroups.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/world/feature/CobblemonPlacedFeatures.kt
2025-07-29 08:36:31 -07:00
plastered_crab e9d079a223 Chance to add type gem clusters to works genned Type Gem growths underground 2025-07-09 23:03:13 -07:00
plastered_crab e2e42ee91c Chance to add type gem clusters to works genned Type Gem growths underground 2025-07-09 13:16:56 -07:00
plastered_crab 4b0208201b Chance to add type gem clusters to works genned Type Gem growths underground 2025-07-09 07:19:53 -07:00
plastered_crab bec3f97733 Fix some classes 2025-07-09 06:40:24 -07:00
plastered_crab 16cfe37dac Merge branch 'refs/heads/main' into 1.21.1-TMs
# Conflicts:
#	common/src/main/kotlin/com/cobblemon/mod/common/CobblemonNetwork.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/client/CobblemonClient.kt
#	common/src/main/resources/assets/cobblemon/lang/en_us.json
2025-07-09 05:25:07 -07:00
plastered_crab 7381da863c Merge branch 'refs/heads/main' into 1.21.1-TMs 2025-06-29 20:55:28 -07:00
Test b0902825fa teach through drag-dropping in TMM 2025-06-27 01:34:45 -04:00
Test 31c489cba0 Merge branch 'main' of https://gitlab.com/cable-mc/cobblemon into 1.21.1-TMs 2025-06-25 23:30:29 -04:00
Test 6a2f21d75a merge 2025-06-25 23:30:12 -04:00
Test e2c42a57c7 Merge branch '1.21.1-TMs' of https://gitlab.com/cable-mc/cobblemon into 1.21.1-TMs
# Conflicts:
#	common/src/main/kotlin/com/cobblemon/mod/common/CobblemonBlocks.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/client/CobblemonClient.kt
2025-06-25 22:48:43 -04:00
Test 8592b53216 tmm refactor 2025-06-25 22:39:42 -04:00
plastered_crab 49dcf0049f Merge branch 'refs/heads/main' into 1.21.1-TMs
# Conflicts:
#	common/src/main/kotlin/com/cobblemon/mod/common/CobblemonBlocks.kt
2025-06-20 06:08:06 -07:00
plastered_crab 076bee923f Merge branch 'refs/heads/main' into 1.21.1-TMs
# Conflicts:
#	common/src/main/kotlin/com/cobblemon/mod/common/CobblemonBlocks.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/CobblemonItemComponents.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/CobblemonMenuType.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/client/CobblemonClient.kt
2025-06-10 18:27:00 -07:00
Plastered_Crab aacdb33827 Nevemind put it here instead 2025-05-30 10:17:02 -07:00
Plastered_Crab 53e9ece930 Player's TM datastore gets synced when their pokemon learn a move 2025-05-30 10:13:08 -07:00
plastered_crab 87f08d9bab 75% saturation on the Type colors 2025-05-29 23:43:01 -07:00
plastered_crab a50a6326af Merge remote-tracking branch 'origin/1.21.1-TMs' into 1.21.1-TMs 2025-05-29 22:32:12 -07:00
plastered_crab 3c0eec833e Type Color and TM asset change 2025-05-29 22:31:27 -07:00
Plastered_Crab 5b0cfdffcb Merge branch 'main' into 1.21.1-TMs 2025-05-29 15:11:22 -07:00
plastered_crab d788e0402e Merge remote-tracking branch 'origin/1.21.1-TMs' into 1.21.1-TMs 2025-05-28 19:04:22 -07:00
Plastered_Crab a347dc5e2a Merge branch 'main' into 1.21.1-TMs 2025-05-28 10:52:13 -07:00
plastered_crab b2fe158a7b Merge branch 'refs/heads/main' into 1.21.1-TMs 2025-05-28 09:33:57 -07:00
plastered_crab faab7e8df0 Change type gem block smelting recipes 2025-05-27 23:22:37 -07:00
plastered_crab 9070e198f1 Type gem clusters are no longer items and can't be placed. 2025-05-27 23:05:14 -07:00
plastered_crab 45b2a0db4d alter type gem clusters to drop type gems when broken 2025-05-27 21:51:16 -07:00
plastered_crab 65d39050ea Merge branch 'refs/heads/main' into 1.21.1-TMs
# Conflicts:
#	common/src/main/kotlin/com/cobblemon/mod/common/CobblemonItemComponents.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/CobblemonNetwork.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/client/CobblemonClient.kt
#	common/src/main/resources/assets/cobblemon/lang/en_us.json
#	common/src/main/resources/assets/cobblemon/sounds.json
2025-05-27 19:57:54 -07:00
plastered_crab 5da16df5ae Changes to Type Gem Cluster logic 2025-05-20 23:41:42 -07:00
plastered_crab 24fc4b05ab Toast appears now when learning a new TM + Licenses 2025-05-20 22:27:44 -07:00
Plastered_Crab 173902feb1 Starting code to display Toasts when unlocking new TMs 2025-05-20 19:14:41 -07:00
Plastered_Crab fd5f08fe84 Call syncTMsFromPokemon from add method in PokemonStore class. 2025-05-20 18:46:56 -07:00
Plastered_Crab d430ad6ca1 Move the syncTMsFromPokemon method to TMMoveManager 2025-05-20 18:21:05 -07:00
Plastered_Crab 1309c18292 Player unlocks TMs by catching pokemon with those moves and TM Machine lists only player learned moves 2025-05-20 18:08:42 -07:00
plastered_crab b6deebac97 Preparing for TM Move Data store 2025-05-19 15:16:01 -07:00
Plastered_Crab 83711f2dcb Merge branch '1.21.1-TMs-(dont-be-shelvish)' into 1.21.1-TMs
# Conflicts:
#	common/src/main/kotlin/com/cobblemon/mod/common/client/CobblemonClient.kt
2025-04-24 14:11:35 -07:00
Plastered_Crab 18e1a767af Use new TM Shelf Block and starting to get it working 2025-04-24 14:07:38 -07:00
Polymeta 6ae3efb461 fix merge and tidy up
Signed-off-by: Polymeta <40173118+Polymeta@users.noreply.github.com>
2025-04-24 19:29:38 +01:00
Polymeta 84e1934134 Merge branch 'refs/heads/main' into 1.21.1-TMs
# Conflicts:
#	common/src/main/kotlin/com/cobblemon/mod/common/CobblemonBlockEntities.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/CobblemonBlocks.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/CobblemonItemComponents.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/client/CobblemonClient.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/data/CobblemonDataProvider.kt
#	common/src/main/resources/assets/cobblemon/lang/en_us.json
#	common/src/main/resources/cobblemon-common.accesswidener
#	fabric/src/main/kotlin/com/cobblemon/mod/fabric/CobblemonFabric.kt
2025-04-24 16:58:20 +01:00
Plastered_Crab 9aed9342ee Fix atrocious formatting 2025-04-23 13:33:54 -07:00
Plastered_Crab e4d0bf39ca Added in WIP tooltips for TMs 2025-04-23 13:26:32 -07:00
plastered_crab 847fa6842e Test Bookcase can hold TMs, Upgrade, Dubious Disc, Pokedex, etc (very WIP) 2025-04-22 13:51:15 -07:00
plastered_crab 08aa4f29bd Dubious Disc and Upgrade able to be placed in the Bookshelf too 2025-04-22 10:59:35 -07:00
plastered_crab 539218381b Corrected face being mirrored 2025-04-22 09:21:45 -07:00
plastered_crab 9dff39b4d7 Shelf is no longer upside down lmao 2025-04-22 08:42:24 -07:00
plastered_crab 1e578e94e5 Shelf renders without redish color 2025-04-22 08:32:35 -07:00
plastered_crab ec35c9b9bb shelf face rendered (upside down...) 2025-04-22 07:55:36 -07:00
plastered_crab 0deaeaeb7d fit the TM case textures onto shelves better 2025-04-22 07:22:49 -07:00
plastered_crab ec3d9e1a56 Test code for placing TMs in Chiseled Bookshelves 2025-04-21 17:11:10 -07:00
Polymeta 814f84ae42 licenses
Signed-off-by: Polymeta <40173118+Polymeta@users.noreply.github.com>
2025-04-18 01:11:33 +01:00
Polymeta 904be475ef Merge branch 'refs/heads/main' into 1.21.1-TMs
# Conflicts:
#	common/src/main/kotlin/com/cobblemon/mod/common/CobblemonNetwork.kt
#	common/src/main/resources/cobblemon-common.accesswidener
2025-04-18 00:44:25 +01:00
Plastered_Crab 5edecbe81b Add crafting recipes / loot tables type gems, fix collision boxes, break rules, etc 2025-04-17 15:29:42 -07:00
Plastered_Crab f357033404 Fixed 100+ recipes, fixed CraftTMPacketHandler, adjusted GUI for TM Machine, and fixed names for some moves 2025-04-17 12:27:54 -07:00
Plastered_Crab 4800ae6649 Tweaking of some TM recipes 2025-04-17 09:29:21 -07:00
plastered_crab 60b0690c1e Add remaining 10 TM recipes. now all are present for testing 2025-04-17 00:40:00 -07:00
plastered_crab 82e31dd766 Add 330+ TM recipes for testing >:) 2025-04-17 00:00:34 -07:00
Guilherme Pereira 130e767e75 force type gems to grow halfway upon world generation 2025-03-28 05:02:33 -03:00
Guilherme Pereira b1a1d509ec make type gems grow naturally 2025-03-27 19:37:46 -03:00
Plastered_Crab 0698cf495e Type Gem Clusters fill in empty space when they grow grow stunted buds when hitting max capactity 2025-03-26 16:49:00 -07:00
Plastered_Crab 6047660405 Type Gem clusters grow in the same direction as their previous state more often and also fill in gaps with clusters 2025-03-26 14:53:05 -07:00
Plastered_Crab aaf3495f83 New transitional stages for the type gem clusters and fixes for rendering issues 2025-03-26 13:09:59 -07:00
Plastered_Crab ae6529c9fd Type gem clusters grow their respective type gem blocks when placed on the core 2025-03-25 17:05:03 -07:00
plastered_crab 45a96b2a42 Prepare for new Type Gem generation for each type of gem 2025-03-19 16:07:58 -07:00
Apion 4212903c67 Merge branch 'fix-tm-automation' into '1.21.1-TMs'
General Fixes and Implementation of the TM Machine for 1.21.1

See merge request cable-mc/cobblemon!1542
2025-03-01 08:52:01 +00:00
BuildTools be47dbcede Some Requested Changes 2025-03-01 06:05:38 +02:00
Apion 9556c57c69 Fix broken accesswideners 2025-02-23 21:33:54 -08:00
BuildTools f72b65bfac Fix for TMM GUI elements being offset in wrong postion after a previus TMM GUI Fix 2025-02-22 13:13:28 +02:00
BuildTools 6121700c9b Fixed disk in TMM rendering in wrong location after fixing TMM rendering backwards 2025-02-22 12:20:52 +02:00
BuildTools 91c968e743 A better fix for a previos TMM GUI fix 2025-02-22 12:05:30 +02:00
BuildTools 8fed6f4823 Fixed TMM rendering backwards and now the TMM will eject disc from its facing direction proper 2025-02-22 10:31:43 +02:00
BuildTools 34e4b39d75 Added Properties to TMM regarding breaking the block and loot table (based of PC) 2025-02-22 09:52:58 +02:00
BuildTools a21c70ce46 Resizing TMM GUI no longer breaks the GUI Buttons 2025-02-21 23:00:52 +02:00
BuildTools 8865a71f4c TMM will now output signal when ready to craft Blank TM and will drop Filter TM on break 2025-02-21 20:32:52 +02:00
BuildTools 142cadc187 TMM can now craft blank TMs if no TM is set in the filter, as well as allow taking out the filter TM 2025-02-21 19:43:36 +02:00
BuildTools 66f4c2531d Fixed TMM GUI quick move feature to properly work as well as what is considered to be outside the GUI 2025-02-19 20:16:00 +02:00
BuildTools 3f8ddd5f7d TM Machine now turns on/off and plays sound then opened/closed 2025-02-16 22:09:07 +02:00
BuildTools c076e14cbd Made Comparator read TM Machine and it provides power if the TM Machine has the materials to autocraft 2025-02-15 23:00:32 +02:00
BuildTools d724eb068b Fixed missing tooltip render call causing tooltips over items not showing in TM Machine 2025-02-15 13:10:15 +02:00
BuildTools d3ac263e29 Made the item form of TM Machine render properly in usual cases 2025-02-15 12:32:35 +02:00
BuildTools a6b7fe1f17 TM can now finally autocraft TMs based on filtered TM by receiving redstone signal 2025-02-15 09:50:28 +02:00
BuildTools ec714ccb84 Fixed Filtering for Hopper input not working 2025-02-12 19:53:54 +02:00
BuildTools ab0a129ba1 TM Machine GUI and Inventory synced and working properly 2025-02-12 18:45:32 +02:00
Guilherme Pereira a3f272b2aa Merge branch 'main' into 1.21.1-TMs 2025-02-06 03:48:28 -03:00
Guilherme Pereira 77d91ed979 make last type gems growing from core not fully grow into blocks 2025-01-29 03:56:35 -03:00
Guilherme Pereira 9907ba17c1 update licenses 2025-01-27 06:28:51 -03:00
Guilherme Pereira a6f0e19a44 type gem core now generates more gems 2025-01-27 06:27:27 -03:00
Guilherme Pereira 7ee064b04d make type gem bud grow into a block in its final stage 2025-01-27 05:29:14 -03:00
Guilherme Pereira f2e4c735f7 add type gems 2025-01-27 05:04:04 -03:00
Guilherme Pereira 5345bd321f update licenses 2025-01-21 19:08:49 -03:00
Guilherme Pereira eab8d0063b fix tms item sprite colors 2025-01-21 19:08:00 -03:00
Guilherme Pereira 6877977234 tm branch ressurect attempt 2025-01-17 23:23:01 -03:00
plastered_crab 60cb81362e Added some small langs 2025-01-09 07:46:53 -08:00
plastered_crab 088acb8e86 Added TMs, created TechnicalMachineRegistrySyncPacket.kt, TM json files are loading, TM machine GUI working better, altered obtain methods, and more 2025-01-08 20:04:24 -08:00
plastered_crab 77f59f06cb add tm_disk.geo file 2025-01-08 10:49:41 -08:00
plastered_crab a0882c6105 TM branch lives to see another day! (Still needs some issues fixed) 2025-01-08 10:49:21 -08:00
plastered_crab d50eb52172 Merge branch 'refs/heads/main' into 1.21.1-TMs 2025-01-07 19:49:30 -08:00
Plastered_Crab 5e5cadd314 Some more changes to unported files 2024-12-26 16:34:29 -08:00
Plastered_Crab 75b06f82f0 Oops forgor two files (they were not staged oops again) 2024-12-26 16:21:04 -08:00
Plastered_Crab 2ab050aa60 Oops forgor two files 2024-12-26 16:20:25 -08:00
Plastered_Crab 6d2f645e4a More work to port over TM stuff to 1.21.1 2024-12-26 16:10:04 -08:00
Plastered_Crab 9f937e29f2 Merge branch 'main' into 1.21.1-TMs 2024-12-26 13:54:27 -08:00
Plastered_Crab abc61a96c8 Merge branch 'main' into 1.21.1-TMs 2024-12-17 10:21:05 -08:00
Plastered_Crab b1d10822d4 Merge branch 'main' into 1.21.1-TMs 2024-12-12 08:35:22 -08:00
Plastered_Crab 09d984456d Start of new branch for 1.21.1 version of TM Machine code (this was painful) 2024-11-26 15:04:32 -08:00
8892 changed files with 620309 additions and 124542 deletions
+3
View File
@@ -24,6 +24,7 @@ eclipse
run
runClient
runServer
utilityscripts/implementation/*.txt
# Files from Forge MDK
forge*changelog.txt
@@ -36,9 +37,11 @@ common/src/main/resources/assets/cobblemon/showdown
# Generated files
*/generated/resources/*
/fabric/src/generated/resources/cobblemon-common.accesswidener
/fabric/src/main/generated/*
/.ignored/
common/.fabric
.kotlin/
# MacOS
.DS_Store
/common/config/*
+6 -2
View File
@@ -16,6 +16,7 @@ check_assets_cache:
stage: preprocessing
script:
- echo "Checking if cached hash matches current hash"
- yum install -y findutils
# Calculate the current hash
- find common/src/main/resources/assets common/src/main/resources/data -type f -exec sha256sum {} + | sort -k 2 | sha256sum > current_hash.txt
@@ -71,8 +72,8 @@ setup_packsquash:
- echo "Installing wget & unzip"
- yum install -y wget unzip
- echo "Downloading PackSquash"
- wget https://github.com/ComunidadAylas/PackSquash/releases/download/v0.4.0/PackSquash.CLI.executable.x86_64-unknown-linux-musl.zip
- unzip PackSquash.CLI.executable.x86_64-unknown-linux-musl.zip -d ./packsquash_bin
- wget https://github.com/ComunidadAylas/PackSquash/releases/download/v0.4.1/packsquash-x86_64-unknown-linux-musl.zip
- unzip packsquash-x86_64-unknown-linux-musl.zip -d ./packsquash_bin
- echo "Creating PackSquash options.toml"
- |
cat <<EOF > ./options.toml
@@ -148,6 +149,7 @@ build:
dependencies:
- replace_resources
script:
- yum install -y findutils
- export GRADLE_OPTS="-Xmx4G -Xms4G"
- chmod +x ./gradlew
- ./gradlew build
@@ -163,6 +165,7 @@ publish:
rules:
- if: '$CI_PROJECT_PATH == "cable-mc/cobblemon" && $CI_COMMIT_BRANCH == "main"'
script:
- yum install -y findutils
- export GRADLE_OPTS="-Xmx4G -Xms4G"
- chmod +x ./gradlew
- ./gradlew publish
@@ -176,6 +179,7 @@ deploy_artifacts:
dependencies:
- build
script:
- yum install -y findutils
- echo "Collecting artifacts..."
- find neoforge/build/libs/ -type f -name "*.jar" | grep -vE "dev-shadow|sources|javadoc" | xargs -I {} mv {} ./
- find fabric/build/libs/ -type f -name "*.jar" | grep -vE "dev-shadow|sources|javadoc" | xargs -I {} mv {} ./
+479 -21
View File
@@ -1,60 +1,518 @@
# Changelog
## [1.7.4 (MONTH Xth, 2026)](#1-7-4)
## [1.8.0 (MONTH Xth, 2026)](#1-8-0)
### Additions
- Added config options to award experience to fainted Pokémon for opponents they helped defeat (`awardExperienceToFaintedPokemon`) and to still award experience for defeated enemies even after battle loss/forfeit (`awardExperienceOnBattleLoss`)
- 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 a 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
- Added a way to obtain Porygon by inserting the Upgrade or Dubious Disc into a data monitor
- Added a new `cobblemon:structure`, which is a feature without any restrictions allowing the Builders to place certain structures in much more specific manner.
- Added Configs for Infinite Use TMs and Unlocking all TMs
- Added Type Gem blocks
- Added Type Gem Clusters
- Added TMs
- Added TM Machine
- Added Deepslate Core Block
- Added /givetm Command
- Added advancement triggers for learning TMs: `cobblemon:has_learn_specific_tm` (per-TM), `cobblemon:has_learn_all_tm` (all TMs learned), and `cobblemon:tms_learned` (count-based), backed by a new `totalTMLearnedCount` on player advancement data.
- Added `cobblemon:catch_alpha_pokemon` advancement trigger and `totalAlphaCaptureCount` tracking for capturing Alpha Pokémon.
- Added Move Dex to Pokédex
- Added the Habitat Block, a spawner block for servers and adventure maps that controls spawning in an area.
- Added Disk Rack for storing disks and being an audio sequencer for Noteblocks
- Added intrinsic scaling to all Pokémon (+-5%). Some rendering cases, such as shoulder mounting, revert to 1.0 scaling to preserve animation accuracy.
- Added scaling to "baby" Pokémon (smaller (-20%) at level 1 → normally sized at level 10)
- Added conditional seats for riding. Seats can be gated by molang such as "is_alpha".
- Added Alpha Pokémon
- Added alpha scaling (alphas are larger than their normal counterparts)
- Alphas will always lead herds and will spawn in herds
- Alphas spawn with two random TM moves from their learnset
- Alpha Pokémon will always defend themselves from players that attack them
- Added alpha level matching and stat boost (based on level)
- Added pitch-down and reverb to alpha cries
- Added alpha Pokémon bait effect
- Added alpha eye rendering including eye overlay, bloom, eye trail, and particles.
- Added cobweb block slowness immunity for spider Pokémon
- Added 49 new habitat structures. 34 as typical Minecraft structures and 15 as structures that get placed as biome features to allow for more natural placement in generation. Structures placed as biome features will not be able to be located with the `/locate structure` command.
- Vanilla village house template pools have been adjusted to account for the new abandoned village structure habitat. Weights have changed within the JSON file for every piece to ensure too many habitats don't generate in a single village.
- Added 10 new ruin structures.
- rooted_arch_ruins & crumbling_arch_ruins have been transferred over to biome features, allowing for better placement in generation.
- All ruin structures that did not generate with a gimmighoul/gilded chest before will now generate with one.
- All ruin structures gilded chest loot tables have been updated to include a guaranteed TM not learned naturally by any Pokémon through their level-up moveset. Each ruin gets its own specific TM, so you can now go hunting ruins to complete your move dex!
- All fossil structures have been transferred over to biome features, allowing for better placement in generation.
- The prehistoric_underwater_fissure & prehistoric_submerged_impact fossil structures now use the biome tag `#cobblemon:is_temperate_ocean`.
- Gimmighoul towers now generate at ground level rather than sinking one block into the ground.
- A new shipwreck cove structure called the "magma_shipwreck_cove" has been added.
- Shipwreck coves now generate slightly more frequently.
- Added equipment loot tables for shipwreck cove enemies.
- Maps from abandoned fishing boats leading to shipwreck coves now will skip explored chunks, allowing the player to find more shipwreck coves easier.
- The lush shipwreck cove's phantom mob spawner has been replaced with breezes.
- The lush shipwreck cove structure itself has been slightly cleaned up to be less noisy with the blocks it is built out of.
- All shipwreck coves' spawners have been adjusted to give compatible mobs enchanted iron or diamond armour and weapons while in its ominous state. The armour given to the mobs will also use the automaton trim. We upped the difficulty because it was too easy now that your Pokémon can fight for you.
- One TM of the elemental hyper beams has been added as guaranteed loot to the main treasure chest in every shipwreck cove. (Magma cove gets blast burn, lush cove gets frenzy plant, and submerged cove gets hydro cannon)
- Added 7 new advancements
- Pressing the inventory key now closes the Pokémon interact wheel GUI
- Pokémon cries now play when clicking Pokémon in the summary screen.
- Pressing the Summary key while either the starter selection or summary screen are open now closes those screens
- Ice type Pokémon are now immune to Packed Snow
- Held item visibility can now be controlled by the held_item_visible command argument.
### New rideable Pokémon
- Crobat
- Skarmory
- Milotic
- Archeops
- Goodra
- Goodra (Hisuian Form)
- Drampa
- Duraludon
- Archaludon
### Pokémon Added
#### Generation 3
- Wurmple
- Silcoon
- Beautifly
- Cascoon
- Dustox
- Skitty
- Delcatty
- Seviper
- Zangoose
#### Generation 4
- Cherubi
- Cherrim
- Stunky
- Skuntank
#### Generation 5
- Audino
- Pawniard
- Bisharp
#### Generation 6
- Pancham (+ Cosmetic with Black Glasses)
- Pangoro (+ Cosmetic with Black Glasses)
#### Generation 7
- Rockruff
- Lycanroc
#### Generation 8
- Rolycoly
- Carkol
- Coalossal
- Runerigus
- Snom
- Frosmoth
- Indeedee
- Duraludon
- Applin
- Flapple
- Appletun
#### Generation 9
- Nymble
- Lokix
- Kingambit
- Dipplin
- Archaludon
- Hydrapple
#### Regional Forms
- Sandshrew (Alolan Form)
- Sandslash (Alolan Form)
- Yamask (Galarian Form)
- Avalugg (Hisuian Form)
### Model updates for the following Pokémon
- Sandshrew
- Sandslash
- Nidoking
- Zubat
- Golbat
- Crobat
- Ditto
- Porygon
- Porygon2
- Porygon-Z
- Skarmory
- Smoochum
- Jynx
- Popplio
- Brionne
- Primarina
- Fletchling
- Fletchinder
- Talonflame
- Sableye
- Mawile
- Goomy
- Sliggoo
- Goodra
- Nacli
- Naclstack
- Garganacl
- Bidoof
- Cranidos
- Chatot
- Yamask
- Cofagrigus
- Tyranitar
- Turtonator
- Golett
- Corsola
- Arbok (New Patterns: Angry, Cartoon, Clown, Comedic, Crow, Grin, Ink, Modern, Rain, Scribble, Silence, Sloth, Suspicious, Will)
- ... and Substitute
#### Model changes to the regional bias resource pack:
- Added Mime Jr. (Galar Bias)
- Added Bergmite (Hisui Bias)
- Changed models for every existing regional bias
### Animation updates for the following Pokémon
- Kakuna
- Grimer
- Nidoran♀ (+ New shoulder mount)
- Nidorina
- Nidoran♂ (+ New shoulder mount)
- Sandshrew
- Diglett
- Dugtrio
- Graveler
- Happiny
- Chansey
- Blissey
- Poliwhirl
- Poliwrath
- Zubat
- Vulpix
- Drowzee
- Hypno
- Noctowl
- Skarmory
- Skitty
- Flygon
- Shellos
- Riolu
- Lucario
- Purrloin
- Liepard
- Joltik
- Galvantula
- Nidoking
- Fletchling
- Fletchinder
- Talonflame
- Archeops
- Drampa
- Sewaddle
- Swadloon
- Leavanny
- Goomy
- Sliggoo
- Goodra
- Shedinja
- Skwovet
- Greedent
- Bidoof
- Cranidos
- Chatot
- Yamask
- Cofagrigus
- Luvdisc
- Staryu
- Starmie
- Togetic
- Rellor
- Rabsca
- Yungoos
- Gumshoos
- Cottonee
- Whimsicott
- Corsola
#### Added sounds to the following moves
- Absorb
- Aurora Beam
- Double Team
- Draco Meteor
- Fire Punch
- Fire Spin
- Flame Charge
- Flame Wheel
- Giga Drain
- Ice Punch
- Leech Life
- Magical Leaf
- Mega Drain
- Minimize
- Poison Gas
- Rock Throw
- Scary Face
- Seed bomb
- Smokescreen
- String Shot
- Tail Whip
### Changes
- Stat increase and decrease particles have been changed, with the addition of alpha boost particles.
- Dragonite's mailbag cosmetic can now also be obtained with a chest in the cosmetic slot
- Adjusted Croagunk's walkspeed
- Adjusted Aerodactyl's walkspeed
- Sharp Beak can now be crafted
- Metal Alloy can now be crafted
- Ability Capsules can now be brewed
- Using an Ability Capsule will now return an Empty Bottle
- The following items can now be obtained by brushing the following Pokémon:
- Pink Wool - Wigglytuff
- White Wool - Swablu, Altaria
- Shed Shell - Ekans, Arbok, Dratini, Dragonair, Dunsparce, Treecko, Grovyle, Sceptile, Seviper, Scraggy, Scrafty, Helioptile, Heliolisk, Salandit, Salazzle, Sobble, Drizzile, Inteleon, Silicoblra, Sandaconda, Toxel, Toxtricity, Orthworm, Dudunsparce
- Phantom Membrane - Dreepy, Drakloak, Dragapult
- The following items can now be obtained by evolving the following Pokémon into any of their evolutions:
- Turtle Scute - Squirtle, Wartortle, Turtwig, Grotle, Tirtouga, Chewtle
- Shed Shell - Metapod, Kakuna, Ekans, Paras, Venonat, Krabby, Scyther, Kabuto, Dratini, Dragonair, Ledyba, Spinarak, Yanma, Pineco, Dunsparce, GLigar, Pupitar, Treecko, Grovyle, Silcoon, Cascoon, Surskit, Nincada, Trapinch, Vibrava, Corphish, Anorith, Bagon, Shelgon, Kricketot, Burmy, Combee, Skorupi, Swadloon, Whirlipede, Dwebble, Scraggy, Karrablast, Joltik, Larvesta, Spewpa, Clauncher, Helioptile, Charjabug, Crabrawler, Cutiefly, Dewpider, Salandit, Wimpod, Poipole, Sobble, Drizzile, Dottler, Silicobra, Toxel, Sizzlipede, Snom, Tarountula, Nymble, Rellor
- Saccharine Leaves now drop Tart, Sweet, or Syrupy Apples, depending on their honey coating stage, instead of vanilla Apples
- Fixed the height of the Tumblestone Bud items when held in hand, placed on head, viewed in a GUI, and placed in an Item Frame
- Refactored all advancements, removing several deemed unnecessary. Due to this refactor, all previously obtained advancements will be reset besides the root (for picking a starter Pokémon). We are sorry for the inconvience, but it makes the tab cleaner and simplifies future advancements.
- 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.
- Decrease the default pastured mon wander radius to 32.
- Factor in the weight of Pokémon 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)
- Changed the bait effects of the following items: (Vanilla) Sweet & Glow Berries, Golden & Enchanted Golden Apples (Cobblemon) Custap, Eggant, Hopo & Micle Berries, Sweet Hearts
- Wild Pokémon now reliably have at least one offensive move if they can have offensive moves at that level.
- Data Monitor can accept Disks (TMs, Music Disks, Upgrade, Dubious Disk, etc.) to change what's being displayed on the screen
- Rider positioning is now client-driven (Remove poseOffsets and offset per seat/pose) in favour of sending real-time passenger position.
- Cleaned up seat data. Removed all now unused fields from seats in all species files. Also made locator seat names explicit in the species files (however, this doesn't break the legacy format)
- Marks can now provide aspects.
- Added new shiny and Alpha chance configs
- Apricorns now make a new sound when harvested
- Lowered the volume of harvesting berries
- Added alternate versions of the basic PC Wallpapers based on the original design of Cobblemon's PC, before public release
- Improved compatibility with various mods
- Farmer's Delight's cutting board can now be used to strip Apricorn and Saccharine's logs, or salvage their planks from various blocks. It can also separate their boats from chests
- Farmer's Delight's cutting board can be used to get two white dye from Pep-Up Flowers and two magenta dye from Medicinal Leeks
- Farmer's Delight's cutting board can separate Tumblestone Blocks back into Tumblestones
- Farmer's Delight's cutting board can salvage Type Gems from their Gem Blocks
- Farmer's Delight's Onions, Tomatoes, and Cabbages can be used to cook Open-Faced Sandwiches. Nature's Spirit's Olives also can be used
- Farmer's Delight's cutting board can be used on Hearty Grains to obtain rice and straw, similarly to Farmer's Delight's Rice Panicles
- Farmer's Delight's Apple Pies and Apple Ciders can now be made using Applin Apples, alongside the Vanilla counterpart
- Amendments allows for cooking Leek and Potato Stew in a Cauldron
- Any mods that utilise Moonlight's Soft Fluid system can store Leek and Potato Stew, Medicinal Brew, Antidote, Awakening, Burn Heal, Ice Heal, Paralyze Heal, Full Heal, Potion, Super Potion, Hyper Potion, Max Potion, Full Restore, Ability Capsules, Moomoo Milk, and Berry Juice in liquid form (such as Suplementaries' Jar or Goblet, or Cauldrons while using Amendments)
- Supplementaries' Hourglass can now use Bright Powder, Quick Powder, Metal Powder, Heal Powder, Silver Powder, and Remedy
- Berry Trees are now compatible with the Planter properly
- Saccharine Way Signs (added by Supplementaries automagically) now use a premade texture to prevent odd visual issues
- Supplementaries' Jar can now store various Cobblemon cookies, candies, and similar items
- Some of Supplementaries' items have been added to the `#cobblemon:held/container_held_items` item tag, including sacks, safes, and lunch baskets
- Experience Nuggets can be used in place of Sculk for making the EXP Candies if using Create
- Rage Candy Bar has a Create Mixing recipe
- All Cobblemon ores can now be crushed in Create's Crushing Wheels
- All Gem and Tumblestone Clusters can be crushed for automatic, low return, gems
- Hearty Grains can be milled like Farmer's Delight Rice Panicles if both Farmer's Delight and Create are installed
- Big Roots and Revival Herbs can be milled to their respective powders
- Pep-Up Flowers, Medicinal Leeks, and all 70 berries can be milled in Create's Millstone for additional dye drops
- Auspicious Armour and Upgrades can be Haunted using Create's crafting systems
- Applin Apples can be used to make Honeyed Apples in Create
- Golden Apples can now be crafted using the Applin Apples
- Prismarine Crystals and Amethyst Shards can now be used to craft Pokedexes
- Updated Pokédex Screens item tag to support tagged variants of Redstone and Glowstone Dust
- Sounds for interacting with various Cobblemon blocks now play from the centre of the block, rather than the corner
- The `/pc` command no longer plays PC activation sounds
### Fixes
- Fixes https://gitlab.com/cable-mc/cobblemon/-/issues/1943
- Fix occasional crash on retrieving revived fossils
- Fixed Blitzle's base scale being `1` rather than the intended `0.8`
- Fixed Magnezone's emissive layer for the shiny having the wrong name, thus displaying wrongly
- Fixed Litleo not blinking
- Fixed Omanyte and Omastar incorrectly using water animations on land.
- Fixed Pokédex layout for genderless variations
- Fixed odd stacking behaviour with the poke_bait item.
- 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
- Fixed an issue where particle like beam can disappear when you don't see the beginning of the beam, or you look away
- Fixed Bedrock particle materials (alpha/opaque/blend/add) sharing one render batch, which caused incorrect culling on mixed batches; each material now batches and draws with its own blend and cull state, and the alpha material renders as a true cutout
- Fixed an occasional crash on retrieving revived fossils
- Fixed brushing not working on Neoforge
- Fixed braking not working for submarines (whoops).
- Fixed strafing not having the same friction as forward movement (funny whoops).
- Fixed submarine's surface-water animations not playing when supposed to.
- Fixed submarine camera freaking out when looking up or down on the surface.
- Fixed pastured mons despawning and running away.
- Fixed Apricorn trees crashing when other mods bonemeal it
- Fixed the issue that caused Hover Behaviour rides without a ground style to be rendered useless upon touching the ground on a server.
- Removed the "inAir" penalty for block destruction speed when on a hover mount.
- Fixed horizontal and vertical collisions with hover mounts so they no longer accumulate or retain momentum
- Fixed NeoForge brewing stand unexpectedly crashing users when shift clicking items within its menu
- Fixed NPCs switching Pokémon very often during battles
- Fixed Campfire pot causing crashes under certain circumstances
- Fixed Type Gems not being consumed upon use
- Fixed Ancient Pokeball's to their respective modifiers
- Fixed a Server warning when recalling Pokemon
- Fixed Ancient Pokéball's to their respective modifiers
- Fixed a Server warning when recalling Pokémon
- Fixed sliding particles incorrectly handling block collision
- Fixed Full Heal not curing status conditions in battle
- Fixed a rare issue with battles locking up when you are forced to switch, with the switch menu appearing instantly.
- Fixed the combined effects of Pledge moves having broken Showdown message handling and localisation
- 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.
- Resolved the niche issue where Structures would spawn in an incorrect location, creating very funky world gen.
- Fixed Galarian Ponyta missing its cry.
- Fixed various log warnings caused by redundant files and sound events.
- Traded Pokémon will now retain the original friendship level when traded back to its OT
- Clusters now display correctly on maps
- Fixed removing mulch from berry trees with a shovel not working.
- Fixed collecting honey from Saccharine Leaf blocks deleting Honey Bottles when the inventory was full
- Fixed Stripped Saccharine Wood recipe being missing
- Fixed CancelableSoundInstance causing lag by attempting to create sounds every tick when out of range of hearing
- Fixed Stat Reducing Aprijuice not being possible to apply on a max out Pokémon, and the possibility of going into negatives
- Fixed Exploit where you could take out the bait or drop your Pokérod with bait to avoid consuming bait, now the bobber will just disappear if you do so
- Fixed Apricorn and Saccharine boats incorrectly using chest boat models
- Fixed wild and trainer battle AI refusing to select moves with the `adjacentAlly` target type, even when it's their only option
- Fixed gilded chests being more accessible than intended
- Fixed fished up Pokémon not being added as "seen" to the Pokedex
- Fixed surprised Gimmighoul encounters not being added as "seen" to the Pokedex
- Fixed a crash involving berry trees that have been world edited.
- Fixed visual desync in multiplayer for players mounting Pokémon outside other players' loaded chunks
- Fixed Pokémon entities leveled by rare candy not getting stronger as Minecraft entities unless recalled.
- Fixed a freeze during game load that occurred when multiple mods tried to load Cobblemon API classes at the same time.
- Fixed random tick crashes from berry trees
- Lowered the volume of Blitzle and Zebstrika's cry
- Regional Foods will now prioritise being eaten instead of used for healing Pokémon, shift clicking will use it as healing
- Resolved Z-Fighting on Pokédex Models
- Restored Ninjask's ability to do barrel rolls
- Fixed Raichu (male) and Alolan Raichu (both genders) not displaying the correct Partner Cap when Pewter Crunchies are in the cosmetic slot.
- Fixed a crash caused by adding enchanted items to the Resurrection Machine
- Fixed a crash that could occur when starting a PvN battle with only fainted Pokémon.
- Fixed the Remember Riding Camera config not being respected when dismounting and resolved the incompatibility with the Auto Third Person mod
- Fixed Full Heal block not dropping Full Heals
- Fixed status cure items not returning an empty bottle when used
- Fixed Panpour consuming its held item when evolving with a Water Stone
- Fixed Smoked Tail Curry returning a Wooden Bowl when consumed despite it not being included in the recipe
- Fixed `/giveallpokemon` not respecting the min and max parameters
- Fixed the choose starter toast not disappearing when capturing a Pokémon instead of opening the starter selection screen
- Fixed an issue where certain Sinister Tea seasonings were only applying as instant effects and would not apply over time
- Long config option labels now scroll instead of overflowing
### Developer
- Added `PokeSnackSpawnerFactory` which allows influence registration on PokeSnack encounters
- Added `FishingSpawnerFactory` which allows influence registration on fishing encounters
- Added `BattleFleeAttemptEvent` fired from `PokemonBattle.checkFleeAttempt`, allowing developers to intercept and control flee attempts
- Tweaked the spawning selector interface to take a bucket function rather than a bucket directly.
- Added a new `cobblemon:height_range` processor type to allow developers to restrict structure-spawning ranges.
- Separated all the functions of MoLangFunctions.kt into their own files.
- Spawn buckets and their base weights are now provided by the spawner, with different base weights for world, fishing, snack, and habitat spawn buckets.
- Removed "SpawnBucket" class in favour of just storing maps of bucket names to weights.
- Fixed nicknames not being applied to Pokémon spawned from `spawn_pool_world` files.
- Added support for `profilePokedexScale`, `profilePokedexTranslation`, `profileSummaryScale`, and `profileSummaryTranslation` in poser files for finer control over profile displays.
- Fixed riding camera offsets defined on Pokémon forms not being applied
### Molang & Datapacks
- q.item.is_enchanted()
- q.item.has_enchantment(minecraft:sharpness, 3)
- Added `moveset_builders` datapack folder for different styles of movesets.
- Added `party_pools` datapack folder for defining groups of Pokémon for 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.
- Added basic chatter NPC Behaviour
- Added `q.item.is_enchanted()`
- Added `q.item.has_enchantment(minecraft:sharpness, 3)`
- Added `has_chosen_starter` & `get_starter_uuid` as available Molang functions
- Added `marks`, `has_mark`, & `remove_marks` as available Molang functions for pokemon
- Added `has_tm_move_unlocked`, `unlock_tm_move`, & `lock_tm_move` as available Molang functions for Players
- Added `marks`, `has_mark`, & `remove_marks` as available Molang functions for Pokémon
- Added Data Component support for species drops, eg `"components": {"minecraft:custom_model_data": 123}`
- Added the new `sortOrder` field to mark entries, (defaults to 0 if not specified) which controls the order in which marks are rendered on the HUD, with higher numbers being rendered on top of lower numbers
- Added optional `order` field to starter categories. It will allow explicitly sorting categories in the starter selection screen
- SpeciesAdditions append vs override now matches wiki documentation
- Added `weighted_choice` as a new feature type. It requires setting weights for each choice and allows developers to simplify the process of assigning random aspect choice based on marble chance
- Added `q.world.spawn_loot_table_items(loot_table_id, x, y, z)` which spawns the items from the loot table at the position. (Use type: "minecraft:chest" for the loot table.)
- Added `q.pokemon.entity` to access the entity of Pokémon.
- Flamethrower and Seismic Toss had their action effect JSON cleaned up
- Ride sounds can now be set as exclusive to passengers
- Ride sounds no longer play when submerged unless specified with a new setting
- NPC Trainers can now call a `command` animation when issuing a command in battle.
- Added a q.failed function to move action effects.
- Herd spawned Pokémon have their levels controlled differently. The `levelRange` property now acts as a clamp instead of a filter, with a new `herdLevelRange` property to do the filter behaviour.
- `q.sound` now accepts three parameters (sound event, volume and pitch) instead of just the sound event and pitch.
### Particles
#### New Move Animations
- Blizzard
- Disarming Voice
- Draco Meteor
- Dragon Breath
- Dragon Rage
- Drain Punch
- Fairy Wind
- Fire Fang
- Gust
- Horn Drill
- Hydro Pump
- Ice Fang
- Leafage
- Leaf Storm
- Light Screen
- Night Shade
- Play Rough
- Pyro Ball
- Reflect
- Rock Slide
- Sonic Boom
- Sucker Punch
- Supersonic
- Thunder Fang
#### Tweaks and Fixes (Moves)
- Confusion
- Dragon Claw
- Eruption
- Fire Punch
- Flame Burst
- Flame Charge
- Flamethrower
- Frost Breath
- Hypnosis
- Ice Punch
- Icy Wind
- Mud Sport
- Poison Fang
- Protect
- Psychic
- Quick Attack
- Rage Powder
- Razor Leaf
- Sand Attack
- Scratch
- Shadow Claw
- Sing
- Spore
- String Shot
- Tackle
- Tail Whip
- Thunder
- Thunder Punch
- Thunder Wave
- Water Gun
- Water Pulse
- Water Sport
#### Miscellaneous Particles
+ Added Wild Might particles for Alpha Pokémon
+ Updated stat increase and decrease particles
### Localization
- Updated translations for:
- Japanese
- German
- Spanish
- Ecuadorian Spanish
- Portuguese
- Brazilian Portuguese
- Simplified Chinese
- Traditional Chinese
- Korean
+9
View File
@@ -0,0 +1,9 @@
- Some kind of particle effect for them? they're meant to have glowing eyes, so maybe some red particles on the eye locator
--- global posers? stacked posers?
--- red texture seems to be what some people wanted.
/- shoulder mounts part of it
- omni boost
- roar when player comes within reach, adjust levels
- Riding settings to control what the min scale is for a pokemon to be ridable.
-510
View File
@@ -1,510 +0,0 @@
{
"format_version": "1.21.11",
"credit": "Made with Blockbench",
"texture_size": [128, 128],
"textures": {
"2": "block/texture"
},
"elements": [
{
"from": [9.999, 10.999, -0.001],
"to": [15.001, 12.001, 0.001],
"rotation": {"angle": 0, "axis": "y", "origin": [1, -1, 1]},
"faces": {
"north": {"uv": [0.25, 1.125, 0.875, 1.25], "texture": "#2"},
"east": {"uv": [0.25, 1.125, 0.25, 1.25], "texture": "#2"},
"south": {"uv": [0.875, 1.125, 1.5, 1.25], "texture": "#2"},
"west": {"uv": [0.875, 1.125, 0.875, 1.25], "texture": "#2"},
"up": {"uv": [0.875, 1.125, 0.25, 1.125], "texture": "#2"},
"down": {"uv": [1.5, 1.125, 0.875, 1.125], "texture": "#2"}
}
},
{
"from": [-0.0001, 8.9999, 2.9999],
"to": [2.0001, 13.0001, 13.0001],
"rotation": {"angle": 0, "axis": "y", "origin": [1, -1, 2]},
"faces": {
"north": {"uv": [4.25, 6, 4.5, 6.5], "texture": "#2"},
"east": {"uv": [3, 6, 4.25, 6.5], "texture": "#2"},
"south": {"uv": [5.75, 6, 6, 6.5], "texture": "#2"},
"west": {"uv": [4.5, 6, 5.75, 6.5], "texture": "#2"},
"up": {"uv": [4.5, 6, 4.25, 4.75], "texture": "#2"},
"down": {"uv": [4.75, 4.75, 4.5, 6], "texture": "#2"}
}
},
{
"from": [-0.0001, 8.9999, -0.0001],
"to": [16.0001, 13.0001, 3.0001],
"rotation": {"angle": 0, "axis": "y", "origin": [1, -1, 1]},
"faces": {
"north": {"uv": [0.375, 3.375, 2.375, 3.875], "texture": "#2"},
"east": {"uv": [0, 3.375, 0.375, 3.875], "texture": "#2"},
"south": {"uv": [2.75, 3.375, 4.75, 3.875], "texture": "#2"},
"west": {"uv": [2.375, 3.375, 2.75, 3.875], "texture": "#2"},
"up": {"uv": [2.375, 3.375, 0.375, 3], "texture": "#2"},
"down": {"uv": [4.375, 3, 2.375, 3.375], "texture": "#2"}
}
},
{
"from": [2.995, 10.995, -0.005],
"to": [15.005, 13.005, 2.005],
"rotation": {"angle": 0, "axis": "y", "origin": [1, -1, 1]},
"faces": {
"north": {"uv": [0.25, 6.75, 1.75, 7], "texture": "#2"},
"east": {"uv": [0, 6.75, 0.25, 7], "texture": "#2"},
"south": {"uv": [2, 6.75, 3.5, 7], "texture": "#2"},
"west": {"uv": [1.75, 6.75, 2, 7], "texture": "#2"},
"up": {"uv": [1.75, 6.75, 0.25, 6.5], "texture": "#2"},
"down": {"uv": [3.25, 6.5, 1.75, 6.75], "texture": "#2"}
}
},
{
"from": [9.999, 10.999, -0.001],
"to": [15.001, 12.001, 0.001],
"rotation": {"angle": 0, "axis": "y", "origin": [1, -1, 1]},
"faces": {
"north": {"uv": [0.25, 1.375, 0.875, 1.5], "texture": "#2"},
"east": {"uv": [0.25, 1.375, 0.25, 1.5], "texture": "#2"},
"south": {"uv": [0.875, 1.375, 1.5, 1.5], "texture": "#2"},
"west": {"uv": [0.875, 1.375, 0.875, 1.5], "texture": "#2"},
"up": {"uv": [0.875, 1.375, 0.25, 1.375], "texture": "#2"},
"down": {"uv": [1.5, 1.375, 0.875, 1.375], "texture": "#2"}
}
},
{
"from": [13.9999, 8.9999, 2.9999],
"to": [16.0001, 13.0001, 13.0001],
"rotation": {"angle": 0, "axis": "y", "origin": [1, -1, 2]},
"faces": {
"north": {"uv": [1.25, 6, 1.5, 6.5], "texture": "#2"},
"east": {"uv": [0, 6, 1.25, 6.5], "texture": "#2"},
"south": {"uv": [2.75, 6, 3, 6.5], "texture": "#2"},
"west": {"uv": [1.5, 6, 2.75, 6.5], "texture": "#2"},
"up": {"uv": [1.5, 6, 1.25, 4.75], "texture": "#2"},
"down": {"uv": [1.75, 4.75, 1.5, 6], "texture": "#2"}
}
},
{
"from": [-0.0001, 8.9999, 12.9999],
"to": [16.0001, 13.0001, 16.0001],
"rotation": {"angle": 0, "axis": "y", "origin": [1, -1, 1]},
"faces": {
"north": {"uv": [0.375, 4.25, 2.375, 4.75], "texture": "#2"},
"east": {"uv": [0, 4.25, 0.375, 4.75], "texture": "#2"},
"south": {"uv": [2.75, 4.25, 4.75, 4.75], "texture": "#2"},
"west": {"uv": [2.375, 4.25, 2.75, 4.75], "texture": "#2"},
"up": {"uv": [2.375, 4.25, 0.375, 3.875], "texture": "#2"},
"down": {"uv": [4.375, 3.875, 2.375, 4.25], "texture": "#2"}
}
},
{
"from": [1, 0, 1],
"to": [15, 10, 15],
"rotation": {"angle": 0, "axis": "y", "origin": [1, 0, 1]},
"faces": {
"north": {"uv": [1.75, 1.75, 3.5, 3], "texture": "#2"},
"east": {"uv": [0, 1.75, 1.75, 3], "texture": "#2"},
"south": {"uv": [5.25, 1.75, 7, 3], "texture": "#2"},
"west": {"uv": [3.5, 1.75, 5.25, 3], "texture": "#2"},
"up": {"uv": [3.5, 1.75, 1.75, 0], "texture": "#2"},
"down": {"uv": [5.25, 0, 3.5, 1.75], "texture": "#2"}
}
},
{
"from": [3.999, 1.999, 0.999],
"to": [12.001, 10.001, 1.001],
"rotation": {"angle": 0, "axis": "y", "origin": [1, 0, 1]},
"faces": {
"north": {"uv": [0, 7.375, 1, 8.375], "texture": "#2"},
"east": {"uv": [0, 7.375, 0, 8.375], "texture": "#2"},
"south": {"uv": [1, 7.375, 2, 8.375], "texture": "#2"},
"west": {"uv": [1, 7.375, 1, 8.375], "texture": "#2"},
"up": {"uv": [1, 7.375, 0, 7.375], "texture": "#2"},
"down": {"uv": [2, 7.375, 1, 7.375], "texture": "#2"}
}
},
{
"from": [2, 11, 5],
"to": [14, 12, 6],
"rotation": {"angle": 0, "axis": "y", "origin": [1, 11, 1]},
"faces": {
"north": {"uv": [5.125, 3.375, 6.625, 3.5], "texture": "#2"},
"east": {"uv": [4.75, 3.375, 4.875, 3.5], "texture": "#2"},
"south": {"uv": [7, 3.375, 8.5, 3.5], "texture": "#2"},
"west": {"uv": [6.875, 3.375, 7, 3.5], "texture": "#2"},
"up": {"uv": [6.625, 3.125, 5.125, 3], "texture": "#2"},
"down": {"uv": [8.125, 3, 6.625, 3.125], "texture": "#2"}
}
},
{
"from": [2, 11, 4],
"to": [14, 12, 5],
"rotation": {"angle": 0, "axis": "y", "origin": [1, 11, 1]},
"faces": {
"north": {"uv": [5.125, 3.375, 6.625, 3.5], "texture": "#2"},
"east": {"uv": [4.875, 3.375, 5, 3.5], "texture": "#2"},
"south": {"uv": [7, 3.375, 8.5, 3.5], "texture": "#2"},
"west": {"uv": [6.75, 3.375, 6.875, 3.5], "texture": "#2"},
"up": {"uv": [6.625, 3.25, 5.125, 3.125], "texture": "#2"},
"down": {"uv": [8.125, 3.125, 6.625, 3.25], "texture": "#2"}
}
},
{
"from": [2, 11, 3],
"to": [14, 12, 4],
"rotation": {"angle": 0, "axis": "y", "origin": [1, 11, 1]},
"faces": {
"north": {"uv": [5.125, 3.375, 6.625, 3.5], "texture": "#2"},
"east": {"uv": [5, 3.375, 5.125, 3.5], "texture": "#2"},
"south": {"uv": [7, 3.375, 8.5, 3.5], "texture": "#2"},
"west": {"uv": [6.625, 3.375, 6.75, 3.5], "texture": "#2"},
"up": {"uv": [6.625, 3.375, 5.125, 3.25], "texture": "#2"},
"down": {"uv": [8.125, 3.25, 6.625, 3.375], "texture": "#2"}
}
},
{
"from": [10, 11, 6],
"to": [14, 12, 8],
"rotation": {"angle": 0, "axis": "y", "origin": [1, 11, 1]},
"faces": {
"north": {"uv": [5, 4.25, 5.5, 4.375], "texture": "#2"},
"east": {"uv": [4.75, 4.25, 5, 4.375], "texture": "#2"},
"south": {"uv": [5.75, 4.25, 6.25, 4.375], "texture": "#2"},
"west": {"uv": [5.5, 4.25, 5.75, 4.375], "texture": "#2"},
"up": {"uv": [5.5, 4.25, 5, 4], "texture": "#2"},
"down": {"uv": [6, 4, 5.5, 4.25], "texture": "#2"}
}
},
{
"from": [2, 11, 6],
"to": [6, 12, 8],
"rotation": {"angle": 0, "axis": "y", "origin": [1, 11, 1]},
"faces": {
"north": {"uv": [5, 4.625, 5.5, 4.75], "texture": "#2"},
"east": {"uv": [4.75, 4.625, 5, 4.75], "texture": "#2"},
"south": {"uv": [5.75, 4.625, 6.25, 4.75], "texture": "#2"},
"west": {"uv": [5.5, 4.625, 5.75, 4.75], "texture": "#2"},
"up": {"uv": [5.5, 4.625, 5, 4.375], "texture": "#2"},
"down": {"uv": [6, 4.375, 5.5, 4.625], "texture": "#2"}
}
},
{
"from": [2, 11, 10],
"to": [14, 12, 11],
"rotation": {"angle": 0, "axis": "y", "origin": [1, 11, 6]},
"faces": {
"north": {"uv": [5.125, 3.875, 6.625, 4], "texture": "#2"},
"east": {"uv": [5, 3.875, 5.125, 4], "texture": "#2"},
"south": {"uv": [7, 3.875, 8.5, 4], "texture": "#2"},
"west": {"uv": [6.625, 3.875, 6.75, 4], "texture": "#2"},
"up": {"uv": [6.625, 3.875, 5.125, 3.75], "texture": "#2"},
"down": {"uv": [8.125, 3.75, 6.625, 3.875], "texture": "#2"}
}
},
{
"from": [2, 11, 11],
"to": [14, 12, 12],
"rotation": {"angle": 0, "axis": "y", "origin": [1, 11, 6]},
"faces": {
"north": {"uv": [5.125, 3.875, 6.625, 4], "texture": "#2"},
"east": {"uv": [4.875, 3.875, 5, 4], "texture": "#2"},
"south": {"uv": [7, 3.875, 8.5, 4], "texture": "#2"},
"west": {"uv": [6.75, 3.875, 6.875, 4], "texture": "#2"},
"up": {"uv": [6.625, 3.75, 5.125, 3.625], "texture": "#2"},
"down": {"uv": [8.125, 3.625, 6.625, 3.75], "texture": "#2"}
}
},
{
"from": [2, 11, 12],
"to": [14, 12, 13],
"rotation": {"angle": 0, "axis": "y", "origin": [1, 11, 6]},
"faces": {
"north": {"uv": [5.125, 3.875, 6.625, 4], "texture": "#2"},
"east": {"uv": [4.75, 3.875, 4.875, 4], "texture": "#2"},
"south": {"uv": [7, 3.875, 8.5, 4], "texture": "#2"},
"west": {"uv": [6.875, 3.875, 7, 4], "texture": "#2"},
"up": {"uv": [6.625, 3.625, 5.125, 3.5], "texture": "#2"},
"down": {"uv": [8.125, 3.5, 6.625, 3.625], "texture": "#2"}
}
},
{
"from": [10, 11, 8],
"to": [14, 12, 10],
"rotation": {"angle": 0, "axis": "y", "origin": [1, 11, 6]},
"faces": {
"north": {"uv": [6.25, 5, 6.75, 5.125], "texture": "#2"},
"east": {"uv": [6, 5, 6.25, 5.125], "texture": "#2"},
"south": {"uv": [7, 5, 7.5, 5.125], "texture": "#2"},
"west": {"uv": [6.75, 5, 7, 5.125], "texture": "#2"},
"up": {"uv": [6.75, 5, 6.25, 4.75], "texture": "#2"},
"down": {"uv": [7.25, 4.75, 6.75, 5], "texture": "#2"}
}
},
{
"from": [6, 11, 9],
"to": [10, 12, 10],
"rotation": {"angle": 0, "axis": "y", "origin": [1, 11, 6]},
"faces": {
"north": {"uv": [6.125, 5.625, 6.625, 5.75], "texture": "#2"},
"east": {"uv": [6, 5.625, 6.125, 5.75], "texture": "#2"},
"south": {"uv": [6.75, 5.625, 7.25, 5.75], "texture": "#2"},
"west": {"uv": [6.625, 5.625, 6.75, 5.75], "texture": "#2"},
"up": {"uv": [6.625, 5.625, 6.125, 5.5], "texture": "#2"},
"down": {"uv": [7.125, 5.5, 6.625, 5.625], "texture": "#2"}
}
},
{
"from": [2, 11, 8],
"to": [6, 12, 10],
"rotation": {"angle": 0, "axis": "y", "origin": [-3, 11, 6]},
"faces": {
"north": {"uv": [6.25, 5.375, 6.75, 5.5], "texture": "#2"},
"east": {"uv": [6, 5.375, 6.25, 5.5], "texture": "#2"},
"south": {"uv": [7, 5.375, 7.5, 5.5], "texture": "#2"},
"west": {"uv": [6.75, 5.375, 7, 5.5], "texture": "#2"},
"up": {"uv": [6.75, 5.375, 6.25, 5.125], "texture": "#2"},
"down": {"uv": [7.25, 5.125, 6.75, 5.375], "texture": "#2"}
}
},
{
"from": [9, 11, 7],
"to": [10, 12, 9],
"rotation": {"angle": 0, "axis": "y", "origin": [1, 11, 6]},
"faces": {
"north": {"uv": [6.5, 4.25, 6.625, 4.375], "texture": "#2"},
"east": {"uv": [6.25, 4.25, 6.5, 4.375], "texture": "#2"},
"south": {"uv": [6.875, 4.25, 7, 4.375], "texture": "#2"},
"west": {"uv": [6.625, 4.25, 6.875, 4.375], "texture": "#2"},
"up": {"uv": [6.625, 4.25, 6.5, 4], "texture": "#2"},
"down": {"uv": [6.75, 4, 6.625, 4.25], "texture": "#2"}
}
},
{
"from": [6, 11, 7],
"to": [7, 12, 9],
"rotation": {"angle": 0, "axis": "y", "origin": [1, 11, 6]},
"faces": {
"north": {"uv": [6.5, 4.625, 6.625, 4.75], "texture": "#2"},
"east": {"uv": [6.25, 4.625, 6.5, 4.75], "texture": "#2"},
"south": {"uv": [6.875, 4.625, 7, 4.75], "texture": "#2"},
"west": {"uv": [6.625, 4.625, 6.875, 4.75], "texture": "#2"},
"up": {"uv": [6.625, 4.625, 6.5, 4.375], "texture": "#2"},
"down": {"uv": [6.75, 4.375, 6.625, 4.625], "texture": "#2"}
}
},
{
"from": [7, 11, 7],
"to": [9, 12, 9],
"rotation": {"angle": 0, "axis": "y", "origin": [1, 11, 6]},
"faces": {
"north": {"uv": [6.25, 6.25, 6.5, 6.375], "texture": "#2"},
"east": {"uv": [6, 6.25, 6.25, 6.375], "texture": "#2"},
"south": {"uv": [6.75, 6.25, 7, 6.375], "texture": "#2"},
"west": {"uv": [6.5, 6.25, 6.75, 6.375], "texture": "#2"},
"up": {"uv": [6.5, 6.25, 6.25, 6], "texture": "#2"},
"down": {"uv": [6.75, 6, 6.5, 6.25], "texture": "#2"}
}
},
{
"from": [6, 11, 6],
"to": [10, 12, 7],
"rotation": {"angle": 0, "axis": "y", "origin": [1, 11, 6]},
"faces": {
"north": {"uv": [6.125, 5.875, 6.625, 6], "texture": "#2"},
"east": {"uv": [6, 5.875, 6.125, 6], "texture": "#2"},
"south": {"uv": [6.75, 5.875, 7.25, 6], "texture": "#2"},
"west": {"uv": [6.625, 5.875, 6.75, 6], "texture": "#2"},
"up": {"uv": [6.625, 5.875, 6.125, 5.75], "texture": "#2"},
"down": {"uv": [7.125, 5.75, 6.625, 5.875], "texture": "#2"}
}
},
{
"from": [0, 13, 11],
"to": [0, 15, 12],
"rotation": {"angle": 0, "axis": "y", "origin": [1, 0, -2]},
"faces": {
"north": {"uv": [6.375, 6.5, 6.375, 6.75], "texture": "#2"},
"east": {"uv": [6.25, 6.5, 6.375, 6.75], "texture": "#2"},
"south": {"uv": [6.5, 6.5, 6.5, 6.75], "texture": "#2"},
"west": {"uv": [6.375, 6.5, 6.5, 6.75], "texture": "#2"},
"up": {"uv": [6.375, 6.5, 6.375, 6.375], "texture": "#2"},
"down": {"uv": [6.375, 6.375, 6.375, 6.5], "texture": "#2"}
}
},
{
"from": [0, 13, 14],
"to": [0, 20, 15],
"rotation": {"angle": 0, "axis": "y", "origin": [1, 0, 1]},
"faces": {
"north": {"uv": [6.125, 6.5, 6.125, 7.375], "texture": "#2"},
"east": {"uv": [6, 6.5, 6.125, 7.375], "texture": "#2"},
"south": {"uv": [6.25, 6.5, 6.25, 7.375], "texture": "#2"},
"west": {"uv": [6.125, 6.5, 6.25, 7.375], "texture": "#2"},
"up": {"uv": [6.125, 6.5, 6.125, 6.375], "texture": "#2"},
"down": {"uv": [6.125, 6.375, 6.125, 6.5], "texture": "#2"}
}
},
{
"from": [0, 13, 14],
"to": [0, 20, 15],
"rotation": {"angle": 0, "axis": "y", "origin": [1, 0, 1]},
"faces": {
"north": {"uv": [6.625, 6.5, 6.625, 7.375], "texture": "#2"},
"east": {"uv": [6.5, 6.5, 6.625, 7.375], "texture": "#2"},
"south": {"uv": [6.75, 6.5, 6.75, 7.375], "texture": "#2"},
"west": {"uv": [6.625, 6.5, 6.75, 7.375], "texture": "#2"},
"up": {"uv": [6.625, 6.5, 6.625, 6.375], "texture": "#2"},
"down": {"uv": [6.625, 6.375, 6.625, 6.5], "texture": "#2"}
}
},
{
"from": [0, 13, 14],
"to": [0, 20, 15],
"rotation": {"angle": 0, "axis": "y", "origin": [1, 0, 1]},
"faces": {
"north": {"uv": [6.875, 6.5, 6.875, 7.375], "texture": "#2"},
"east": {"uv": [6.75, 6.5, 6.875, 7.375], "texture": "#2"},
"south": {"uv": [7, 6.5, 7, 7.375], "texture": "#2"},
"west": {"uv": [6.875, 6.5, 7, 7.375], "texture": "#2"},
"up": {"uv": [6.875, 6.5, 6.875, 6.375], "texture": "#2"},
"down": {"uv": [6.875, 6.375, 6.875, 6.5], "texture": "#2"}
}
}
],
"groups": [
{
"name": "bone",
"origin": [1, 0, 1],
"color": 0,
"children": [
{
"name": "bone9",
"origin": [12.5, 11.5, 0],
"color": 0,
"children": [0]
},
1,
2,
{
"name": "bone5",
"origin": [9, 12, 1],
"color": 0,
"children": [3]
},
{
"name": "bone4",
"origin": [12.5, 11.5, 0],
"color": 0,
"children": [4]
},
5,
6,
7,
{
"name": "bone8",
"origin": [8, 6, 1],
"color": 0,
"children": [8]
},
{
"name": "opening",
"origin": [8, 11.5, 6],
"color": 0,
"children": [
{
"name": "bone3",
"origin": [8, 11.5, 3],
"color": 0,
"children": [
{
"name": "bone10",
"origin": [8, 11.5, 5.5],
"color": 0,
"children": [
9,
{
"name": "bone11",
"origin": [8, 11.5, 4.5],
"color": 0,
"children": [
10,
{
"name": "bone12",
"origin": [8, 11.5, 3.5],
"color": 0,
"children": [11]
}
]
}
]
},
12,
13
]
},
{
"name": "bone2",
"origin": [8, 11.5, 13.0375],
"color": 0,
"children": [
{
"name": "bone13",
"origin": [8, 11.5, 10.5],
"color": 0,
"children": [
14,
{
"name": "bone14",
"origin": [8, 11.5, 11.5],
"color": 0,
"children": [15]
},
{
"name": "bone15",
"origin": [8, 11.5, 12.5],
"color": 0,
"children": [16]
}
]
},
17,
18,
19,
20,
21,
22,
23
]
}
]
},
24,
{
"name": "bone7",
"origin": [1, 0, 1],
"color": 0,
"children": [
{
"name": "bone6",
"origin": [0, 16.5, 14.5],
"color": 0,
"children": [25]
},
{
"name": "bone5red",
"origin": [0, 16.5, 14.5],
"color": 0,
"children": [26]
},
{
"name": "bone8green",
"origin": [0, 16.5, 14.5],
"color": 0,
"children": [27]
}
]
}
]
}
]
}
+4
View File
@@ -72,6 +72,10 @@ tasks.withType<Test> {
}
}
tasks.processResources {
exclude("data/**/README.md")
}
sourceSets {
main {
blossom {
@@ -1,146 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.client.camera;
import com.cobblemon.mod.common.client.util.compat.SodiumCompat;
import com.cobblemon.mod.common.platform.events.ClientChunkEvent;
import com.cobblemon.mod.common.platform.events.PlatformEvents;
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
import kotlin.Unit;
import kotlin.jvm.functions.Function1;
import net.minecraft.client.Minecraft;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.network.protocol.game.ClientboundLevelChunkPacketData;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.chunk.LevelChunk;
import java.util.function.Consumer;
public class CameraClientChunkCacheExtension {
private static final int MIN_RENDER_DISTANCE = 2;
private static final int MAX_RENDER_DISTANCE = 64;
private static final int RENDER_DISTANCE_MARGIN = 2;
private static final Long2ObjectOpenHashMap<LevelChunk> CHUNK_MAP = new Long2ObjectOpenHashMap<>();
private static final Long2ObjectOpenHashMap<LevelChunk> CHUNK_MAP_OTHER_THREADS = new Long2ObjectOpenHashMap<>();
private static volatile ChunkPos CAMERA_CENTER;
private CameraClientChunkCacheExtension() {}
public static void drop(ClientLevel level, ChunkPos chunkPos) {
if (Minecraft.getInstance().isSameThread()) {
long chunkPosLong = chunkPos.toLong();
LevelChunk chunk = CHUNK_MAP.get(chunkPosLong);
if (chunk != null) {
modifyChunkMaps(map -> map.remove(chunkPosLong));
SodiumCompat.getInstance().notifyChunkRemoved(level, chunkPos.x, chunkPos.z);
PlatformEvents.CLIENT_CHUNK_UNLOAD.postEvents(new ClientChunkEvent.Unload(chunk, level));
level.unload(chunk);
}
}
}
public static LevelChunk getChunk(int x, int z) {
long chunkPos = ChunkPos.asLong(x, z);
if (Minecraft.getInstance().isSameThread())
return CHUNK_MAP.get(chunkPos);
else {
synchronized (CHUNK_MAP_OTHER_THREADS) {
return CHUNK_MAP_OTHER_THREADS.get(chunkPos);
}
}
}
public static LevelChunk replaceWithPacketData(ClientLevel level, int x, int z, FriendlyByteBuf packetData, CompoundTag chunkTag, Consumer<ClientboundLevelChunkPacketData.BlockEntityTagOutput> tagOutput) {
if (!Minecraft.getInstance().isSameThread())
throw new UnsupportedOperationException("replaceWithPacketData called off-thread, this shouldn't happen!");
ChunkPos chunkPos = new ChunkPos(x, z);
long longChunkPos = chunkPos.toLong();
LevelChunk chunk = CHUNK_MAP.get(longChunkPos);
if (chunk == null) {
LevelChunk newChunk = new LevelChunk(level, chunkPos);
chunk = newChunk;
chunk.replaceWithPacketData(packetData, chunkTag, tagOutput);
modifyChunkMaps(map -> map.put(longChunkPos, newChunk));
}
level.onChunkLoaded(chunkPos);
SodiumCompat.getInstance().notifyChunkAdded(level, x, z);
PlatformEvents.CLIENT_CHUNK_LOAD.postEvents(new ClientChunkEvent.Load(chunk, level));
return chunk;
}
private static void modifyChunkMaps(Consumer<Long2ObjectOpenHashMap<LevelChunk>> operation) {
operation.accept(CHUNK_MAP);
synchronized (CHUNK_MAP_OTHER_THREADS) {
operation.accept(CHUNK_MAP_OTHER_THREADS);
}
}
public static void clear() {
CHUNK_MAP.clear();
CHUNK_MAP_OTHER_THREADS.clear();
CAMERA_CENTER = null;
}
public static boolean hasCameraChunks() {
if (Minecraft.getInstance().isSameThread()) {
return !CHUNK_MAP.isEmpty();
} else {
synchronized (CHUNK_MAP_OTHER_THREADS) {
return !CHUNK_MAP_OTHER_THREADS.isEmpty();
}
}
}
/**
* Computes render distance using Chebyshev distance with a safety margin.
*/
public static int getSuggestedRenderDistance(ChunkPos center) {
int maxDistance = 0;
if (Minecraft.getInstance().isSameThread()) {
for (long key : CHUNK_MAP.keySet()) {
int x = ChunkPos.getX(key);
int z = ChunkPos.getZ(key);
int dx = Math.abs(x - center.x);
int dz = Math.abs(z - center.z);
maxDistance = Math.max(maxDistance, Math.max(dx, dz));
}
} else {
synchronized (CHUNK_MAP_OTHER_THREADS) {
for (long key : CHUNK_MAP_OTHER_THREADS.keySet()) {
int x = ChunkPos.getX(key);
int z = ChunkPos.getZ(key);
int dx = Math.abs(x - center.x);
int dz = Math.abs(z - center.z);
maxDistance = Math.max(maxDistance, Math.max(dx, dz));
}
}
}
return Math.max(MIN_RENDER_DISTANCE, Math.min(MAX_RENDER_DISTANCE, maxDistance + RENDER_DISTANCE_MARGIN));
}
public static void setCameraCenter(ChunkPos center) {
CAMERA_CENTER = center;
}
public static ChunkPos getCameraCenter() {
return CAMERA_CENTER;
}
}
@@ -1,86 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.client.render.camera;
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
import net.minecraft.client.renderer.chunk.SectionRenderDispatcher;
import net.minecraft.core.BlockPos;
import net.minecraft.core.SectionPos;
import net.minecraft.world.level.Level;
public final class CameraViewAreaExtension {
private static final Long2ObjectOpenHashMap<SectionRenderDispatcher.RenderSection> SECTIONS = new Long2ObjectOpenHashMap<>();
private static SectionRenderDispatcher sectionRenderDispatcher;
private static int minSectionY;
private static int maxSectionY;
private CameraViewAreaExtension() {
}
public static void allChanged(SectionRenderDispatcher dispatcher, Level level) {
clear();
sectionRenderDispatcher = dispatcher;
minSectionY = level.getMinSection();
maxSectionY = level.getMaxSection();
}
public static SectionRenderDispatcher.RenderSection rawFetch(int cx, int cy, int cz, boolean generateNew) {
if (cy < minSectionY || cy >= maxSectionY) {
return null;
}
long sectionPos = SectionPos.asLong(cx, cy, cz);
return generateNew ? provideSection(sectionPos) : SECTIONS.get(sectionPos);
}
public static void setDirty(int cx, int cy, int cz, boolean playerChanged) {
SectionRenderDispatcher.RenderSection section = rawFetch(cx, cy, cz, false);
if (section != null) {
section.setDirty(playerChanged);
}
}
public static void onChunkUnload(int sectionX, int sectionZ) {
for (int sectionY = minSectionY; sectionY < maxSectionY; sectionY++) {
long sectionPos = SectionPos.asLong(sectionX, sectionY, sectionZ);
SectionRenderDispatcher.RenderSection section = SECTIONS.remove(sectionPos);
if (section != null) {
section.releaseBuffers();
}
}
}
public static void clear() {
for (SectionRenderDispatcher.RenderSection section : SECTIONS.values()) {
section.releaseBuffers();
}
SECTIONS.clear();
}
public static int minSectionY() {
return minSectionY;
}
public static int maxSectionY() {
return maxSectionY;
}
private static SectionRenderDispatcher.RenderSection provideSection(long sectionPos) {
return SECTIONS.computeIfAbsent(sectionPos, CameraViewAreaExtension::createSection);
}
private static SectionRenderDispatcher.RenderSection createSection(long sectionPos) {
if (sectionRenderDispatcher == null) {
throw new IllegalStateException("SectionRenderDispatcher not initialised");
}
BlockPos origin = SectionPos.of(sectionPos).origin();
return sectionRenderDispatcher.new RenderSection(0, origin.getX(), origin.getY(), origin.getZ());
}
}
@@ -1,15 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.client.render.camera.accessor;
import net.minecraft.client.renderer.culling.Frustum;
public interface CameraLevelRendererAccessor {
Frustum cobblemonGetFrustum();
}
@@ -13,5 +13,6 @@ public interface ChannelDuck {
void cobblemon$inverseAttenuation(float rolloffFactor);
void cobblemon$clearFilters();
// void cobblemon$exponentialAttenuation(float rolloff, float refDistance, float maxDistance);
void cobblemon$applyReverb(float decayTime, float gain, float diffusion, float density);
void cobblemon$clearReverb();
}
@@ -1,70 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.mixin;
import com.cobblemon.mod.common.duck.ChannelDuck;
import com.mojang.blaze3d.audio.Channel;
import org.lwjgl.openal.AL10;
import org.lwjgl.openal.EXTEfx;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
@Mixin(Channel.class)
public abstract class ChannelMixin implements ChannelDuck {
@Shadow
private int source;
// Id of filter applied when sound is obstructed
private int cobblemon$lowPassFilterId = 0;
@Override
public void cobblemon$applyLowPassFilter(float gain, float hfGain) {
// Delete old filter if it exists
if (cobblemon$lowPassFilterId != 0) {
AL10.alSourcei(source, EXTEfx.AL_DIRECT_FILTER, 0); // Detach filter from source
EXTEfx.alDeleteFilters(cobblemon$lowPassFilterId); // Delete old filter
cobblemon$lowPassFilterId = 0;
}
// Generate a fresh filter
int filterId = EXTEfx.alGenFilters();
if (!EXTEfx.alIsFilter(filterId)) {
System.err.println("Failed to create OpenAL low-pass filter");
return;
}
EXTEfx.alFilteri(filterId, EXTEfx.AL_FILTER_TYPE, EXTEfx.AL_FILTER_LOWPASS);
EXTEfx.alFilterf(filterId, EXTEfx.AL_LOWPASS_GAIN, gain);
EXTEfx.alFilterf(filterId, EXTEfx.AL_LOWPASS_GAINHF, hfGain);
AL10.alSourcei(source, EXTEfx.AL_DIRECT_FILTER, filterId);
// Save the new filter ID
cobblemon$lowPassFilterId = filterId;
}
@Override
public void cobblemon$inverseAttenuation(float rolloffFactor) {
AL10.alSourcei(source, AL10.AL_DISTANCE_MODEL, AL10.AL_INVERSE_DISTANCE);
AL10.alSourcef(source, AL10.AL_ROLLOFF_FACTOR, rolloffFactor);
AL10.alSourcef(source, AL10.AL_REFERENCE_DISTANCE, 1.0f);
AL10.alSourcef(source, AL10.AL_MAX_DISTANCE, 0.0f);
}
@Override
public void cobblemon$clearFilters() {
AL10.alSourcei(source, EXTEfx.AL_DIRECT_FILTER, 0);
if (EXTEfx.alIsFilter(cobblemon$lowPassFilterId)) {
EXTEfx.alDeleteFilters(cobblemon$lowPassFilterId);
cobblemon$lowPassFilterId = 0;
}
}
}
@@ -36,15 +36,15 @@ public class ClientPacketListenerMixin {
for (int passenger : packet.getPassengers()) {
passengers.add(this.level.getEntity(passenger));
}
Arrays
.stream(pokemon.getOccupiedSeats())
pokemon.getOccupiedSeats().values().stream()
.filter(x -> !passengers.contains(x))
.filter(Objects::nonNull)
.forEach(Entity::stopRiding);
var occupiedSeats = Arrays.asList(pokemon.getOccupiedSeats());
// Mount passengers not yet in the map
var currentPassengers = new ArrayList<>(pokemon.getOccupiedSeats().values());
passengers.stream()
.filter(x -> !occupiedSeats.contains(x))
.filter(x -> !currentPassengers.contains(x))
.filter(Objects::nonNull)
.forEach(x -> x.startRiding(pokemon, true));
ci.cancel();
@@ -0,0 +1,133 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.mixin;
import com.cobblemon.mod.common.mixin.accessor.SinglePoolElementAccessor;
import com.cobblemon.mod.common.world.structureprocessors.HeightRangeStructureProcessor;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Holder;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.levelgen.Heightmap;
import net.minecraft.world.level.levelgen.structure.Structure;
import net.minecraft.world.level.levelgen.structure.pools.*;
import net.minecraft.world.level.levelgen.structure.pools.alias.PoolAliasLookup;
import net.minecraft.world.level.levelgen.structure.templatesystem.LiquidSettings;
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureProcessor;
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureProcessorList;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import java.util.Optional;
@Mixin(JigsawPlacement.class)
public class JigsawPlacementMixin {
@Unique
private static final Logger cobblemon$LOGGER = LoggerFactory.getLogger("Cobblemon/HeightRangeVeto");
@Inject(
method = "addPieces(Lnet/minecraft/world/level/levelgen/structure/Structure$GenerationContext;Lnet/minecraft/core/Holder;Ljava/util/Optional;ILnet/minecraft/core/BlockPos;ZLjava/util/Optional;ILnet/minecraft/world/level/levelgen/structure/pools/alias/PoolAliasLookup;Lnet/minecraft/world/level/levelgen/structure/pools/DimensionPadding;Lnet/minecraft/world/level/levelgen/structure/templatesystem/LiquidSettings;)Ljava/util/Optional;",
at = @At("RETURN"),
cancellable = true
)
private static void onAddPieces(
Structure.GenerationContext context,
Holder<StructureTemplatePool> startPool,
Optional<ResourceLocation> startJigsawName,
int maxDepth,
BlockPos pos,
boolean useExpansionHack,
Optional<Heightmap.Types> projectStartToHeightmap,
int maxDistanceFromCenter,
PoolAliasLookup aliasLookup,
DimensionPadding dimensionPadding,
LiquidSettings liquidSettings,
CallbackInfoReturnable<Optional<Structure.GenerationStub>> cir
) {
Optional<Structure.GenerationStub> result = cir.getReturnValue();
if (result.isEmpty()) {
return;
}
BlockPos spawnPos = result.get().position();
String poolId = startPool.unwrapKey().map(key -> key.location().toString()).orElse("unknown");
boolean canPlace = cobblemon$canStructurePlace(context, startPool, spawnPos);
cobblemon$LOGGER.info(
"[HeightRangeVeto] addPieces evaluated requestedPos={} spawnPos={} startPool={} -> canPlace={}",
pos, spawnPos, poolId, canPlace
);
if (canPlace) {
return;
}
cobblemon$LOGGER.info(
"[HeightRangeVeto] Vetoing structure start at {} (startPool={})",
spawnPos, poolId
);
cir.setReturnValue(Optional.empty());
}
@Unique
private static boolean cobblemon$canStructurePlace(
Structure.GenerationContext generationContext,
Holder<StructureTemplatePool> startPool,
BlockPos startPos
) {
for (StructurePoolElement element : startPool.value().templates) {
Optional<HeightRangeStructureProcessor> heightRangeProcessor = cobblemon$getHeightRangeProcessor(element);
if (heightRangeProcessor.isEmpty()) {
continue;
}
HeightRangeStructureProcessor processor = heightRangeProcessor.get();
boolean valid = processor.isValidPlacement(
generationContext.chunkGenerator(),
generationContext.heightAccessor(),
generationContext.randomState(),
startPos
);
cobblemon$LOGGER.info(
"[HeightRangeVeto] template={} pos={} valid={}",
element, startPos, valid
);
if (!valid) {
return false;
}
}
return true;
}
@Unique
private static Optional<HeightRangeStructureProcessor> cobblemon$getHeightRangeProcessor(StructurePoolElement element) {
if (!(element instanceof SinglePoolElement)) {
return Optional.empty();
}
StructureProcessorList processorList = ((SinglePoolElementAccessor) element).getProcessors().value();
for (StructureProcessor processor : processorList.list()) {
if (processor instanceof HeightRangeStructureProcessor heightRangeStructureProcessor) {
return Optional.of(heightRangeStructureProcessor);
}
}
return Optional.empty();
}
}
@@ -0,0 +1,52 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.mixin;
import com.cobblemon.mod.common.block.entity.DiscShelfBlockEntity;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Holder;
import net.minecraft.sounds.SoundEvent;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.NoteBlock;
import net.minecraft.world.level.block.state.properties.NoteBlockInstrument;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(NoteBlock.class)
public abstract class NoteBlockMixin {
@Inject(method = "triggerEvent", at = @At("HEAD"), cancellable = true)
private void cobblemon$triggerTMShelfSequencer(BlockState state, Level level, BlockPos pos, int type, int data, CallbackInfoReturnable<Boolean> cir) {
final BlockPos shelfPos = pos.below();
final BlockEntity blockEntity = level.getBlockEntity(shelfPos);
if (!(blockEntity instanceof DiscShelfBlockEntity discShelfBlockEntity)) {
return;
}
if (!level.isClientSide) {
final BlockPos instrumentPos = shelfPos.below();
final SoundEvent soundEvent;
if (level.getBlockState(instrumentPos).isAir()) {
soundEvent = SoundEvents.NOTE_BLOCK_BIT.value();
} else {
final NoteBlockInstrument instrument = level.getBlockState(instrumentPos).instrument();
final Holder<SoundEvent> holder = instrument.getSoundEvent();
soundEvent = holder.value();
}
discShelfBlockEntity.onNoteBlockPulse(level, pos, soundEvent);
}
// Suppress vanilla note-block playback while it is on top of a TM Shelf.
cir.setReturnValue(false);
}
}
@@ -19,8 +19,10 @@ import com.cobblemon.mod.common.mixin.accessor.TrackedEntityAccessor;
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.pokemon.update.ClientboundUpdateRidingStatePacket;
import com.cobblemon.mod.common.net.messages.client.pokemon.update.evolution.ClientboundSeatAssignmentPacket;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import net.minecraft.network.protocol.Packet;
import net.minecraft.network.protocol.game.ClientGamePacketListener;
import net.minecraft.server.level.ChunkMap;
import net.minecraft.server.level.ServerEntity;
import net.minecraft.server.level.ServerLevel;
@@ -37,6 +39,7 @@ import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.util.List;
import java.util.Set;
import java.util.function.Consumer;
@@ -53,12 +56,15 @@ public abstract class ServerEntityMixin {
private Matrix3f cobblemon$lastSentOrientation;
@Unique
private boolean cobblemon$lastSentActive;
@Unique
private List<Entity> cobblemon$lastSeatPassengers = List.of();
@Inject(method = "sendChanges", at = @At("TAIL"))
private void cobblemon$sendChanges(CallbackInfo ci) {
cobblemon$sendOrientationChanges();
cobblemon$sendRidingStateChanges();
cobblemon$sendDriverInput();
cobblemon$sendOccupiedSeatsChange();
}
private void cobblemon$sendRidingStateChanges() {
@@ -101,6 +107,24 @@ public abstract class ServerEntityMixin {
cobblemon$broadcast(new ClientboundUpdateDriverInputPacket(driverInput, entity.getId()));
}
private void cobblemon$sendOccupiedSeatsChange() {
if (!(this.entity instanceof PokemonEntity pokemon)) return;
List<Entity> currentPassengers = pokemon.getPassengers();
if (currentPassengers.equals(cobblemon$lastSeatPassengers)) return;
cobblemon$lastSeatPassengers = List.copyOf(currentPassengers);
pokemon.getOccupiedSeats().forEach((seat, passenger) -> {
if (seat.getLocator() == null) return;
if (passenger == null) return;
cobblemon$broadcast(new ClientboundSeatAssignmentPacket(
passenger.getId(),
pokemon.getId(),
seat.getLocator()
));
});
}
private void cobblemon$broadcast(NetworkPacket<?> packet) {
if (!(entity.level() instanceof ServerLevel level)) return;
ChunkMap chunkMap = level.getChunkSource().chunkMap;
@@ -115,5 +139,4 @@ public abstract class ServerEntityMixin {
CobblemonNetwork.INSTANCE.sendPacketToPlayer(player, packet);
}
}
}
@@ -23,6 +23,7 @@ import net.minecraft.client.sounds.ChannelAccess;
import net.minecraft.client.sounds.SoundEngine;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.sounds.SoundSource;
import net.minecraft.util.Mth;
import net.minecraft.world.phys.Vec3;
import org.jetbrains.annotations.Nullable;
import org.spongepowered.asm.mixin.Final;
@@ -32,6 +33,7 @@ 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;
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
import java.util.Iterator;
@@ -108,6 +110,17 @@ public abstract class SoundEngineMixin implements SoundEngineDuck {
}
}
/**
* TM Shelf can intentionally push note-block pitches above vanilla's 2.0f ceiling for octave-up playback.
* Keep vanilla clamping for all other sounds.
*/
@Inject(method = "calculatePitch", at = @At("HEAD"), cancellable = true)
private void cobblemon$allowExtendedNoteblockPitch(SoundInstance sound, CallbackInfoReturnable<Float> cir) {
if (sound.getLocation().getPath().startsWith("block.note_block.")) {
cir.setReturnValue(Mth.clamp(sound.getPitch(), 0.5F, 4.0F));
}
}
/** Different behavior for resuming SoundInstances while a BattleMusicInstance is being played. We do not want to resume filtered sounds. */
@Inject(method = "resume()V", at = @At("HEAD"), cancellable = true)
public void resume(CallbackInfo cb) {
@@ -1,67 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.mixin;
import com.cobblemon.mod.common.world.CobblemonStructureIDs;
import com.llamalad7.mixinextras.sugar.Local;
import net.minecraft.core.Holder;
import net.minecraft.core.RegistryAccess;
import net.minecraft.core.registries.Registries;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.LevelHeightAccessor;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.biome.BiomeSource;
import net.minecraft.world.level.chunk.ChunkGenerator;
import net.minecraft.world.level.levelgen.RandomState;
import net.minecraft.world.level.levelgen.structure.Structure;
import net.minecraft.world.level.levelgen.structure.StructurePiece;
import net.minecraft.world.level.levelgen.structure.StructureStart;
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplateManager;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import java.util.function.Predicate;
@Mixin(Structure.class)
public abstract class StructureMixin {
// Define a set of structures that should not spawn below Sea Level
@Unique
private static final Set<ResourceLocation> RESTRICTED_STRUCTURES = new HashSet<>(Arrays.asList(
CobblemonStructureIDs.STONJOURNER_HENGE,
CobblemonStructureIDs.LUNA_HENGE,
CobblemonStructureIDs.SOL_HENGE
));
@Inject(method = "generate", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/levelgen/structure/StructureStart;isValid()Z"),
cancellable = true)
public void cobblemon$isValid(RegistryAccess registryAccess, ChunkGenerator chunkGenerator, BiomeSource biomeSource,
RandomState randomState, StructureTemplateManager structureTemplateManager, long seed,
ChunkPos chunkPos, int references, LevelHeightAccessor heightAccessor,
Predicate<Holder<Biome>> validBiome,
CallbackInfoReturnable<StructureStart> cir,
@Local StructureStart structureStart) {
ResourceLocation structureKey = registryAccess.registryOrThrow(Registries.STRUCTURE).getKey((Structure) (Object) this);
if(!RESTRICTED_STRUCTURES.contains(structureKey)) {
return;
}
for (StructurePiece piece : structureStart.getPieces()) {
if (piece.getBoundingBox().minY() < chunkGenerator.getSeaLevel()) {
cir.setReturnValue(StructureStart.INVALID_START);
return;
}
}
}
}
@@ -1,23 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.mixin.accessor;
import net.minecraft.client.Camera;
import net.minecraft.world.level.BlockGetter;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
@Mixin(Camera.class)
public interface CameraAccessor {
@Accessor("level")
BlockGetter getLevel();
@Accessor("detached")
void setDetached(boolean detached);
}
@@ -1,23 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.mixin.accessor;
import net.minecraft.client.Camera;
import net.minecraft.client.renderer.GameRenderer;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
@Mixin(GameRenderer.class)
public interface GameRendererAccessor {
@Accessor("mainCamera")
Camera cobblemon$getMainCamera();
@Accessor("mainCamera")
void cobblemon$setMainCamera(Camera camera);
}
@@ -0,0 +1,22 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.mixin.accessor;
import net.minecraft.core.Holder;
import net.minecraft.world.level.levelgen.structure.pools.SinglePoolElement;
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureProcessorList;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
@Mixin(SinglePoolElement.class)
public interface SinglePoolElementAccessor {
@Accessor("processors")
Holder<StructureProcessorList> getProcessors();
}
@@ -1,105 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.mixin.camera;
import java.util.HashSet;
import java.util.Set;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import com.cobblemon.mod.common.api.camera.CameraManager;
import com.cobblemon.mod.common.api.camera.CameraManager.ChunkViewUpdate;
import com.llamalad7.mixinextras.sugar.Local;
import com.mojang.logging.LogUtils;
import net.minecraft.server.level.ChunkMap;
import net.minecraft.server.level.ChunkTrackingView;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.chunk.LevelChunk;
import org.slf4j.Logger;
@Mixin(value = ChunkMap.class, priority = 1100)
public abstract class ChunkMapMixin {
private static final Logger COBBLEMON$CAMERA_LOGGER = LogUtils.getLogger();
@Shadow
protected abstract void markChunkPendingToSend(ServerPlayer player, ChunkPos pos);
@Shadow
private static void markChunkPendingToSend(ServerPlayer player, LevelChunk chunk) {}
@Shadow
private static void dropChunk(ServerPlayer player, ChunkPos chunkPos) {}
@Inject(method = "updateChunkTracking", at = @At("HEAD"))
private void cobblemon$handleCameraChunkUpdates(ServerPlayer player, CallbackInfo ci) {
ChunkViewUpdate update = CameraManager.consumeChunkViewUpdate(player);
if (update != null) {
ChunkTrackingView playerView = player.getChunkTrackingView();
ChunkTrackingView current = update.getCurrent();
ChunkTrackingView previous = update.getPrevious();
if (current != null) {
ChunkTrackingView.difference(playerView, current, chunkPos -> cobblemon$queueChunkForPlayer(player, chunkPos), chunkPos -> {});
}
if (previous != null) {
Set<ChunkPos> droppingChunks = new HashSet<>();
ChunkTrackingView targetComparison = current != null ? current : playerView;
ChunkTrackingView.difference(previous, targetComparison, chunkPos -> {}, droppingChunks::add);
for (ChunkPos chunkPos : droppingChunks) {
if (playerView == null || !playerView.contains(chunkPos)) {
dropChunk(player, chunkPos);
}
}
}
}
}
@Inject(method = "onChunkReadyToSend", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerPlayer;getChunkTrackingView()Lnet/minecraft/server/level/ChunkTrackingView;"))
private void cobblemon$queueCameraChunk(LevelChunk chunk, CallbackInfo ci, @Local ServerPlayer player) {
ChunkTrackingView view = CameraManager.getPlayerChunkView(player);
if (view != null && view.contains(chunk.getPos())) {
markChunkPendingToSend(player, chunk);
}
}
@Inject(method = "isChunkTracked", at = @At("HEAD"), cancellable = true)
private void cobblemon$isCameraChunkTracked(ServerPlayer player, int x, int z, CallbackInfoReturnable<Boolean> cir) {
ChunkTrackingView view = CameraManager.getPlayerChunkView(player);
if (view != null && view.contains(x, z) && !player.connection.chunkSender.isPending(ChunkPos.asLong(x, z))) {
cir.setReturnValue(true);
}
}
@Inject(method = "dropChunk", at = @At("HEAD"), cancellable = true)
private static void cobblemon$preventCameraChunkDrop(ServerPlayer player, ChunkPos pos, CallbackInfo ci) {
ChunkTrackingView view = CameraManager.getPlayerChunkView(player);
if (view != null && view.contains(pos)) {
ci.cancel();
}
}
private void cobblemon$queueChunkForPlayer(ServerPlayer player, ChunkPos chunkPos) {
markChunkPendingToSend(player, chunkPos);
}
}
@@ -1,135 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.mixin.client;
import com.cobblemon.mod.common.client.render.camera.CameraFeedHandler;
import com.cobblemon.mod.common.client.render.camera.CameraViewAreaExtension;
import com.cobblemon.mod.common.client.render.camera.accessor.CameraLevelRendererAccessor;
import com.cobblemon.mod.common.client.util.compat.SodiumCompat;
import com.llamalad7.mixinextras.injector.v2.WrapWithCondition;
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
import net.minecraft.client.Camera;
import net.minecraft.client.Minecraft;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.world.entity.Entity;
import net.minecraft.client.renderer.LevelRenderer;
import net.minecraft.client.renderer.ViewArea;
import net.minecraft.client.renderer.chunk.SectionRenderDispatcher;
import net.minecraft.client.renderer.culling.Frustum;
import net.minecraft.core.BlockPos;
import net.minecraft.core.SectionPos;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.ModifyVariable;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(value = LevelRenderer.class, priority = 1100)
public abstract class CameraLevelRendererMixin implements CameraLevelRendererAccessor {
private static final int CINEMATIC_RENDER_DISTANCE_CHUNKS = 32;
private static final float CINEMATIC_FOG_DISTANCE = CINEMATIC_RENDER_DISTANCE_CHUNKS * 16;
@Shadow
@Final
private Minecraft minecraft;
@Shadow
private SectionRenderDispatcher sectionRenderDispatcher;
@Shadow
private ClientLevel level;
@Shadow private Frustum capturedFrustum;
@Shadow public Frustum cullingFrustum;
@WrapWithCondition(method = "setupRender", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/ViewArea;repositionCamera(DD)V"))
private boolean cobblemon$shouldRepositionCamera(ViewArea viewArea, double x, double z) {
return !CameraFeedHandler.isCapturing();
}
/**
* Cancel vanilla setupRender during feed capture to avoid overwriting
* the camera feed's visible sections. When Sodium is active, let it
* proceed since Sodium manages its own chunk rendering pipeline and
* needs setupRender to run.
*/
@Inject(method = "setupRender", at = @At("HEAD"), cancellable = true)
private void cobblemon$onSetupRender(Camera camera, Frustum frustum, boolean hasCapturedFrustum, boolean isSpectator, CallbackInfo ci) {
if (CameraFeedHandler.isCapturing() && !SodiumCompat.getInstance().isActive())
ci.cancel();
}
@Inject(method = "allChanged", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/SectionOcclusionGraph;waitAndReset(Lnet/minecraft/client/renderer/ViewArea;)V"))
private void cobblemon$onAllChanged(CallbackInfo ci) {
CameraViewAreaExtension.allChanged(sectionRenderDispatcher, level);
}
@Inject(method = "isSectionCompiled", at = @At("HEAD"), cancellable = true)
private void cobblemon$onIsSectionCompiled(BlockPos pos, CallbackInfoReturnable<Boolean> cir) {
if (CameraFeedHandler.isCapturing()) {
SectionPos sectionPos = SectionPos.of(pos);
SectionRenderDispatcher.RenderSection section = CameraViewAreaExtension.rawFetch(sectionPos.x(), sectionPos.y(), sectionPos.z(), false);
if (section != null && section.getCompiled() != SectionRenderDispatcher.CompiledSection.UNCOMPILED) {
cir.setReturnValue(true);
}
}
}
@ModifyVariable(method = "renderLevel", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/FogRenderer;setupColor(Lnet/minecraft/client/Camera;FLnet/minecraft/client/multiplayer/ClientLevel;IF)V"), ordinal = 1)
private float cobblemon$modifyFogRenderDistance(float original) {
if (CameraFeedHandler.isCapturing())
return CINEMATIC_FOG_DISTANCE;
return original;
}
/**
* During feed capture the camera entity is a Marker, which causes the vanilla condition
* {@code !(entity instanceof LocalPlayer) || camera.getEntity() == entity} to fail for
* the local player — preventing them from rendering.
*
* By returning the local player from {@code getEntity()} and {@code true} from
* {@code isDetached()}, both condition2 and condition3 in the entity rendering check pass:
* <ul>
* <li>condition2: {@code entity != player || isDetached()==true} → passes</li>
* <li>condition3: {@code player == player} → passes</li>
* </ul>
*/
@WrapOperation(
method = "renderLevel",
at = @At(value = "INVOKE", target = "Lnet/minecraft/client/Camera;getEntity()Lnet/minecraft/world/entity/Entity;")
)
private Entity cobblemon$getCameraEntityDuringCapture(Camera camera, Operation<Entity> original) {
if (CameraFeedHandler.isCapturing()) {
Entity player = Minecraft.getInstance().player;
if (player != null) return player;
}
return original.call(camera);
}
@WrapOperation(
method = "renderLevel",
at = @At(value = "INVOKE", target = "Lnet/minecraft/client/Camera;isDetached()Z")
)
private boolean cobblemon$isCameraDetachedDuringCapture(Camera camera, Operation<Boolean> original) {
if (CameraFeedHandler.isCapturing()) {
return true;
}
return original.call(camera);
}
@Override
public Frustum cobblemonGetFrustum() {
return this.capturedFrustum != null ? this.capturedFrustum : this.cullingFrustum;
}
}
@@ -8,32 +8,22 @@
package com.cobblemon.mod.common.mixin.client;
import com.cobblemon.mod.common.Cobblemon;
import com.cobblemon.mod.common.OrientationControllable;
import com.cobblemon.mod.common.api.camera.CameraRotation;
import com.cobblemon.mod.common.api.orientation.OrientationController;
import com.cobblemon.mod.common.api.riding.Rideable;
import com.cobblemon.mod.common.client.MountedPokemonAnimationRenderController;
import com.cobblemon.mod.common.client.camera.ClientCameraController;
import com.cobblemon.mod.common.client.render.camera.CameraFeedHandler;
import com.cobblemon.mod.common.client.render.camera.MountedCameraRenderer;
import com.cobblemon.mod.common.duck.CameraDuck;
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
import com.llamalad7.mixinextras.sugar.Local;
import net.minecraft.client.Camera;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.LevelRenderer;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.phys.Vec3;
import org.joml.Quaternionf;
import org.joml.Vector3f;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
@Mixin(Camera.class)
@@ -42,7 +32,6 @@ public abstract class CameraMixin implements CameraDuck {
@Shadow private float eyeHeightOld;
@Shadow private BlockGetter level;
@Shadow private Entity entity;
@Final @Shadow private Quaternionf rotation;
@Final @Shadow private Vector3f forwards;
@Final @Shadow private Vector3f up;
@Final @Shadow private Vector3f left;
@@ -54,11 +43,6 @@ public abstract class CameraMixin implements CameraDuck {
@Override public BlockGetter cobblemon$getLevel() {
return level;
}
@Shadow protected abstract void setRotation(float yRot, float xRot);
@Unique private float returnTimer = 0;
@Unique private float rollAngleStart = 0;
@Unique Minecraft minecraft = Minecraft.getInstance();
@Override public Entity cobblemon$getEntity() {
return entity;
@@ -82,28 +66,6 @@ public abstract class CameraMixin implements CameraDuck {
Entity vehicle = entity.getVehicle();
MountedPokemonAnimationRenderController.INSTANCE.reset();
// Check for cinematic camera override
if (ClientCameraController.isActive()) {
// When capturing a feed, use that specific camera's transform
// instead of the primary camera to avoid both feeds sharing the same position.
java.util.UUID capturedId = CameraFeedHandler.getCurrentlyCapturedCamera();
ClientCameraController.ActiveTransform cameraTransform = capturedId != null
? ClientCameraController.getActiveCameraTransform(capturedId)
: ClientCameraController.getCameraTransform();
if (cameraTransform != null) {
Vec3 position = cameraTransform.getPosition();
CameraRotation rotation = cameraTransform.getRotation();
setPosition(new Vec3(position.x, position.y, position.z));
setRotation(rotation.getYaw(), rotation.getPitch());
OrientationController.Companion.getFORWARDS().rotate(this.rotation, this.forwards);
OrientationController.Companion.getUP().rotate(this.rotation, this.up);
OrientationController.Companion.getLEFT().rotate(this.rotation, this.left);
return;
}
}
if(vehicle instanceof Rideable){
Vec3 position = MountedCameraRenderer.INSTANCE.getCameraPosition(
instance,
@@ -0,0 +1,123 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.mixin.client;
import com.cobblemon.mod.common.duck.ChannelDuck;
import com.mojang.blaze3d.audio.Channel;
import org.lwjgl.openal.AL10;
import org.lwjgl.openal.AL11;
import org.lwjgl.openal.EXTEfx;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
@Mixin(Channel.class)
public abstract class ChannelMixin implements ChannelDuck {
@Shadow
private int source;
// Ids of effects applied to the channel
private int cobblemon$lowPassFilterId = 0;
private int cobblemon$reverbEffectId = 0;
private int cobblemon$reverbSlotId = 0;
@Override
public void cobblemon$applyLowPassFilter(float gain, float hfGain) {
// Delete old filter if it exists
if (cobblemon$lowPassFilterId != 0) {
AL10.alSourcei(source, EXTEfx.AL_DIRECT_FILTER, 0); // Detach filter from source
EXTEfx.alDeleteFilters(cobblemon$lowPassFilterId); // Delete old filter
cobblemon$lowPassFilterId = 0;
}
// Generate a fresh filter
int filterId = EXTEfx.alGenFilters();
if (!EXTEfx.alIsFilter(filterId)) {
System.err.println("Failed to create OpenAL low-pass filter");
return;
}
EXTEfx.alFilteri(filterId, EXTEfx.AL_FILTER_TYPE, EXTEfx.AL_FILTER_LOWPASS);
EXTEfx.alFilterf(filterId, EXTEfx.AL_LOWPASS_GAIN, gain);
EXTEfx.alFilterf(filterId, EXTEfx.AL_LOWPASS_GAINHF, hfGain);
AL10.alSourcei(source, EXTEfx.AL_DIRECT_FILTER, filterId);
// Save the new filter ID
cobblemon$lowPassFilterId = filterId;
}
@Override
public void cobblemon$inverseAttenuation(float rolloffFactor) {
AL10.alSourcei(source, AL10.AL_DISTANCE_MODEL, AL10.AL_INVERSE_DISTANCE);
AL10.alSourcef(source, AL10.AL_ROLLOFF_FACTOR, rolloffFactor);
AL10.alSourcef(source, AL10.AL_REFERENCE_DISTANCE, 1.0f);
AL10.alSourcef(source, AL10.AL_MAX_DISTANCE, 0.0f);
}
@Override
public void cobblemon$clearFilters() {
AL10.alSourcei(source, EXTEfx.AL_DIRECT_FILTER, 0);
if (EXTEfx.alIsFilter(cobblemon$lowPassFilterId)) {
EXTEfx.alDeleteFilters(cobblemon$lowPassFilterId);
cobblemon$lowPassFilterId = 0;
}
}
@Override
public void cobblemon$applyReverb(float decayTime, float gain, float diffusion, float density) {
// Clean up existing reverb first if it exists
cobblemon$clearReverb();
// Create the effect object
int effectId = EXTEfx.alGenEffects();
if (!EXTEfx.alIsEffect(effectId)) {
System.err.println("Failed to create OpenAL reverb effect");
return;
}
EXTEfx.alEffecti(effectId, EXTEfx.AL_EFFECT_TYPE, EXTEfx.AL_EFFECT_REVERB);
EXTEfx.alEffectf(effectId, EXTEfx.AL_REVERB_DECAY_TIME, decayTime);
EXTEfx.alEffectf(effectId, EXTEfx.AL_REVERB_GAIN, gain);
EXTEfx.alEffectf(effectId, EXTEfx.AL_REVERB_DIFFUSION, diffusion);
EXTEfx.alEffectf(effectId, EXTEfx.AL_REVERB_DENSITY, density);
// Create auxiliary effect slot and load effect into it
int slotId = EXTEfx.alGenAuxiliaryEffectSlots();
if (!EXTEfx.alIsAuxiliaryEffectSlot(slotId)) {
System.err.println("Failed to create OpenAL auxiliary effect slot");
EXTEfx.alDeleteEffects(effectId);
return;
}
EXTEfx.alAuxiliaryEffectSloti(slotId, EXTEfx.AL_EFFECTSLOT_EFFECT, effectId);
// Route source through the slot — send 0, no direct filter
AL11.alSource3i(source, EXTEfx.AL_AUXILIARY_SEND_FILTER, slotId, 0, EXTEfx.AL_FILTER_NULL);
cobblemon$reverbEffectId = effectId;
cobblemon$reverbSlotId = slotId;
}
@Override
public void cobblemon$clearReverb() {
if (cobblemon$reverbSlotId != 0) {
// Detach source from slot
AL11.alSource3i(source, EXTEfx.AL_AUXILIARY_SEND_FILTER,
EXTEfx.AL_EFFECTSLOT_NULL, 0, EXTEfx.AL_FILTER_NULL);
EXTEfx.alDeleteAuxiliaryEffectSlots(cobblemon$reverbSlotId);
cobblemon$reverbSlotId = 0;
}
if (cobblemon$reverbEffectId != 0) {
EXTEfx.alDeleteEffects(cobblemon$reverbEffectId);
cobblemon$reverbEffectId = 0;
}
}
}
@@ -1,83 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.mixin.client;
import com.cobblemon.mod.common.client.camera.CameraClientChunkCacheExtension;
import com.cobblemon.mod.common.client.camera.CameraChunkVisibilityManager;
import com.cobblemon.mod.common.client.render.camera.CameraFeedHandler;
import net.minecraft.client.Minecraft;
import net.minecraft.client.multiplayer.ClientChunkCache;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.network.protocol.game.ClientboundLevelChunkPacketData;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.chunk.LevelChunk;
import net.minecraft.world.level.chunk.status.ChunkStatus;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import java.util.function.Consumer;
@Mixin(value = ClientChunkCache.class, priority = 1100)
public abstract class ClientChunkCacheMixin {
@Shadow
volatile ClientChunkCache.Storage storage;
@Shadow
@Final
ClientLevel level;
/**
* Intercept updateViewCenter to use camera position when active.
*/
@Inject(method = "drop", at = @At("HEAD"))
private void cobblemon$onDrop(ChunkPos chunkPos, CallbackInfo ci) {
int renderDistance = Minecraft.getInstance().options.renderDistance().get();
if (CameraChunkVisibilityManager.shouldKeepChunk(chunkPos, renderDistance)
|| CameraFeedHandler.shouldAddChunk(chunkPos, renderDistance)) {
return;
}
CameraClientChunkCacheExtension.drop(level, chunkPos);
}
/**
* Override replaceWithPacketData to accept chunks based on camera position.
*/
@Inject(method = "replaceWithPacketData", at = @At("HEAD"), cancellable = true)
public void cobblemon$onReplaceWithPacketData(int x, int z, FriendlyByteBuf buffer, CompoundTag chunkTag, Consumer<ClientboundLevelChunkPacketData.BlockEntityTagOutput> tagOutputConsumer, CallbackInfoReturnable<LevelChunk> cir) {
int renderDistance = Minecraft.getInstance().options.renderDistance().get();
ChunkPos chunkPos = new ChunkPos(x, z);
boolean isInPlayerRange = storage.inRange(x, z);
boolean shouldAddChunk = CameraChunkVisibilityManager.shouldKeepChunk(chunkPos, renderDistance)
|| CameraFeedHandler.shouldAddChunk(chunkPos, renderDistance);
if (shouldAddChunk) {
LevelChunk newChunk = CameraClientChunkCacheExtension.replaceWithPacketData(level, x, z, new FriendlyByteBuf(buffer.copy()), chunkTag, tagOutputConsumer);
if (!isInPlayerRange)
cir.setReturnValue(newChunk);
}
}
@Inject(method = "getChunk(IILnet/minecraft/world/level/chunk/status/ChunkStatus;Z)Lnet/minecraft/world/level/chunk/LevelChunk;", at = @At("TAIL"), cancellable = true)
private void cobblemon$onGetChunk(int x, int z, ChunkStatus chunkStatus, boolean requireChunk, CallbackInfoReturnable<LevelChunk> cir) {
if (!storage.inRange(x, z)) {
LevelChunk chunk = CameraClientChunkCacheExtension.getChunk(x, z);
if (chunk != null)
cir.setReturnValue(chunk);
}
}
}
@@ -9,122 +9,43 @@
package com.cobblemon.mod.common.mixin.client;
import com.cobblemon.mod.common.api.scheduling.ClientTaskTracker;
import com.cobblemon.mod.common.api.tween.TweenManager;
import com.cobblemon.mod.common.client.camera.GameCamera;
import com.cobblemon.mod.common.client.camera.ClientCameraController;
import com.cobblemon.mod.common.client.render.camera.CameraFeedHandler;
import com.cobblemon.mod.common.client.render.camera.compositor.CompositorManager;
import net.minecraft.client.Camera;
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity;
import com.llamalad7.mixinextras.sugar.Local;
import net.minecraft.client.DeltaTracker;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.GameRenderer;
import net.minecraft.world.entity.Entity;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Mutable;
import org.spongepowered.asm.mixin.Shadow;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.BlockGetter;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.ModifyArg;
import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.util.function.Predicate;
@Mixin(GameRenderer.class)
public abstract class GameRendererMixin {
@Shadow @Final @Mutable
private Camera mainCamera;
public class GameRendererMixin {
@Unique
private Camera cobblemon$playerCamera;
long lastTime = -1;
@Unique
private final GameCamera cobblemon$gameCamera = new GameCamera();
@Unique
private boolean cobblemon$usingCinematic;
@Unique
private long cobblemon$lastTime = -1;
@Inject(method = "render", at = @At("HEAD"))
private void cobblemon$swapCamera(DeltaTracker counter, boolean tick, CallbackInfo ci) {
@Inject(
method = "render",
at = @At(value = "TAIL")
)
public void render(DeltaTracker counter, boolean tick, CallbackInfo ci) {
Minecraft client = Minecraft.getInstance();
if (client.level == null) {
cobblemon$restoreCamera();
return;
}
if (ClientCameraController.shouldUseCinematicCamera()) {
if (!cobblemon$usingCinematic) {
cobblemon$playerCamera = mainCamera;
mainCamera = cobblemon$gameCamera;
cobblemon$usingCinematic = true;
}
ClientCameraController.prepareCinematicCamera(client, counter.getGameTimeDeltaPartialTick(tick));
} else if (cobblemon$usingCinematic) {
cobblemon$restoreCamera();
}
}
/**
* Skip the vanilla renderLevel() call when a fullscreen compositor is active since
* the compositor covers the entire screen with camera feeds.
* This avoids a full wasted scene render every frame.
*/
@Redirect(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/GameRenderer;renderLevel(Lnet/minecraft/client/DeltaTracker;)V"))
private void cobblemon$skipVanillaRenderLevel(GameRenderer instance, DeltaTracker deltaTracker) {
if (!CompositorManager.isFullscreenActive()) {
instance.renderLevel(deltaTracker);
}
}
@Inject(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/GameRenderer;tryTakeScreenshotIfNeeded()V"))
private void cobblemon$afterLevelRendering(DeltaTracker deltaTracker, boolean renderLevel, CallbackInfo ci) {
// Only capture feeds when a compositor is actively consuming them.
// This avoids expensive full-resolution renders (especially with Iris)
// when feeds aren't being displayed.
boolean compositorNeedsFeeds = CompositorManager.isFullscreenActive()
|| !CompositorManager.INSTANCE.getRequiredFeeds().isEmpty();
if (compositorNeedsFeeds && CameraFeedHandler.hasFeeds()) {
CameraFeedHandler.captureFeeds(deltaTracker);
}
if (CompositorManager.isFullscreenActive()) {
CompositorManager.INSTANCE.compositeAll();
CompositorManager.renderFullscreen();
}
}
@Inject(method = "pick", at = @At("HEAD"), cancellable = true)
private void cobblemon$preventFramePick(float partialTicks, CallbackInfo ci) {
if (CameraFeedHandler.isCapturing())
ci.cancel();
}
@Inject(method = "render", at = @At(value = "TAIL"))
private void cobblemon$afterRender(DeltaTracker counter, boolean tick, CallbackInfo ci) {
Minecraft client = Minecraft.getInstance();
long newTime = System.currentTimeMillis();
// Don't play scheduled animations when the game is paused
if (client.isPaused()) {
cobblemon$lastTime = newTime;
lastTime = newTime;
return;
}
if (cobblemon$lastTime != -1) {
float delta = (newTime - cobblemon$lastTime) / 1000F;
ClientTaskTracker.INSTANCE.update(delta);
TweenManager.Companion.getClient().update(delta);
if (lastTime != -1) {
ClientTaskTracker.INSTANCE.update((newTime - lastTime) / 1000F);
}
cobblemon$lastTime = newTime;
lastTime = newTime;
}
@ModifyArg(
@@ -139,12 +60,4 @@ public abstract class GameRendererMixin {
return (entityX) -> !(entity.getVehicle() == entityX && entityX instanceof PokemonEntity) && original.test(entityX);
}
@Unique
private void cobblemon$restoreCamera() {
if (cobblemon$usingCinematic) {
mainCamera = cobblemon$playerCamera;
cobblemon$playerCamera = null;
cobblemon$usingCinematic = false;
}
}
}
@@ -9,7 +9,6 @@
package com.cobblemon.mod.common.mixin.client;
import com.cobblemon.mod.common.OrientationControllable;
import com.cobblemon.mod.common.client.camera.ClientCameraController;
import com.cobblemon.mod.common.item.PokedexItem;
import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.client.Minecraft;
@@ -29,12 +28,6 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
public class ItemInHandRendererMixin {
@Inject(method = "renderArmWithItem", at = @At(value = "HEAD"), cancellable = true)
private void cobblemon$renderArmWithItem(AbstractClientPlayer abstractClientPlayer, float f, float g, InteractionHand interactionHand, float h, ItemStack itemStack, float i, PoseStack poseStack, MultiBufferSource multiBufferSource, int j, CallbackInfo ci) {
// Hide arms when cinematic camera is active
if (ClientCameraController.isActive()) {
ci.cancel();
return;
}
if (abstractClientPlayer.isUsingItem() && abstractClientPlayer.getUseItem().getItem() instanceof PokedexItem) {
ci.cancel();
}
@@ -9,10 +9,13 @@
package com.cobblemon.mod.common.mixin.client;
import com.cobblemon.mod.common.Cobblemon;
import com.cobblemon.mod.common.CobblemonItemComponents;
import com.cobblemon.mod.common.CobblemonItems;
import com.cobblemon.mod.common.ModAPI;
import com.cobblemon.mod.common.item.PokeBallItem;
import com.cobblemon.mod.common.item.PokedexItem;
import com.cobblemon.mod.common.item.WearableItem;
import com.cobblemon.mod.common.item.components.TMMoveComponent;
import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.client.renderer.ItemModelShaper;
@@ -54,11 +57,17 @@ public abstract class ItemRendererMixin {
cancellable = true
)
private void cobblemon$overrideItemModel(ItemStack stack, ItemDisplayContext renderMode, boolean leftHanded, PoseStack matrices, MultiBufferSource multiBufferSource, int light, int overlay, BakedModel model, CallbackInfo ci) {
boolean shouldBe2d = renderMode == ItemDisplayContext.GUI || renderMode == ItemDisplayContext.FIXED;
boolean shouldBe2d = renderMode == ItemDisplayContext.GUI || renderMode == ItemDisplayContext.FIXED || stack.getItem() == CobblemonItems.TECHNICAL_MACHINE;
ResourceLocation resourceLocation = null;
if (shouldBe2d) {
if (stack.getItem() instanceof PokeBallItem pokeBallItem) resourceLocation = pokeBallItem.getPokeBall().getModel2d();
else if (stack.getItem() instanceof PokedexItem pokedexItem) resourceLocation = pokedexItem.getType().getItemSpritePath();
else if (stack.getItem() == CobblemonItems.TECHNICAL_MACHINE) {
TMMoveComponent component = stack.get(CobblemonItemComponents.TM_MOVE);
if (component != null) {
resourceLocation = new ResourceLocation(Cobblemon.MODID, "tm/" + component.getMove().getElementalType().showdownId() + "_tm");
}
}
}
if (renderMode != ItemDisplayContext.HEAD && stack.getItem() instanceof WearableItem wearableItem) resourceLocation = wearableItem.getModel2d();
@@ -23,6 +23,7 @@ import com.cobblemon.mod.common.duck.RidePassenger;
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity;
import com.cobblemon.mod.common.net.messages.server.orientation.ServerboundUpdateOrientationPacket;
import com.cobblemon.mod.common.net.messages.server.riding.ServerboundUpdateDriverInputPacket;
import com.cobblemon.mod.common.net.messages.server.riding.ServerboundUpdatePassengerPositionPacket;
import com.cobblemon.mod.common.net.messages.server.riding.ServerboundUpdateRiderRotationPacket;
import com.mojang.authlib.GameProfile;
import net.minecraft.client.CameraType;
@@ -148,10 +149,22 @@ public abstract class LocalPlayerMixin extends AbstractClientPlayer implements O
cobblemon$lastRideYRot = rideYRot;
cobblemon$lastRideEyePos = rideEyePos;
CobblemonNetwork.INSTANCE.sendToServer(new ServerboundUpdateRiderRotationPacket(rideXRot, rideYRot, rideEyePos));
CobblemonNetwork.INSTANCE.sendToServer(
new ServerboundUpdateRiderRotationPacket(rideXRot, rideYRot, rideEyePos)
);
}
}
@Inject(method = "rideTick", at = @At("TAIL"))
private void cobblemon$updatePassengerPosition(CallbackInfo ci) {
if (Minecraft.getInstance().player != (Object)this) return;
if (!(this.getVehicle() instanceof PokemonEntity pokemonEntity)) return;
if (pokemonEntity.getSeatForPassenger(this) == null) return;
var offset = this.position().subtract(pokemonEntity.position());
CobblemonNetwork.INSTANCE.sendToServer(
new ServerboundUpdatePassengerPositionPacket(this.getId(), offset)
);
}
@Unique
@@ -217,9 +230,10 @@ public abstract class LocalPlayerMixin extends AbstractClientPlayer implements O
private void cobblemon$isHandsBusy(CallbackInfoReturnable<Boolean> cir) {
Entity vehicle = this.getVehicle();
if (vehicle instanceof PokemonEntity pokemonEntity) {
int seatIndex = pokemonEntity.getPassengers().indexOf(this);
Seat seat = pokemonEntity.getSeats().get(seatIndex);
cir.setReturnValue(seat.getHandsBusy());
Seat seat = pokemonEntity.getSeatForPassenger(this);;
if (seat != null) {
cir.setReturnValue(seat.getHandsBusy());
}
}
}
@@ -9,8 +9,7 @@
package com.cobblemon.mod.common.mixin.client;
import com.cobblemon.mod.common.client.CobblemonBakingOverrides;
import java.util.List;
import java.util.Map;
import net.minecraft.client.Minecraft;
import net.minecraft.client.color.block.BlockColors;
import net.minecraft.client.renderer.block.model.BlockModel;
import net.minecraft.client.resources.model.BlockStateModelLoader;
@@ -18,29 +17,76 @@ import net.minecraft.client.resources.model.ModelBakery;
import net.minecraft.client.resources.model.ModelResourceLocation;
import net.minecraft.client.resources.model.UnbakedModel;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.packs.resources.Resource;
import net.minecraft.util.profiling.ProfilerFiller;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
@Mixin(ModelBakery.class)
public abstract class ModelLoaderMixin {
@Shadow abstract UnbakedModel getModel(ResourceLocation resourceLocation);
@Shadow protected abstract void registerModel(ModelResourceLocation modelId, UnbakedModel unbakedModel);
@Shadow protected abstract void loadItemModelAndDependencies(ResourceLocation resourceLocation);
@Unique
List<String> dynamicFolders = Arrays.asList("egg", "tm");
@Inject(
method = "<init>",
at = @At("TAIL")
method = "<init>",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/util/profiling/ProfilerFiller;popPush(Ljava/lang/String;)V",
ordinal = 1
)
)
public void loadCustomItemModels(BlockColors blockColors,
ProfilerFiller profiler,
Map<ResourceLocation, BlockModel> jsonUnbakedModels,
Map<ResourceLocation, List<BlockStateModelLoader.LoadedJson>> blockStates,
CallbackInfo ci
) {
/*
* The models/item/*.json's only get loaded if there's an item in the registry that actually asks for it. It
* naively looks for things in the root with an item ID and calls upon it, and some of those JSONs reference
* other model JSONs and so it cascades a little bit. Used for block models but more importantly here, sprites.
*
* The thing about the eggs (and TMs) is, we really want the eggs to be addon-compatible in a way that doesn't restrict
* the species that can have eggs, so we can't pre-plan all of them. This mixin looks for the things inside the
* egg subfolder (which won't get loaded automagically) and manually inserts them into the unbaked model list so
* Minecraft loads them for us. We'll then dynamically call these models from the ItemRendererMixin; so it's
* hacky at the init stage and hacky at the render stage. Pretty cool in the gameplay stage though.
*
* - Hiro
*/
dynamicFolders.forEach(folder -> {
Map<ResourceLocation, Resource> map = Minecraft.getInstance().getResourceManager().listResources("models/item/" + folder, (t) -> true);
map.forEach((key, value) -> {
ResourceLocation resourceLocation = new ResourceLocation(key.getNamespace(), key.getPath().replace("models/item/", "").replace(".json", ""));
this.loadItemModelAndDependencies(resourceLocation);
});
});
}
@Inject(
method = "<init>",
at = @At("TAIL")
)
public void init(BlockColors blockColors,
ProfilerFiller profiler,
Map<ResourceLocation, BlockModel> jsonUnbakedModels,
Map<ResourceLocation, List<BlockStateModelLoader.LoadedJson>> blockStates,
CallbackInfo ci) {
ProfilerFiller profiler,
Map<ResourceLocation, BlockModel> jsonUnbakedModels,
Map<ResourceLocation, List<BlockStateModelLoader.LoadedJson>> blockStates,
CallbackInfo ci) {
CobblemonBakingOverrides.INSTANCE.getModels().forEach(bakingOverride -> {
var unbakedModel = this.getModel(bakingOverride.getModelLocation());
this.registerModel(bakingOverride.getModelIdentifier(), unbakedModel);
@@ -8,14 +8,11 @@
package com.cobblemon.mod.common.mixin.client;
import com.cobblemon.mod.common.client.camera.ClientCameraController;
import com.cobblemon.mod.common.client.render.ClientPlayerIcon;
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity;
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.client.CameraType;
import net.minecraft.client.Minecraft;
import net.minecraft.client.model.PlayerModel;
import net.minecraft.client.player.AbstractClientPlayer;
import net.minecraft.client.renderer.MultiBufferSource;
@@ -25,7 +22,6 @@ import net.minecraft.client.renderer.entity.player.PlayerRenderer;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(PlayerRenderer.class)
@@ -35,27 +31,6 @@ public abstract class PlayerRendererMixin extends LivingEntityRenderer<AbstractC
super(context, model, shadowRadius);
}
/**
* Override the camera type check to force player body rendering when cinematic camera is active.
* This makes Minecraft think we're not in first person mode (for rendering purposes only),
* so the local player's body is rendered even though the camera entity is still the player.
*/
@Redirect(
method = "render(Lnet/minecraft/client/player/AbstractClientPlayer;FFLcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;I)V",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/client/CameraType;isFirstPerson()Z"
)
)
private boolean cobblemon$allowBodyRenderInCinematic(CameraType instance) {
// When cinematic camera is active and configured to show player body,
// pretend we're not in first person so the player body renders
if (ClientCameraController.isActive() && ClientCameraController.shouldRenderPlayerBody()) {
return false;
}
return instance.isFirstPerson();
}
@Inject(method = "render", at = @At(value = "TAIL"))
public void renderPlayer(AbstractClientPlayer player, float f, float g, PoseStack poseStack, MultiBufferSource multiBufferSource, int i, CallbackInfo ci) {
ClientPlayerIcon.Companion.onRenderPlayer(player);
@@ -1,25 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.mixin.client;
import com.cobblemon.mod.common.client.render.camera.CameraViewAreaExtension;
import net.minecraft.client.renderer.ViewArea;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(ViewArea.class)
public class ViewAreaMixin {
@Inject(method = "setDirty", at = @At("HEAD"))
private void cobblemon$markCinematicDirty(int cx, int cy, int cz, boolean reRenderOnMainThread, CallbackInfo ci) {
CameraViewAreaExtension.setDirty(cx, cy, cz, reRenderOnMainThread);
}
}
@@ -1,21 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.mixin.invoker;
import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen;
import net.minecraft.world.inventory.Slot;
import org.jetbrains.annotations.Nullable;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Invoker;
@Mixin(AbstractContainerScreen.class)
public interface AbstractContainerScreenInvoker {
@Invoker("findSlot")
@Nullable Slot callFindSlot(double mouseX, double mouseY);
}
@@ -18,6 +18,7 @@ import com.cobblemon.mod.common.api.drop.EvolutionItemDropEntry
import com.cobblemon.mod.common.api.drop.ItemDropEntry
import com.cobblemon.mod.common.api.events.CobblemonEvents
import com.cobblemon.mod.common.api.events.CobblemonEvents.DATA_SYNCHRONIZED
import com.cobblemon.mod.common.api.habitats.HabitatPools
import com.cobblemon.mod.common.api.interaction.RequestManager
import com.cobblemon.mod.common.api.molang.MoLangLoadedFilesCache
import com.cobblemon.mod.common.api.molang.ObjectValue
@@ -33,6 +34,7 @@ import com.cobblemon.mod.common.api.pokemon.feature.ChoiceSpeciesFeatureProvider
import com.cobblemon.mod.common.api.pokemon.feature.FlagSpeciesFeatureProvider
import com.cobblemon.mod.common.api.pokemon.feature.IntSpeciesFeatureProvider
import com.cobblemon.mod.common.api.pokemon.feature.SpeciesFeatures
import com.cobblemon.mod.common.api.pokemon.feature.WeightedChoiceSpeciesFeatureProvider
import com.cobblemon.mod.common.api.pokemon.helditem.HeldItemProvider
import com.cobblemon.mod.common.api.pokemon.stats.EvCalculator
import com.cobblemon.mod.common.api.pokemon.stats.Generation8EvCalculator
@@ -62,6 +64,8 @@ import com.cobblemon.mod.common.api.storage.player.adapter.DexDataMongoBackend
import com.cobblemon.mod.common.api.storage.player.adapter.DexDataNbtBackend
import com.cobblemon.mod.common.api.storage.player.adapter.PlayerDataJsonBackend
import com.cobblemon.mod.common.api.storage.player.adapter.PlayerDataMongoBackend
import com.cobblemon.mod.common.api.storage.player.adapter.TMMoveMongoBackend
import com.cobblemon.mod.common.api.storage.player.adapter.TMMoveNbtBackend
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
@@ -72,11 +76,8 @@ 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.api.camera.track.CameraTrackDeserializers
import com.cobblemon.mod.common.block.dispenser.DispenserBehaviorRegistry
import com.cobblemon.mod.common.client.CobblemonPack
import com.cobblemon.mod.common.api.tween.EasingRegistry
import com.cobblemon.mod.common.api.tween.TweenManager
import com.cobblemon.mod.common.command.argument.*
import com.cobblemon.mod.common.config.CobblemonConfig
import com.cobblemon.mod.common.config.LastChangedVersion
@@ -93,9 +94,11 @@ import com.cobblemon.mod.common.net.messages.client.settings.ServerSettingsPacke
import com.cobblemon.mod.common.permission.LaxPermissionValidator
import com.cobblemon.mod.common.platform.events.PlatformEvents
import com.cobblemon.mod.common.pokemon.Pokemon
import com.cobblemon.mod.common.pokemon.aspects.ALPHA_ASPECT
import com.cobblemon.mod.common.pokemon.aspects.CHARACTERISTIC_RAINBOW_ASPECT
import com.cobblemon.mod.common.pokemon.aspects.COSMETIC_SLOT_ASPECT
import com.cobblemon.mod.common.pokemon.aspects.GENDER_ASPECT
import com.cobblemon.mod.common.pokemon.aspects.MARK_ASPECT
import com.cobblemon.mod.common.pokemon.aspects.SHINY_ASPECT
import com.cobblemon.mod.common.pokemon.evolution.variants.BlockClickEvolution
import com.cobblemon.mod.common.pokemon.feature.SlowpokeTailRegrowthSpeciesFeature
@@ -105,6 +108,7 @@ import com.cobblemon.mod.common.pokemon.helditem.CobblemonHeldItemManager
import com.cobblemon.mod.common.pokemon.properties.AspectPropertyType
import com.cobblemon.mod.common.pokemon.properties.BattleCloneProperty
import com.cobblemon.mod.common.pokemon.properties.FreezeFrameProperty
import com.cobblemon.mod.common.pokemon.properties.HeldItemVisibleProperty
import com.cobblemon.mod.common.pokemon.properties.HiddenAbilityPropertyType
import com.cobblemon.mod.common.pokemon.properties.LabelProperty
import com.cobblemon.mod.common.pokemon.properties.NoAIProperty
@@ -112,13 +116,7 @@ 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.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.util.*
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
@@ -247,6 +245,8 @@ object Cobblemon {
DATA_SYNCHRONIZED.subscribe {
storage.onPlayerDataSync(it)
it.tmList().scheduleFullSyncFromStores(it.party(), it.pc())
it.pokedex().scheduleFullSyncFromStores(it.party(), it.pc())
playerDataManager.syncAllToPlayer(it)
starterHandler.handleJoin(it)
it.requestWallpapers()
@@ -259,7 +259,6 @@ object Cobblemon {
playerDataManager.onPlayerDisconnect(it.player)
RequestManager.onLogoff(it.player)
serverPlayerStructs.remove(it.player.uuid)
com.cobblemon.mod.common.api.molangui.MolangUiSessionManager.closeAllForPlayer(it.player.uuid)
}
PlatformEvents.PLAYER_DEATH.subscribe {
PCLinkManager.removeLink(it.player.uuid)
@@ -302,7 +301,6 @@ object Cobblemon {
HeldItemProvider.register(CobblemonHeldItemManager, Priority.LOWEST)
}
fun sendServerSettingsPacketToPlayer(player: ServerPlayer) {
ServerSettingsPacket(
this.config.preventCompletePartyDeposit,
@@ -311,6 +309,9 @@ object Cobblemon {
this.config.maxPokemonLevel,
this.config.maxPokemonFriendship,
this.config.maxDynamaxLevel,
this.config.unlockAllMoveDexMovesByDefault,
this.config.pokemonIntrinsicSizeMin,
this.config.pokemonIntrinsicSizeMax
).sendToPlayer(player)
}
@@ -324,8 +325,11 @@ object Cobblemon {
GENDER_ASPECT.register()
COSMETIC_SLOT_ASPECT.register()
CHARACTERISTIC_RAINBOW_ASPECT.register()
ALPHA_ASPECT.register()
MARK_ASPECT.register()
SpeciesFeatures.types["choice"] = ChoiceSpeciesFeatureProvider::class.java
SpeciesFeatures.types["weighted_choice"] = WeightedChoiceSpeciesFeatureProvider::class.java
SpeciesFeatures.types["flag"] = FlagSpeciesFeatureProvider::class.java
SpeciesFeatures.types["integer"] = IntSpeciesFeatureProvider::class.java
@@ -347,10 +351,7 @@ object Cobblemon {
CustomPokemonProperty.register(UnaspectPropertyType)
CustomPokemonProperty.register(FreezeFrameProperty)
CustomPokemonProperty.register(NoAIProperty)
// Tween & camera system initialization
EasingRegistry.registerBuiltinEasings()
CameraTrackDeserializers.registerBuiltinTracks()
CustomPokemonProperty.register(HeldItemVisibleProperty)
CobblemonEvents.POKEMON_PROPERTY_INITIALISED.emit(Unit)
@@ -364,7 +365,6 @@ object Cobblemon {
PlatformEvents.SERVER_TICK_POST.subscribe {
ServerTaskTracker.update(1/20F)
ServerRealTimeTaskTracker.update()
TweenManager.server.update(1/20F)
}
PlatformEvents.SERVER_TICK_PRE.subscribe {
ServerRealTimeTaskTracker.update()
@@ -373,6 +373,7 @@ object Cobblemon {
val server = event.server
MoLangLoadedFilesCache.initialize(server)
playerDataManager = PlayerInstancedDataStoreManager().also { it.setup(server) }
HabitatPools.onServerLoading(server)
val mongoClient: MongoClient?
@@ -385,8 +386,12 @@ object Cobblemon {
val pokedexNbtFactory = CachedPlayerDataStoreFactory(DexDataNbtBackend())
pokedexNbtFactory.setup(server)
val tmMoveFactory = CachedPlayerDataStoreFactory(TMMoveNbtBackend())
tmMoveFactory.setup(server)
playerDataManager.setFactory(generalJsonFactory, PlayerInstancedDataStoreTypes.GENERAL)
playerDataManager.setFactory(pokedexNbtFactory, PlayerInstancedDataStoreTypes.POKEDEX)
playerDataManager.setFactory(tmMoveFactory, PlayerInstancedDataStoreTypes.TM_MOVES)
if (config.storageFormat == "nbt") {
NBTStoreAdapter(pokemonStoreRoot.absolutePath, useNestedFolders = true, folderPerClass = true)
@@ -413,8 +418,14 @@ object Cobblemon {
val pokedexMongoFactory = CachedPlayerDataStoreFactory(DexDataMongoBackend(mongoClient, config.mongoDBDatabaseName, "PokeDexCollection"))
pokedexMongoFactory.setup(server)
val tmMovesMongoFactory = CachedPlayerDataStoreFactory(
TMMoveMongoBackend(mongoClient, config.mongoDBDatabaseName, "TMMovesCollection")
)
tmMovesMongoFactory.setup(server)
playerDataManager.setFactory(generalMongoFactory, PlayerInstancedDataStoreTypes.GENERAL)
playerDataManager.setFactory(pokedexMongoFactory, PlayerInstancedDataStoreTypes.POKEDEX)
playerDataManager.setFactory(tmMovesMongoFactory, PlayerInstancedDataStoreTypes.TM_MOVES)
MongoDBStoreAdapter(mongoClient, config.mongoDBDatabaseName)
} catch (e: ClassNotFoundException) {
LOGGER.error("MongoDB driver not found.")
@@ -598,6 +609,7 @@ object Cobblemon {
this.implementation.registerCommandArgument(cobblemonResource("mark"), MarkArgumentType::class, SingletonArgumentInfo.contextFree(MarkArgumentType::mark))
this.implementation.registerCommandArgument(cobblemonResource("transform_type"), TransformTypeArgumentType::class, SingletonArgumentInfo.contextFree(TransformTypeArgumentType::transformType))
this.implementation.registerCommandArgument(cobblemonResource("model_part"), ModelPartArgumentType::class, SingletonArgumentInfo.contextFree(ModelPartArgumentType::modelPart))
this.implementation.registerCommandArgument(cobblemonResource("tm"), TmArgumentType::class, SingletonArgumentInfo.contextFree(TmArgumentType::tm))
}
}
@@ -8,22 +8,15 @@
package com.cobblemon.mod.common
import com.cobblemon.mod.common.block.entity.BerryBlockEntity
import com.cobblemon.mod.common.block.entity.HealingMachineBlockEntity
import com.cobblemon.mod.common.block.entity.PCBlockEntity
import com.cobblemon.mod.common.block.entity.PokemonPastureBlockEntity
import com.cobblemon.mod.common.block.entity.FossilAnalyzerBlockEntity
import com.cobblemon.mod.common.block.entity.FossilMultiblockEntity
import com.cobblemon.mod.common.block.entity.RestorationTankBlockEntity
import com.cobblemon.mod.common.block.multiblock.FossilMultiblockBuilder
import com.cobblemon.mod.common.block.entity.*
import com.cobblemon.mod.common.block.entity.DisplayCaseBlockEntity
import com.cobblemon.mod.common.block.habitat.HabitatBlockEntity
import com.cobblemon.mod.common.block.multiblock.FossilMultiblockBuilder
import com.cobblemon.mod.common.platform.PlatformRegistry
import net.minecraft.core.Registry
import net.minecraft.core.registries.BuiltInRegistries
import net.minecraft.core.registries.Registries
import net.minecraft.world.level.block.entity.BlockEntityType
import net.minecraft.resources.ResourceKey
import net.minecraft.world.level.block.entity.BlockEntityType
object CobblemonBlockEntities : PlatformRegistry<Registry<BlockEntityType<*>>, ResourceKey<Registry<BlockEntityType<*>>>, BlockEntityType<*>>() {
@@ -39,6 +32,9 @@ object CobblemonBlockEntities : PlatformRegistry<Registry<BlockEntityType<*>>, R
@JvmField
val LECTERN: BlockEntityType<LecternBlockEntity> = this.create("lectern", BlockEntityType.Builder.of(::LecternBlockEntity, CobblemonBlocks.LECTERN).build(null))
@JvmField
val DISC_SHELF: BlockEntityType<DiscShelfBlockEntity> = this.create("disc_shelf", BlockEntityType.Builder.of(::DiscShelfBlockEntity, CobblemonBlocks.DISC_SHELF).build(null))
@JvmField
val BERRY = this.create("berry", BlockEntityType.Builder.of(::BerryBlockEntity, *CobblemonBlocks.berries().values.toTypedArray()).build(null))
@@ -48,6 +44,13 @@ object CobblemonBlockEntities : PlatformRegistry<Registry<BlockEntityType<*>>, R
val SIGN: BlockEntityType<CobblemonSignBlockEntity> = this.create("sign", BlockEntityType.Builder.of(::CobblemonSignBlockEntity, CobblemonBlocks.APRICORN_SIGN, CobblemonBlocks.APRICORN_WALL_SIGN, CobblemonBlocks.SACCHARINE_SIGN, CobblemonBlocks.SACCHARINE_WALL_SIGN).build(null))
@JvmField
val HANGING_SIGN: BlockEntityType<CobblemonHangingSignBlockEntity> = this.create("hanging_sign", BlockEntityType.Builder.of(::CobblemonHangingSignBlockEntity, CobblemonBlocks.APRICORN_HANGING_SIGN, CobblemonBlocks.APRICORN_WALL_HANGING_SIGN, CobblemonBlocks.SACCHARINE_HANGING_SIGN, CobblemonBlocks.SACCHARINE_WALL_HANGING_SIGN).build(null))
@JvmField
val TM_MACHINE: BlockEntityType<TMMachineBlockEntity> = this.create("tm_machine", BlockEntityType.Builder.of(::TMMachineBlockEntity, CobblemonBlocks.TM_MACHINE).build(null))
@JvmField
val HABITAT_BLOCK: BlockEntityType<HabitatBlockEntity> = this.create("habitat_block",
BlockEntityType.Builder.of(::HabitatBlockEntity, CobblemonBlocks.HABITAT_BLOCK).build(null)
)
@JvmField
val GILDED_CHEST: BlockEntityType<GildedChestBlockEntity> = this.create("chest", BlockEntityType.Builder.of(::GildedChestBlockEntity,
@@ -106,10 +109,4 @@ object CobblemonBlockEntities : PlatformRegistry<Registry<BlockEntityType<*>>, R
"poke_snack",
BlockEntityType.Builder.of(::PokeSnackBlockEntity, CobblemonBlocks.POKE_SNACK, CobblemonBlocks.POKE_CAKE).build(null)
)
@JvmField
val STADIUM_BLOCK: BlockEntityType<StadiumBlockEntity> = this.create(
"stadium_block",
BlockEntityType.Builder.of(::StadiumBlockEntity, CobblemonBlocks.STADIUM_BLOCK).build(null)
)
}
@@ -11,20 +11,27 @@ 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
import com.cobblemon.mod.common.block.MintBlock.MintType
import com.cobblemon.mod.common.block.campfirepot.CampfireBlock
import com.cobblemon.mod.common.block.campfirepot.CampfirePotBlock
import com.cobblemon.mod.common.block.chest.GildedChestBlock
import com.cobblemon.mod.common.block.general.BaleBlock
import com.cobblemon.mod.common.block.general.HorizontalRotationCarpetBlock
import com.cobblemon.mod.common.block.general.HorizontalRotationalBlock
import com.cobblemon.mod.common.block.grower.SaccharineTreeGrower
import com.cobblemon.mod.common.block.habitat.HabitatBlock
import com.cobblemon.mod.common.block.sign.CobblemonHangingSignBlock
import com.cobblemon.mod.common.block.sign.CobblemonSignBlock
import com.cobblemon.mod.common.block.sign.CobblemonWallHangingSignBlock
import com.cobblemon.mod.common.block.sign.CobblemonWallSignBlock
import com.cobblemon.mod.common.block.general.HorizontalRotationCarpetBlock
import com.cobblemon.mod.common.block.general.HorizontalRotationalBlock
import com.cobblemon.mod.common.mixin.invoker.*
import com.cobblemon.mod.common.block.tmmachine.TMMachineBlock
import com.cobblemon.mod.common.mixin.invoker.BlocksInvoker
import com.cobblemon.mod.common.mixin.invoker.DoorBlockInvoker
import com.cobblemon.mod.common.mixin.invoker.FireBlockInvoker
import com.cobblemon.mod.common.mixin.invoker.PressurePlateBlockInvoker
import com.cobblemon.mod.common.mixin.invoker.StairsBlockInvoker
import com.cobblemon.mod.common.mixin.invoker.TrapdoorBlockInvoker
import com.cobblemon.mod.common.platform.PlatformRegistry
import com.cobblemon.mod.common.util.cobblemonResource
import net.minecraft.core.BlockPos
@@ -46,7 +53,6 @@ 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>() {
@@ -121,19 +127,19 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
val APRICORN_PLANKS = this.create("apricorn_planks",
Block(
BlockBehaviour.Properties.of().mapColor(MapColor.DIRT).instrument(NoteBlockInstrument.BASS)
.strength(2.0f, 3.0f).sound(SoundType.WOOD)
.strength(2.0F, 3.0F).sound(SoundType.WOOD)
)
)
@JvmField
val APRICORN_LEAVES = leaves("apricorn_leaves")
@JvmField
val APRICORN_FENCE = this.create("apricorn_fence", FenceBlock(BlockBehaviour.Properties.of().mapColor(APRICORN_PLANKS.defaultMapColor()).instrument(NoteBlockInstrument.BASS).strength(2.0f, 3.0f).sound(SoundType.WOOD)))
val APRICORN_FENCE = this.create("apricorn_fence", FenceBlock(BlockBehaviour.Properties.of().mapColor(APRICORN_PLANKS.defaultMapColor()).instrument(NoteBlockInstrument.BASS).strength(2.0F, 3.0F).sound(SoundType.WOOD)))
@JvmField
val APRICORN_FENCE_GATE = this.create("apricorn_fence_gate", FenceGateBlock(APRICORN_WOOD_TYPE, BlockBehaviour.Properties.of().mapColor(APRICORN_PLANKS.defaultMapColor()).strength(2.0f, 3.0f).sound(SoundType.WOOD).ignitedByLava().forceSolidOn()))
val APRICORN_FENCE_GATE = this.create("apricorn_fence_gate", FenceGateBlock(APRICORN_WOOD_TYPE, BlockBehaviour.Properties.of().mapColor(APRICORN_PLANKS.defaultMapColor()).strength(2.0F, 3.0F).sound(SoundType.WOOD).ignitedByLava().forceSolidOn()))
@JvmField
val APRICORN_BUTTON = this.create("apricorn_button", BlocksInvoker.createWoodenButtonBlock(APRICORN_BLOCK_SET_TYPE))
@JvmField
val APRICORN_PRESSURE_PLATE = this.create("apricorn_pressure_plate", PressurePlateBlockInvoker.`cobblemon$create`(APRICORN_BLOCK_SET_TYPE, BlockBehaviour.Properties.of().mapColor(APRICORN_PLANKS.defaultMapColor()).noCollission().strength(0.5f).sound(SoundType.WOOD)))
val APRICORN_PRESSURE_PLATE = this.create("apricorn_pressure_plate", PressurePlateBlockInvoker.`cobblemon$create`(APRICORN_BLOCK_SET_TYPE, BlockBehaviour.Properties.of().mapColor(APRICORN_PLANKS.defaultMapColor()).noCollission().strength(0.5F).sound(SoundType.WOOD)))
@JvmField
val APRICORN_SIGN = this.create("apricorn_sign", CobblemonSignBlock(BlockBehaviour.Properties.ofFullCopy(Blocks.OAK_SIGN), APRICORN_WOOD_TYPE))
@@ -150,7 +156,7 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
@JvmField
val APRICORN_WALL_HANGING_SIGN = this.create("apricorn_wall_hanging_sign", CobblemonWallHangingSignBlock(BlockBehaviour.Properties.ofFullCopy(Blocks.OAK_HANGING_SIGN), APRICORN_WOOD_TYPE))
@JvmField
val APRICORN_SLAB = this.create("apricorn_slab", SlabBlock(BlockBehaviour.Properties.of().mapColor(MapColor.WOOD).instrument(NoteBlockInstrument.BASS).strength(2.0f, 3.0f).sound(SoundType.WOOD)))
val APRICORN_SLAB = this.create("apricorn_slab", SlabBlock(BlockBehaviour.Properties.of().mapColor(MapColor.WOOD).instrument(NoteBlockInstrument.BASS).strength(2.0F, 3.0F).sound(SoundType.WOOD)))
@JvmField
val APRICORN_STAIRS = this.create("apricorn_stairs", StairsBlockInvoker.`cobblemon$create`(APRICORN_PLANKS.defaultBlockState(), BlockBehaviour.Properties.ofFullCopy(APRICORN_PLANKS)))
@JvmField
@@ -187,12 +193,12 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
@JvmField
val STRIPPED_SACCHARINE_WOOD = this.create("stripped_saccharine_wood", RotatedPillarBlock(BlockBehaviour.Properties.of().mapColor(MapColor.COLOR_LIGHT_BLUE).instrument(NoteBlockInstrument.BASS).strength(2.0F).sound(SoundType.WOOD).ignitedByLava())) //log("stripped_saccharine_log")
@JvmField
val SACCHARINE_PLANKS = this.create("saccharine_planks", Block(BlockBehaviour.Properties.of().mapColor(MapColor.COLOR_LIGHT_BLUE).instrument(NoteBlockInstrument.BASS).strength(2.0f, 3.0f).sound(SoundType.WOOD)))
val SACCHARINE_PLANKS = this.create("saccharine_planks", Block(BlockBehaviour.Properties.of().mapColor(MapColor.COLOR_LIGHT_BLUE).instrument(NoteBlockInstrument.BASS).strength(2.0F, 3.0F).sound(SoundType.WOOD)))
@JvmField
val SACCHARINE_LEAVES = this.create("saccharine_leaves", SaccharineLeafBlock(
BlockBehaviour.Properties.of().mapColor(
MapColor.PLANT
).strength(0.2f).randomTicks().sound(SoundType.GRASS).noOcclusion()
).strength(0.2F).randomTicks().sound(SoundType.GRASS).noOcclusion()
.isValidSpawn { _: BlockState?, _: BlockGetter?, _: BlockPos?, entity: EntityType<*>? ->
entity === EntityType.OCELOT || entity === EntityType.PARROT
}.isSuffocating { _: BlockState?, _: BlockGetter?, _: BlockPos? ->
@@ -204,13 +210,13 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
false
}))
@JvmField
val SACCHARINE_FENCE = this.create("saccharine_fence", FenceBlock(BlockBehaviour.Properties.of().mapColor(SACCHARINE_PLANKS.defaultMapColor()).instrument(NoteBlockInstrument.BASS).strength(2.0f, 3.0f).sound(SoundType.WOOD)))
val SACCHARINE_FENCE = this.create("saccharine_fence", FenceBlock(BlockBehaviour.Properties.of().mapColor(SACCHARINE_PLANKS.defaultMapColor()).instrument(NoteBlockInstrument.BASS).strength(2.0F, 3.0F).sound(SoundType.WOOD)))
@JvmField
val SACCHARINE_FENCE_GATE = this.create("saccharine_fence_gate", FenceGateBlock(SACCHARINE_WOOD_TYPE, BlockBehaviour.Properties.of().mapColor(SACCHARINE_PLANKS.defaultMapColor()).instrument(NoteBlockInstrument.BASS).strength(2.0f, 3.0f).sound(SoundType.WOOD).ignitedByLava().forceSolidOn()))
val SACCHARINE_FENCE_GATE = this.create("saccharine_fence_gate", FenceGateBlock(SACCHARINE_WOOD_TYPE, BlockBehaviour.Properties.of().mapColor(SACCHARINE_PLANKS.defaultMapColor()).instrument(NoteBlockInstrument.BASS).strength(2.0F, 3.0F).sound(SoundType.WOOD).ignitedByLava().forceSolidOn()))
@JvmField
val SACCHARINE_BUTTON = this.create("saccharine_button", BlocksInvoker.createWoodenButtonBlock(BlockSetType.OAK))
@JvmField
val SACCHARINE_PRESSURE_PLATE = this.create("saccharine_pressure_plate", PressurePlateBlockInvoker.`cobblemon$create`(SACCHARINE_BLOCK_SET_TYPE, BlockBehaviour.Properties.of().mapColor(SACCHARINE_PLANKS.defaultMapColor()).instrument(NoteBlockInstrument.BASS).noCollission().strength(0.5f).sound(SoundType.WOOD)))
val SACCHARINE_PRESSURE_PLATE = this.create("saccharine_pressure_plate", PressurePlateBlockInvoker.`cobblemon$create`(SACCHARINE_BLOCK_SET_TYPE, BlockBehaviour.Properties.of().mapColor(SACCHARINE_PLANKS.defaultMapColor()).instrument(NoteBlockInstrument.BASS).noCollission().strength(0.5F).sound(SoundType.WOOD)))
@JvmField
val SACCHARINE_SIGN = this.create("saccharine_sign", CobblemonSignBlock(BlockBehaviour.Properties.ofFullCopy(Blocks.OAK_SIGN), SACCHARINE_WOOD_TYPE))
@JvmField
@@ -220,7 +226,7 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
@JvmField
val SACCHARINE_WALL_HANGING_SIGN = this.create("saccharine_wall_hanging_sign", CobblemonWallHangingSignBlock(BlockBehaviour.Properties.ofFullCopy(Blocks.OAK_HANGING_SIGN), SACCHARINE_WOOD_TYPE))
@JvmField
val SACCHARINE_SLAB = this.create("saccharine_slab", SlabBlock(BlockBehaviour.Properties.of().mapColor(MapColor.WOOD).instrument(NoteBlockInstrument.BASS).strength(2.0f, 3.0f).sound(SoundType.WOOD)))
val SACCHARINE_SLAB = this.create("saccharine_slab", SlabBlock(BlockBehaviour.Properties.of().mapColor(MapColor.WOOD).instrument(NoteBlockInstrument.BASS).strength(2.0F, 3.0F).sound(SoundType.WOOD)))
@JvmField
val SACCHARINE_STAIRS = this.create("saccharine_stairs", StairsBlockInvoker.`cobblemon$create`(SACCHARINE_PLANKS.defaultBlockState(), BlockBehaviour.Properties.ofFullCopy(SACCHARINE_PLANKS)))
@JvmField
@@ -249,31 +255,31 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
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)
val TUMBLESTONE_CLUSTER = tumblestoneBlock("tumblestone_cluster", TumblestoneBlock.STAGE_3, 7, 3, null, MapColor.TERRACOTTA_ORANGE)
@JvmField
val LARGE_BUDDING_TUMBLESTONE = tumblestoneBlock("large_budding_tumblestone", GrowableStoneBlock.STAGE_2, 5, 3, TUMBLESTONE_CLUSTER)
val LARGE_BUDDING_TUMBLESTONE = tumblestoneBlock("large_budding_tumblestone", TumblestoneBlock.STAGE_2, 5, 3, TUMBLESTONE_CLUSTER, MapColor.TERRACOTTA_ORANGE)
@JvmField
val MEDIUM_BUDDING_TUMBLESTONE = tumblestoneBlock("medium_budding_tumblestone", GrowableStoneBlock.STAGE_1, 4, 3, LARGE_BUDDING_TUMBLESTONE)
val MEDIUM_BUDDING_TUMBLESTONE = tumblestoneBlock("medium_budding_tumblestone", TumblestoneBlock.STAGE_1, 4, 3, LARGE_BUDDING_TUMBLESTONE, MapColor.TERRACOTTA_ORANGE)
@JvmField
val SMALL_BUDDING_TUMBLESTONE = tumblestoneBlock("small_budding_tumblestone", GrowableStoneBlock.STAGE_0, 3, 4, MEDIUM_BUDDING_TUMBLESTONE)
val SMALL_BUDDING_TUMBLESTONE = tumblestoneBlock("small_budding_tumblestone", TumblestoneBlock.STAGE_0, 3, 4, MEDIUM_BUDDING_TUMBLESTONE, MapColor.TERRACOTTA_ORANGE)
@JvmField
val SKY_TUMBLESTONE_CLUSTER = tumblestoneBlock("sky_tumblestone_cluster", GrowableStoneBlock.STAGE_3, 7, 3, null)
val SKY_TUMBLESTONE_CLUSTER = tumblestoneBlock("sky_tumblestone_cluster", TumblestoneBlock.STAGE_3, 7, 3, null, MapColor.COLOR_LIGHT_BLUE)
@JvmField
val LARGE_BUDDING_SKY_TUMBLESTONE = tumblestoneBlock("large_budding_sky_tumblestone", GrowableStoneBlock.STAGE_2, 5, 3, SKY_TUMBLESTONE_CLUSTER)
val LARGE_BUDDING_SKY_TUMBLESTONE = tumblestoneBlock("large_budding_sky_tumblestone", TumblestoneBlock.STAGE_2, 5, 3, SKY_TUMBLESTONE_CLUSTER, MapColor.COLOR_LIGHT_BLUE)
@JvmField
val MEDIUM_BUDDING_SKY_TUMBLESTONE = tumblestoneBlock("medium_budding_sky_tumblestone", GrowableStoneBlock.STAGE_1, 4, 3, LARGE_BUDDING_SKY_TUMBLESTONE)
val MEDIUM_BUDDING_SKY_TUMBLESTONE = tumblestoneBlock("medium_budding_sky_tumblestone", TumblestoneBlock.STAGE_1, 4, 3, LARGE_BUDDING_SKY_TUMBLESTONE, MapColor.COLOR_LIGHT_BLUE)
@JvmField
val SMALL_BUDDING_SKY_TUMBLESTONE = tumblestoneBlock("small_budding_sky_tumblestone", GrowableStoneBlock.STAGE_0, 3, 4, MEDIUM_BUDDING_SKY_TUMBLESTONE)
val SMALL_BUDDING_SKY_TUMBLESTONE = tumblestoneBlock("small_budding_sky_tumblestone", TumblestoneBlock.STAGE_0, 3, 4, MEDIUM_BUDDING_SKY_TUMBLESTONE, MapColor.COLOR_LIGHT_BLUE)
@JvmField
val BLACK_TUMBLESTONE_CLUSTER = tumblestoneBlock("black_tumblestone_cluster", GrowableStoneBlock.STAGE_3, 7, 3, null)
val BLACK_TUMBLESTONE_CLUSTER = tumblestoneBlock("black_tumblestone_cluster", TumblestoneBlock.STAGE_3, 7, 3, null, MapColor.TERRACOTTA_BLACK)
@JvmField
val LARGE_BUDDING_BLACK_TUMBLESTONE = tumblestoneBlock("large_budding_black_tumblestone", GrowableStoneBlock.STAGE_2, 5, 3, BLACK_TUMBLESTONE_CLUSTER)
val LARGE_BUDDING_BLACK_TUMBLESTONE = tumblestoneBlock("large_budding_black_tumblestone", TumblestoneBlock.STAGE_2, 5, 3, BLACK_TUMBLESTONE_CLUSTER, MapColor.TERRACOTTA_BLACK)
@JvmField
val MEDIUM_BUDDING_BLACK_TUMBLESTONE = tumblestoneBlock("medium_budding_black_tumblestone", GrowableStoneBlock.STAGE_1, 4, 3, LARGE_BUDDING_BLACK_TUMBLESTONE)
val MEDIUM_BUDDING_BLACK_TUMBLESTONE = tumblestoneBlock("medium_budding_black_tumblestone", TumblestoneBlock.STAGE_1, 4, 3, LARGE_BUDDING_BLACK_TUMBLESTONE, MapColor.TERRACOTTA_BLACK)
@JvmField
val SMALL_BUDDING_BLACK_TUMBLESTONE = tumblestoneBlock("small_budding_black_tumblestone", GrowableStoneBlock.STAGE_0, 3, 4, MEDIUM_BUDDING_BLACK_TUMBLESTONE)
val SMALL_BUDDING_BLACK_TUMBLESTONE = tumblestoneBlock("small_budding_black_tumblestone", TumblestoneBlock.STAGE_0, 3, 4, MEDIUM_BUDDING_BLACK_TUMBLESTONE, MapColor.TERRACOTTA_BLACK)
@JvmField
val TUMBLESTONE_BLOCK = this.create("tumblestone_block", Block(BlockBehaviour.Properties.of().mapColor(MapColor.TERRACOTTA_ORANGE).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
@@ -282,6 +288,87 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
@JvmField
val BLACK_TUMBLESTONE_BLOCK = this.create("black_tumblestone_block", Block(BlockBehaviour.Properties.of().mapColor(MapColor.TERRACOTTA_BLACK).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
@JvmField
val TYPE_GEM_CORE = this.create("deepslate_crystal_core", TypeGemCoreBlock(BlockBehaviour.Properties.of().strength(4.0F, 10.0F).requiresCorrectToolForDrops().mapColor(MapColor.DEEPSLATE)))
private val typeGemBlocks = mutableMapOf<ResourceLocation, Block>()
@JvmField
val TYPE_GEM_BLOCK_NORMAL = typeGemBlock("normal_gem_block", MapColor.QUARTZ)
@JvmField
val TYPE_GEM_BLOCK_FIRE = typeGemBlock("fire_gem_block", MapColor.FIRE)
@JvmField
val TYPE_GEM_BLOCK_WATER = typeGemBlock("water_gem_block", MapColor.WATER)
@JvmField
val TYPE_GEM_BLOCK_GRASS = typeGemBlock("grass_gem_block", MapColor.COLOR_LIGHT_GREEN)
@JvmField
val TYPE_GEM_BLOCK_ELECTRIC = typeGemBlock("electric_gem_block", MapColor.GOLD)
@JvmField
val TYPE_GEM_BLOCK_ICE = typeGemBlock("ice_gem_block", MapColor.ICE)
@JvmField
val TYPE_GEM_BLOCK_FIGHTING = typeGemBlock("fighting_gem_block", MapColor.COLOR_RED)
@JvmField
val TYPE_GEM_BLOCK_POISON = typeGemBlock("poison_gem_block", MapColor.COLOR_PURPLE)
@JvmField
val TYPE_GEM_BLOCK_GROUND = typeGemBlock("ground_gem_block", MapColor.PODZOL)
@JvmField
val TYPE_GEM_BLOCK_FLYING = typeGemBlock("flying_gem_block", MapColor.COLOR_LIGHT_BLUE)
@JvmField
val TYPE_GEM_BLOCK_PSYCHIC = typeGemBlock("psychic_gem_block", MapColor.COLOR_MAGENTA)
@JvmField
val TYPE_GEM_BLOCK_BUG = typeGemBlock("bug_gem_block", MapColor.TERRACOTTA_LIGHT_GREEN)
@JvmField
val TYPE_GEM_BLOCK_ROCK = typeGemBlock("rock_gem_block", MapColor.TERRACOTTA_LIGHT_GRAY)
@JvmField
val TYPE_GEM_BLOCK_GHOST = typeGemBlock("ghost_gem_block", MapColor.TERRACOTTA_MAGENTA)
@JvmField
val TYPE_GEM_BLOCK_DRAGON = typeGemBlock("dragon_gem_block", MapColor.COLOR_BLUE)
@JvmField
val TYPE_GEM_BLOCK_DARK = typeGemBlock("dark_gem_block", MapColor.TERRACOTTA_BLACK)
@JvmField
val TYPE_GEM_BLOCK_STEEL = typeGemBlock("steel_gem_block", MapColor.METAL)
@JvmField
val TYPE_GEM_BLOCK_FAIRY = typeGemBlock("fairy_gem_block", MapColor.COLOR_PINK)
private val typeGemClusters = mutableMapOf<ResourceLocation, TypeGemClusterBlock>()
@JvmField
val TYPE_GEM_CLUSTER_NORMAL = typeGemCluster("normal_gem_cluster", TYPE_GEM_BLOCK_NORMAL, cobblemonResource("normal_gem"), MapColor.QUARTZ)
@JvmField
val TYPE_GEM_CLUSTER_FIRE = typeGemCluster("fire_gem_cluster", TYPE_GEM_BLOCK_FIRE, cobblemonResource("fire_gem"), MapColor.FIRE)
@JvmField
val TYPE_GEM_CLUSTER_WATER = typeGemCluster("water_gem_cluster", TYPE_GEM_BLOCK_WATER, cobblemonResource("water_gem"), MapColor.WATER)
@JvmField
val TYPE_GEM_CLUSTER_GRASS = typeGemCluster("grass_gem_cluster", TYPE_GEM_BLOCK_GRASS, cobblemonResource("grass_gem"), MapColor.COLOR_LIGHT_GREEN)
@JvmField
val TYPE_GEM_CLUSTER_ELECTRIC = typeGemCluster("electric_gem_cluster", TYPE_GEM_BLOCK_ELECTRIC, cobblemonResource("electric_gem"), MapColor.GOLD)
@JvmField
val TYPE_GEM_CLUSTER_ICE = typeGemCluster("ice_gem_cluster", TYPE_GEM_BLOCK_ICE, cobblemonResource("ice_gem"), MapColor.ICE)
@JvmField
val TYPE_GEM_CLUSTER_FIGHTING = typeGemCluster("fighting_gem_cluster", TYPE_GEM_BLOCK_FIGHTING, cobblemonResource("fighting_gem"), MapColor.COLOR_RED)
@JvmField
val TYPE_GEM_CLUSTER_POISON = typeGemCluster("poison_gem_cluster", TYPE_GEM_BLOCK_POISON, cobblemonResource("poison_gem"), MapColor.COLOR_PURPLE)
@JvmField
val TYPE_GEM_CLUSTER_GROUND = typeGemCluster("ground_gem_cluster", TYPE_GEM_BLOCK_GROUND, cobblemonResource("ground_gem"), MapColor.PODZOL)
@JvmField
val TYPE_GEM_CLUSTER_FLYING = typeGemCluster("flying_gem_cluster", TYPE_GEM_BLOCK_FLYING, cobblemonResource("flying_gem"), MapColor.COLOR_LIGHT_BLUE)
@JvmField
val TYPE_GEM_CLUSTER_PSYCHIC = typeGemCluster("psychic_gem_cluster", TYPE_GEM_BLOCK_PSYCHIC, cobblemonResource("psychic_gem"), MapColor.COLOR_MAGENTA)
@JvmField
val TYPE_GEM_CLUSTER_BUG = typeGemCluster("bug_gem_cluster", TYPE_GEM_BLOCK_BUG, cobblemonResource("bug_gem"), MapColor.TERRACOTTA_LIGHT_GREEN)
@JvmField
val TYPE_GEM_CLUSTER_ROCK = typeGemCluster("rock_gem_cluster", TYPE_GEM_BLOCK_ROCK, cobblemonResource("rock_gem"), MapColor.TERRACOTTA_LIGHT_GRAY)
@JvmField
val TYPE_GEM_CLUSTER_GHOST = typeGemCluster("ghost_gem_cluster", TYPE_GEM_BLOCK_GHOST, cobblemonResource("ghost_gem"), MapColor.TERRACOTTA_MAGENTA)
@JvmField
val TYPE_GEM_CLUSTER_DRAGON = typeGemCluster("dragon_gem_cluster", TYPE_GEM_BLOCK_DRAGON, cobblemonResource("dragon_gem"), MapColor.COLOR_BLUE)
@JvmField
val TYPE_GEM_CLUSTER_DARK = typeGemCluster("dark_gem_cluster", TYPE_GEM_BLOCK_DARK, cobblemonResource("dark_gem"), MapColor.TERRACOTTA_BLACK)
@JvmField
val TYPE_GEM_CLUSTER_STEEL = typeGemCluster("steel_gem_cluster", TYPE_GEM_BLOCK_STEEL, cobblemonResource("steel_gem"), MapColor.METAL)
@JvmField
val TYPE_GEM_CLUSTER_FAIRY = typeGemCluster("fairy_gem_cluster", TYPE_GEM_BLOCK_FAIRY, cobblemonResource("fairy_gem"), MapColor.COLOR_PINK)
@JvmField
val POLISHED_TUMBLESTONE = this.create("polished_tumblestone", Block(BlockBehaviour.Properties.of().mapColor(MapColor.TERRACOTTA_ORANGE).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
@JvmField
@@ -450,6 +537,18 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
)
)
@JvmField
val HABITAT_BLOCK = this.create(
name = "habitat_block",
entry = HabitatBlock(
properties = BlockBehaviour.Properties.of()
.mapColor(MapColor.STONE)
.strength(1.5F, Blocks.OBSIDIAN.explosionResistance)
.pushReaction(PushReaction.BLOCK)
)
)
@JvmField
val CAMPFIRE = create("campfire", CampfireBlock(BlockBehaviour.Properties.of().sound(SoundType.WOOD).noOcclusion().pushReaction(PushReaction.BLOCK).mapColor(MapColor.PODZOL).strength(2.0F).lightLevel{14}, false))
@@ -459,7 +558,7 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
@JvmField
val RELIC_COIN_POUCH = create("relic_coin_pouch", CoinPouchBlock(BlockBehaviour.Properties.of().sound(CobblemonSounds.RELIC_COIN_POUCH_SOUNDS).pushReaction(PushReaction.DESTROY).noOcclusion(), true))
@JvmField
val RELIC_COIN_SACK = create("relic_coin_sack", CoinPouchBlock(BlockBehaviour.Properties.of().sound(CobblemonSounds.RELIC_COIN_SACK_SOUNDS).pushReaction(PushReaction.DESTROY).strength(0.4f), false))
val RELIC_COIN_SACK = create("relic_coin_sack", CoinPouchBlock(BlockBehaviour.Properties.of().sound(CobblemonSounds.RELIC_COIN_SACK_SOUNDS).pushReaction(PushReaction.DESTROY).strength(0.4F).mapColor(MapColor.GOLD), false))
@JvmField
val GILDED_CHEST = create("gilded_chest", GildedChestBlock(BlockBehaviour.Properties.ofFullCopy(Blocks.CHEST).noOcclusion().sound(CobblemonSounds.GILDED_CHEST_SOUNDS), GildedChestBlock.Type.RED))
@@ -512,14 +611,14 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
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))
val CLEANSE_TAG = create("cleanse_tag", WallAttachedStackableItemBlock(BlockBehaviour.Properties.of().sound(CobblemonSounds.ITEM_BLOCK_PAPER_SMALL_SOUNDS).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))
val SPELL_TAG = create("spell_tag", WallAttachedStackableItemBlock(BlockBehaviour.Properties.of().sound(CobblemonSounds.ITEM_BLOCK_PAPER_SMALL_SOUNDS).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))
val BLUNDER_POLICY = create("blunder_policy", WallAttachedDirectionalShapeBlock(BlockBehaviour.Properties.of().sound(CobblemonSounds.ITEM_BLOCK_PAPER_LARGE_SOUNDS).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))
val WEAKNESS_POLICY = create("weakness_policy", WallAttachedDirectionalShapeBlock(BlockBehaviour.Properties.of().sound(CobblemonSounds.ITEM_BLOCK_PAPER_LARGE_SOUNDS).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))
@@ -574,28 +673,43 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
@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
val DAMAGED_MONITOR = create("damaged_monitor", DamagedMonitorBlock(BlockBehaviour.Properties.of().mapColor(MapColor.METAL).sound(SoundType.METAL).pushReaction(PushReaction.BLOCK).requiresCorrectToolForDrops().strength(5.0F, 6.0F).lightLevel { when (it.getValue(DamagedMonitorBlock.SCREEN)) { DamagedMonitorBlock.BrokenMonitorScreen.GLITCHING -> 10; else -> 0 } }))
@JvmField
val FOSSIL_ANALYZER = create("fossil_analyzer", FossilAnalyzerBlock(BlockBehaviour.Properties.of().mapColor(MapColor.METAL).sound(SoundType.METAL).pushReaction(PushReaction.BLOCK).requiresCorrectToolForDrops().strength(5.0F, 6.0F).noOcclusion()))
@JvmField
val RESTORATION_TANK = create("restoration_tank", RestorationTankBlock(BlockBehaviour.Properties.of().mapColor(MapColor.METAL).sound(SoundType.GLASS).pushReaction(PushReaction.BLOCK).requiresCorrectToolForDrops().strength(5.0F, 6.0F).noOcclusion()))
@JvmField
val HEALING_MACHINE = create("healing_machine", HealingMachineBlock(BlockBehaviour.Properties.of().mapColor(MapColor.METAL).sound(SoundType.METAL).pushReaction(PushReaction.BLOCK).strength(2f).noOcclusion().lightLevel { if (it.getValue(HealingMachineBlock.CHARGE_LEVEL) >= HealingMachineBlock.MAX_CHARGE_LEVEL) 12 else 5 }))
@JvmField
val STADIUM_BLOCK = create("stadium_block", StadiumBlock(BlockBehaviour.Properties.of().mapColor(MapColor.METAL).sound(SoundType.METAL).strength(3.5F, 6.0F).noOcclusion().pushReaction(PushReaction.BLOCK)))
val HEALING_MACHINE = create("healing_machine", HealingMachineBlock(BlockBehaviour.Properties.of().mapColor(MapColor.METAL).sound(SoundType.METAL).pushReaction(PushReaction.BLOCK).strength(2F).noOcclusion().lightLevel { if (it.getValue(HealingMachineBlock.CHARGE_LEVEL) >= HealingMachineBlock.MAX_CHARGE_LEVEL) 12 else 5 }))
@JvmField
val PC = create("pc", PCBlock(BlockBehaviour.Properties.of().mapColor(MapColor.METAL).sound(SoundType.METAL).pushReaction(PushReaction.BLOCK).strength(2F).noOcclusion().lightLevel { if ((it.getValue(PCBlock.ON) as Boolean) && (it.getValue(PCBlock.PART) == PCBlock.PCPart.TOP)) 13 else 0 }))
val TM_MACHINE = create(
"tm_machine",
TMMachineBlock(
BlockBehaviour.Properties.of()
.mapColor(MapColor.COLOR_GREEN)
.sound(SoundType.METAL)
.pushReaction(PushReaction.BLOCK)
.strength(2F)
.noOcclusion()
)
)
@JvmField
val LECTERN = create("lectern", LecternBlock(BlockBehaviour.Properties.of().mapColor(MapColor.WOOD).instrument(NoteBlockInstrument.BASS).sound(SoundType.WOOD).strength(2.5F).ignitedByLava().lightLevel { if (it.getValue(LecternBlock.EMIT_LIGHT) as Boolean) 13 else 0 }))
@JvmField
val DISC_SHELF = create("disc_shelf", DiscShelfBlock(BlockBehaviour.Properties.of().mapColor(MapColor.WOOD).instrument(NoteBlockInstrument.BASS).sound(SoundType.METAL).strength(2.5F)))
@JvmField
val DISPLAY_CASE = create("display_case", DisplayCaseBlock(BlockBehaviour.Properties.of().sound(CobblemonSounds.DISPLAY_CASE_SOUNDS).noOcclusion().pushReaction(PushReaction.BLOCK).mapColor(MapColor.STONE).strength(0.3F).requiresCorrectToolForDrops()))
// TODO after 1.7
// @JvmField
// val INCENSE_SWEET = create("incense_sweet", SweetIncenseBlock(BlockBehaviour.Properties.of().sound(CobblemonSounds.DISPLAY_CASE_SOUNDS).noOcclusion().pushReaction(PushReaction.BLOCK).mapColor(MapColor.STONE).strength(0.3f)))
// val INCENSE_SWEET = create("incense_sweet", SweetIncenseBlock(BlockBehaviour.Properties.of().sound(CobblemonSounds.DISPLAY_CASE_SOUNDS).noOcclusion().pushReaction(PushReaction.BLOCK).mapColor(MapColor.STONE).strength(0.3F)))
@JvmField
val PASTURE = create("pasture", PastureBlock(BlockBehaviour.Properties.of().mapColor(MapColor.COLOR_BROWN).sound(SoundType.WOOD).strength(2F).noOcclusion().pushReaction(PushReaction.BLOCK).lightLevel { if ((it.getValue(PastureBlock.ON) as Boolean) && (it.getValue(PastureBlock.PART) == PastureBlock.PasturePart.TOP)) 13 else 0 }))
@@ -663,8 +777,9 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
private fun apricornBlock(name: String, apricorn: Apricorn): ApricornBlock = this.create(name, ApricornBlock(BlockBehaviour.Properties.of().mapColor(apricorn.mapColor()).randomTicks().strength(Blocks.OAK_LOG.defaultDestroyTime(), Blocks.OAK_LOG.explosionResistance).sound(SoundType.WOOD).noOcclusion(), apricorn))
private fun tumblestoneBlock(name: String, stage: Int, height: Int, xzOffset: Int, nextStage: Block?) : Block {
private fun tumblestoneBlock(name: String, stage: Int, height: Int, xzOffset: Int, nextStage: Block?, mapColor: MapColor) : Block {
return this.create(name, TumblestoneBlock(BlockBehaviour.Properties.of()
.mapColor(mapColor)
.pushReaction(PushReaction.DESTROY)
.noOcclusion()
.strength(1.5F)
@@ -893,4 +1008,28 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
val block = BlocksInvoker.createLeavesBlock(SoundType.GRASS)
return this.create(name, block)
}
}
private fun typeGemBlock(name: String, mapColor: MapColor): Block {
val typeGemBlock = this.create(name, Block(BlockBehaviour.Properties.of().mapColor(mapColor).strength(3.0F, 6.0F).sound(CobblemonSounds.TYPE_GEM_BLOCK_SOUNDS)))
val identifier = cobblemonResource(name)
typeGemBlocks[identifier] = typeGemBlock
return typeGemBlock
}
fun typeGemBlocks() = typeGemBlocks.toMap()
private fun typeGemCluster(name: String, gemBlock: Block, dropItemId: ResourceLocation, mapColor: MapColor): Block {
val gemClusterBlock = this.create(name, TypeGemClusterBlock(BlockBehaviour.Properties.of().mapColor(mapColor).strength(2.0F, 3.0F).sound(CobblemonSounds.TYPE_GEM_CLUSTER_SOUNDS).pushReaction(PushReaction.DESTROY), gemBlock, dropItemId))
TypeGemClusterBlock.gemToClusterMap[gemBlock] = gemClusterBlock
val identifier = cobblemonResource(name)
typeGemClusters[identifier] = gemClusterBlock
return gemClusterBlock
}
fun typeGemClusters() = typeGemClusters.toMap()
}
@@ -15,11 +15,7 @@ import net.minecraft.commands.CommandSourceStack
import net.minecraft.commands.Commands
object CobblemonCommands {
fun register(
dispatcher: CommandDispatcher<CommandSourceStack>,
registry: CommandBuildContext,
selection: Commands.CommandSelection
) {
fun register(dispatcher: CommandDispatcher<CommandSourceStack>, registry: CommandBuildContext, selection: Commands.CommandSelection) {
SpawnPokemon.register(dispatcher)
SpawnNPCCommand.register(dispatcher)
GivePokemon.register(dispatcher)
@@ -75,13 +71,11 @@ object CobblemonCommands {
MarkGiveAllCommand.register(dispatcher)
PcSearchCommand.register(dispatcher)
PcTakeCommand.register(dispatcher)
GiveTmCommand.register(dispatcher)
TmCommand.register(dispatcher)
// Possibly lock down registration if and only if under dev environment or running in an environment
// with a certain system environment variable set
CobblemonInfoCommand.register(dispatcher)
CalculateSeatPositionCommand.register(dispatcher)
CameraDebugCommand.register(dispatcher)
StadiumBattleCommand.register(dispatcher)
MolangUiCommand.register(dispatcher)
}
}
}
@@ -19,6 +19,7 @@ import net.minecraft.server.level.ServerPlayer
import net.minecraft.server.packs.PackType
import net.minecraft.server.packs.resources.PreparableReloadListener
import net.minecraft.tags.TagKey
import net.minecraft.world.inventory.MenuType
import net.minecraft.world.level.GameRules
import net.minecraft.world.level.ItemLike
import net.minecraft.world.level.biome.Biome
@@ -69,6 +69,12 @@ object CobblemonItemComponents : PlatformRegistry<Registry<DataComponentType<*>>
.networkSynchronized(FoodColourComponent.PACKET_CODEC)
.build())
@JvmField
val TM_MOVE: DataComponentType<TMMoveComponent> = create("tm_move", DataComponentType.builder<TMMoveComponent>()
.persistent(TMMoveComponent.CODEC)
.networkSynchronized(TMMoveComponent.PACKET_CODEC)
.build())
@JvmField
val INGREDIENT: DataComponentType<IngredientComponent> = create("ingredient", DataComponentType.builder<IngredientComponent>()
.persistent(IngredientComponent.CODEC)
@@ -101,6 +107,7 @@ object CobblemonItemComponents : PlatformRegistry<Registry<DataComponentType<*>>
Registry.register(BuiltInRegistries.DATA_COMPONENT_TYPE, ResourceLocation.parse("cobblemon:flavour"), FLAVOUR)
Registry.register(BuiltInRegistries.DATA_COMPONENT_TYPE, ResourceLocation.parse("cobblemon:ride_boosts"), RIDE_BOOST)
Registry.register(BuiltInRegistries.DATA_COMPONENT_TYPE, ResourceLocation.parse("cobblemon:food_colour"), FOOD_COLOUR)
Registry.register(BuiltInRegistries.DATA_COMPONENT_TYPE, ResourceLocation.parse("cobblemon:tm_move"), TM_MOVE)
Registry.register(BuiltInRegistries.DATA_COMPONENT_TYPE, ResourceLocation.parse("cobblemon:ingredient"), INGREDIENT)
Registry.register(BuiltInRegistries.DATA_COMPONENT_TYPE, ResourceLocation.parse("cobblemon:food"), FOOD)
Registry.register(BuiltInRegistries.DATA_COMPONENT_TYPE, ResourceLocation.parse("cobblemon:mob_effects"), MOB_EFFECTS)
@@ -21,8 +21,8 @@ import com.cobblemon.mod.common.api.text.gray
import com.cobblemon.mod.common.block.BerryBlock
import com.cobblemon.mod.common.block.MintBlock
import com.cobblemon.mod.common.block.MintBlock.MintType
import com.cobblemon.mod.common.client.pokedex.PokedexType
import com.cobblemon.mod.common.block.campfirepot.CampfirePotColor
import com.cobblemon.mod.common.client.pokedex.PokedexType
import com.cobblemon.mod.common.entity.boat.CobblemonBoatType
import com.cobblemon.mod.common.item.*
import com.cobblemon.mod.common.item.armor.CobblemonArmorTrims
@@ -35,11 +35,9 @@ import com.cobblemon.mod.common.item.berry.HealingBerryItem
import com.cobblemon.mod.common.item.berry.PPRestoringBerryItem
import com.cobblemon.mod.common.item.berry.PortionHealingBerryItem
import com.cobblemon.mod.common.item.berry.StatusCuringBerryItem
import com.cobblemon.mod.common.item.interactive.PonigiriItem
import com.cobblemon.mod.common.item.food.SinisterTeaItem
import com.cobblemon.mod.common.item.interactive.*
import com.cobblemon.mod.common.item.interactive.ability.AbilityChangeItem
import com.cobblemon.mod.common.item.stadium.StadiumPlacementWandItem
import com.cobblemon.mod.common.platform.PlatformRegistry
import com.cobblemon.mod.common.pokeball.PokeBall
import com.cobblemon.mod.common.pokemon.IVs
@@ -76,9 +74,6 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
@JvmField
val NPC_EDITOR = create("npc_editor", CobblemonItem(Item.Properties().stacksTo(1)))
@JvmField
val STADIUM_PLACEMENT_WAND = create("stadium_placement_wand", StadiumPlacementWandItem())
@JvmField
val pokeBalls = mutableListOf<PokeBallItem>()
@JvmField
@@ -410,7 +405,7 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
@JvmField
val BIG_MALASADA = regionalFoodItem("big_malasada", 64, 7, 0.3f, false)
@JvmField
val SMOKED_TAIL_CURRY = regionalFoodItem("smoked_tail_curry", 64, 10, 0.6f, false, ItemStack(Items.BOWL, 1))
val SMOKED_TAIL_CURRY = regionalFoodItem("smoked_tail_curry", 64, 10, 0.6f, false)
@JvmField
val JUBILIFE_MUFFIN = regionalFoodItem("jubilife_muffin", 64, 7, 0.3f, false)
@JvmField
@@ -457,15 +452,19 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
@JvmField
val MONITOR = blockItem("monitor", CobblemonBlocks.MONITOR)
@JvmField
val DAMAGED_MONITOR = blockItem("damaged_monitor", CobblemonBlocks.DAMAGED_MONITOR)
@JvmField
val HEALING_MACHINE = blockItem("healing_machine", CobblemonBlocks.HEALING_MACHINE, Rarity.UNCOMMON)
@JvmField
val PC = blockItem("pc", CobblemonBlocks.PC)
@JvmField
val TM_MACHINE = blockItem("tm_machine", CobblemonBlocks.TM_MACHINE)
@JvmField
val DISC_SHELF = blockItem("disc_shelf", CobblemonBlocks.DISC_SHELF)
@JvmField
val PASTURE = blockItem("pasture", CobblemonBlocks.PASTURE)
@JvmField
val DISPLAY_CASE = blockItem("display_case", CobblemonBlocks.DISPLAY_CASE)
@JvmField
val STADIUM_BLOCK = blockItem("stadium_block", CobblemonBlocks.STADIUM_BLOCK)
// @JvmField
// val INCENSE_SWEET = blockItem("incense_sweet", CobblemonBlocks.INCENSE_SWEET) // TODO after 1.7
@@ -605,6 +604,9 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
@JvmField val BERRY_JUICE = this.create("berry_juice", BerryJuiceItem())
@JvmField
val HABITAT_BLOCK = blockItem("habitat_block", CobblemonBlocks.HABITAT_BLOCK)
@JvmField
val GALARICA_NUTS = compostableItemNameBlockItem("galarica_nuts", CobblemonBlocks.GALARICA_NUT_BUSH)
@@ -1214,6 +1216,83 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
@JvmField
val BLACK_TUMBLESTONE_BLOCK = blockItem("black_tumblestone_block", CobblemonBlocks.BLACK_TUMBLESTONE_BLOCK)
@JvmField
val TYPE_GEM_CORE = blockItem("deepslate_crystal_core", CobblemonBlocks.TYPE_GEM_CORE)
@JvmField
val TYPE_GEM_CLUSTER_NORMAL = blockItem("normal_gem_cluster", CobblemonBlocks.TYPE_GEM_CLUSTER_NORMAL)
@JvmField
val TYPE_GEM_CLUSTER_FIRE = blockItem("fire_gem_cluster", CobblemonBlocks.TYPE_GEM_CLUSTER_FIRE)
@JvmField
val TYPE_GEM_CLUSTER_WATER = blockItem("water_gem_cluster", CobblemonBlocks.TYPE_GEM_CLUSTER_WATER)
@JvmField
val TYPE_GEM_CLUSTER_ELECTRIC = blockItem("electric_gem_cluster", CobblemonBlocks.TYPE_GEM_CLUSTER_ELECTRIC)
@JvmField
val TYPE_GEM_CLUSTER_GRASS = blockItem("grass_gem_cluster", CobblemonBlocks.TYPE_GEM_CLUSTER_GRASS)
@JvmField
val TYPE_GEM_CLUSTER_ICE = blockItem("ice_gem_cluster", CobblemonBlocks.TYPE_GEM_CLUSTER_ICE)
@JvmField
val TYPE_GEM_CLUSTER_FIGHTING = blockItem("fighting_gem_cluster", CobblemonBlocks.TYPE_GEM_CLUSTER_FIGHTING)
@JvmField
val TYPE_GEM_CLUSTER_POISON = blockItem("poison_gem_cluster", CobblemonBlocks.TYPE_GEM_CLUSTER_POISON)
@JvmField
val TYPE_GEM_CLUSTER_GROUND = blockItem("ground_gem_cluster", CobblemonBlocks.TYPE_GEM_CLUSTER_GROUND)
@JvmField
val TYPE_GEM_CLUSTER_FLYING = blockItem("flying_gem_cluster", CobblemonBlocks.TYPE_GEM_CLUSTER_FLYING)
@JvmField
val TYPE_GEM_CLUSTER_PSYCHIC = blockItem("psychic_gem_cluster", CobblemonBlocks.TYPE_GEM_CLUSTER_PSYCHIC)
@JvmField
val TYPE_GEM_CLUSTER_BUG = blockItem("bug_gem_cluster", CobblemonBlocks.TYPE_GEM_CLUSTER_BUG)
@JvmField
val TYPE_GEM_CLUSTER_ROCK = blockItem("rock_gem_cluster", CobblemonBlocks.TYPE_GEM_CLUSTER_ROCK)
@JvmField
val TYPE_GEM_CLUSTER_GHOST = blockItem("ghost_gem_cluster", CobblemonBlocks.TYPE_GEM_CLUSTER_GHOST)
@JvmField
val TYPE_GEM_CLUSTER_DRAGON = blockItem("dragon_gem_cluster", CobblemonBlocks.TYPE_GEM_CLUSTER_DRAGON)
@JvmField
val TYPE_GEM_CLUSTER_DARK = blockItem("dark_gem_cluster", CobblemonBlocks.TYPE_GEM_CLUSTER_DARK)
@JvmField
val TYPE_GEM_CLUSTER_STEEL = blockItem("steel_gem_cluster", CobblemonBlocks.TYPE_GEM_CLUSTER_STEEL)
@JvmField
val TYPE_GEM_CLUSTER_FAIRY = blockItem("fairy_gem_cluster", CobblemonBlocks.TYPE_GEM_CLUSTER_FAIRY)
@JvmField
val TYPE_GEM_BLOCK_NORMAL = blockItem("normal_gem_block", CobblemonBlocks.TYPE_GEM_BLOCK_NORMAL)
@JvmField
val TYPE_GEM_BLOCK_FIRE = blockItem("fire_gem_block", CobblemonBlocks.TYPE_GEM_BLOCK_FIRE)
@JvmField
val TYPE_GEM_BLOCK_WATER = blockItem("water_gem_block", CobblemonBlocks.TYPE_GEM_BLOCK_WATER)
@JvmField
val TYPE_GEM_BLOCK_ELECTRIC = blockItem("electric_gem_block", CobblemonBlocks.TYPE_GEM_BLOCK_ELECTRIC)
@JvmField
val TYPE_GEM_BLOCK_GRASS = blockItem("grass_gem_block", CobblemonBlocks.TYPE_GEM_BLOCK_GRASS)
@JvmField
val TYPE_GEM_BLOCK_ICE = blockItem("ice_gem_block", CobblemonBlocks.TYPE_GEM_BLOCK_ICE)
@JvmField
val TYPE_GEM_BLOCK_FIGHTING = blockItem("fighting_gem_block", CobblemonBlocks.TYPE_GEM_BLOCK_FIGHTING)
@JvmField
val TYPE_GEM_BLOCK_POISON = blockItem("poison_gem_block", CobblemonBlocks.TYPE_GEM_BLOCK_POISON)
@JvmField
val TYPE_GEM_BLOCK_GROUND = blockItem("ground_gem_block", CobblemonBlocks.TYPE_GEM_BLOCK_GROUND)
@JvmField
val TYPE_GEM_BLOCK_FLYING = blockItem("flying_gem_block", CobblemonBlocks.TYPE_GEM_BLOCK_FLYING)
@JvmField
val TYPE_GEM_BLOCK_PSYCHIC = blockItem("psychic_gem_block", CobblemonBlocks.TYPE_GEM_BLOCK_PSYCHIC)
@JvmField
val TYPE_GEM_BLOCK_BUG = blockItem("bug_gem_block", CobblemonBlocks.TYPE_GEM_BLOCK_BUG)
@JvmField
val TYPE_GEM_BLOCK_ROCK = blockItem("rock_gem_block", CobblemonBlocks.TYPE_GEM_BLOCK_ROCK)
@JvmField
val TYPE_GEM_BLOCK_GHOST = blockItem("ghost_gem_block", CobblemonBlocks.TYPE_GEM_BLOCK_GHOST)
@JvmField
val TYPE_GEM_BLOCK_DRAGON = blockItem("dragon_gem_block", CobblemonBlocks.TYPE_GEM_BLOCK_DRAGON)
@JvmField
val TYPE_GEM_BLOCK_DARK = blockItem("dark_gem_block", CobblemonBlocks.TYPE_GEM_BLOCK_DARK)
@JvmField
val TYPE_GEM_BLOCK_STEEL = blockItem("steel_gem_block", CobblemonBlocks.TYPE_GEM_BLOCK_STEEL)
@JvmField
val TYPE_GEM_BLOCK_FAIRY = blockItem("fairy_gem_block", CobblemonBlocks.TYPE_GEM_BLOCK_FAIRY)
@JvmField
val POKEROD_SMITHING_TEMPLATE = create("pokerod_smithing_template", SmithingTemplateItem(
Component.translatable("item.minecraft.fishing_rod").blue(),
@@ -1438,44 +1517,49 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
val RELIC_COIN_POUCH = blockItem("relic_coin_pouch", CobblemonBlocks.RELIC_COIN_POUCH)
@JvmField
val RELIC_COIN_SACK = blockItem("relic_coin_sack", CobblemonBlocks.RELIC_COIN_SACK)
@JvmField
val TECHNICAL_MACHINE = this.create("technical_machine", TechnicalMachineItem(Properties()))
@JvmField
val BLANK_TM = this.create("blank_tm", CobblemonItem(Item.Properties()))
// Type Gems
@JvmField
val NORMAL_GEM = noSettingsItem("normal_gem")
val NORMAL_GEM = this.create("normal_gem", GemItem(Item.Properties(), CobblemonBlocks.TYPE_GEM_CLUSTER_NORMAL))
@JvmField
val FIRE_GEM = noSettingsItem("fire_gem")
val FIRE_GEM = this.create("fire_gem", GemItem(Item.Properties(), CobblemonBlocks.TYPE_GEM_CLUSTER_FIRE))
@JvmField
val WATER_GEM = noSettingsItem("water_gem")
val WATER_GEM = this.create("water_gem", GemItem(Item.Properties(), CobblemonBlocks.TYPE_GEM_CLUSTER_WATER))
@JvmField
val GRASS_GEM = noSettingsItem("grass_gem")
val GRASS_GEM = this.create("grass_gem", GemItem(Item.Properties(), CobblemonBlocks.TYPE_GEM_CLUSTER_GRASS))
@JvmField
val ELECTRIC_GEM = noSettingsItem("electric_gem")
val ELECTRIC_GEM = this.create("electric_gem", GemItem(Item.Properties(), CobblemonBlocks.TYPE_GEM_CLUSTER_ELECTRIC))
@JvmField
val ICE_GEM = noSettingsItem("ice_gem")
val ICE_GEM = this.create("ice_gem", GemItem(Item.Properties(), CobblemonBlocks.TYPE_GEM_CLUSTER_ICE))
@JvmField
val FIGHTING_GEM = noSettingsItem("fighting_gem")
val FIGHTING_GEM = this.create("fighting_gem", GemItem(Item.Properties(), CobblemonBlocks.TYPE_GEM_CLUSTER_FIGHTING))
@JvmField
val POISON_GEM = noSettingsItem("poison_gem")
val POISON_GEM = this.create("poison_gem", GemItem(Item.Properties(), CobblemonBlocks.TYPE_GEM_CLUSTER_POISON))
@JvmField
val GROUND_GEM = noSettingsItem("ground_gem")
val GROUND_GEM = this.create("ground_gem", GemItem(Item.Properties(), CobblemonBlocks.TYPE_GEM_CLUSTER_GROUND))
@JvmField
val FLYING_GEM = noSettingsItem("flying_gem")
val FLYING_GEM = this.create("flying_gem", GemItem(Item.Properties(), CobblemonBlocks.TYPE_GEM_CLUSTER_FLYING))
@JvmField
val PSYCHIC_GEM = noSettingsItem("psychic_gem")
val PSYCHIC_GEM = this.create("psychic_gem", GemItem(Item.Properties(), CobblemonBlocks.TYPE_GEM_CLUSTER_PSYCHIC))
@JvmField
val BUG_GEM = noSettingsItem("bug_gem")
val BUG_GEM = this.create("bug_gem", GemItem(Item.Properties(), CobblemonBlocks.TYPE_GEM_CLUSTER_BUG))
@JvmField
val ROCK_GEM = noSettingsItem("rock_gem")
val ROCK_GEM = this.create("rock_gem", GemItem(Item.Properties(), CobblemonBlocks.TYPE_GEM_CLUSTER_ROCK))
@JvmField
val GHOST_GEM = noSettingsItem("ghost_gem")
val GHOST_GEM = this.create("ghost_gem", GemItem(Item.Properties(), CobblemonBlocks.TYPE_GEM_CLUSTER_GHOST))
@JvmField
val DRAGON_GEM = noSettingsItem("dragon_gem")
val DRAGON_GEM = this.create("dragon_gem", GemItem(Item.Properties(), CobblemonBlocks.TYPE_GEM_CLUSTER_DRAGON))
@JvmField
val DARK_GEM = noSettingsItem("dark_gem")
val DARK_GEM = this.create("dark_gem", GemItem(Item.Properties(), CobblemonBlocks.TYPE_GEM_CLUSTER_DARK))
@JvmField
val STEEL_GEM = noSettingsItem("steel_gem")
val STEEL_GEM = this.create("steel_gem", GemItem(Item.Properties(), CobblemonBlocks.TYPE_GEM_CLUSTER_STEEL))
@JvmField
val FAIRY_GEM = noSettingsItem("fairy_gem")
val FAIRY_GEM = this.create("fairy_gem", GemItem(Item.Properties(), CobblemonBlocks.TYPE_GEM_CLUSTER_FAIRY))
//@JvmField
//val BINDING_SOIL = blockItem("binding_soil", CobblemonBlocks.BINDING_SOIL)
@@ -9,8 +9,8 @@
package com.cobblemon.mod.common
import com.cobblemon.mod.common.api.molangui.container.MolangContainerMenu
import com.cobblemon.mod.common.block.campfirepot.CookingPotMenu
import com.cobblemon.mod.common.block.tmmachine.TMMachineMenu
import com.cobblemon.mod.common.platform.PlatformRegistry
import net.minecraft.core.Registry
import net.minecraft.core.registries.BuiltInRegistries
@@ -20,8 +20,8 @@ import net.minecraft.world.inventory.MenuType
object CobblemonMenuType : PlatformRegistry<Registry<MenuType<*>>, ResourceKey<Registry<MenuType<*>>>, MenuType<*>>() {
val COOKING_POT = MenuType.register("cooking_pot", ::CookingPotMenu)
val MOLANG_UI = MenuType.register("molang_ui", ::MolangContainerMenu)
val COOKING_POT = MenuType.register("cooking_pot_menu", ::CookingPotMenu)
val TM_MACHINE = MenuType.register("tm_machine_menu", ::TMMachineMenu)
override val registry: Registry<MenuType<*>>
get() = BuiltInRegistries.MENU
@@ -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)
}
}
@@ -9,7 +9,6 @@
package com.cobblemon.mod.common
import com.cobblemon.mod.common.api.net.NetworkPacket
import com.cobblemon.mod.common.client.net.CalculateSeatPositionsHandler
import com.cobblemon.mod.common.client.net.OpenBehaviourEditorHandler
import com.cobblemon.mod.common.client.net.PlayerInteractOptionsHandler
import com.cobblemon.mod.common.client.net.SetClientPlayerDataHandler
@@ -18,14 +17,6 @@ import com.cobblemon.mod.common.client.net.battle.*
import com.cobblemon.mod.common.client.net.callback.move.OpenMoveCallbackHandler
import com.cobblemon.mod.common.client.net.callback.party.OpenPartyCallbackHandler
import com.cobblemon.mod.common.client.net.callback.partymove.OpenPartyMoveCallbackHandler
import com.cobblemon.mod.common.client.net.camera.CameraDebugHandler
import com.cobblemon.mod.common.client.net.camera.CameraEndHandler
import com.cobblemon.mod.common.client.net.camera.CameraFocusHandler
import com.cobblemon.mod.common.client.net.camera.CameraStartHandler
import com.cobblemon.mod.common.client.net.camera.CameraStateHandler
import com.cobblemon.mod.common.client.net.camera.CameraTransformHandler
import com.cobblemon.mod.common.client.net.camera.CompositorHandler
import com.cobblemon.mod.common.client.net.camera.SplitScreenHandler
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
@@ -41,10 +32,11 @@ 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
import com.cobblemon.mod.common.client.net.molangui.MolangUiCloseHandler
import com.cobblemon.mod.common.client.net.molangui.MolangUiOpenHandler
import com.cobblemon.mod.common.client.net.molangui.MolangUiUpdateHandler
import com.cobblemon.mod.common.client.net.gui.SetActiveTMPacketHandler
import com.cobblemon.mod.common.client.net.gui.SetTMMachineContainerDataPacketHandler
import com.cobblemon.mod.common.client.net.gui.SummaryUIPacketHandler
import com.cobblemon.mod.common.client.net.gui.SynchronizeActiveTMHandler
import com.cobblemon.mod.common.client.net.habitat.OpenHabitatBlockEditorHandler
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
@@ -54,13 +46,13 @@ 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.ClientboundSeatAssignmentPacketHandler
import com.cobblemon.mod.common.client.net.pokemon.update.ClientboundUpdateRidingStateHandler
import com.cobblemon.mod.common.client.net.pokemon.update.PokemonUpdatePacketHandler
import com.cobblemon.mod.common.client.net.riding.ClientboundUpdateDriverInputHandler
import com.cobblemon.mod.common.client.net.settings.OpenCobblemonConfigEditorHandler
import com.cobblemon.mod.common.client.net.settings.ServerSettingsPacketHandler
import com.cobblemon.mod.common.client.net.sound.UnvalidatedPlaySoundS2CPacketHandler
import com.cobblemon.mod.common.client.net.stadium.OpenStadiumConfigHandler
import com.cobblemon.mod.common.client.net.spawn.SpawnExtraDataEntityHandler
import com.cobblemon.mod.common.client.net.starter.StarterUIPacketHandler
import com.cobblemon.mod.common.client.net.storage.RemoveClientPokemonHandler
@@ -80,20 +72,11 @@ 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
import com.cobblemon.mod.common.net.messages.client.PlayerInteractOptionsPacket
import com.cobblemon.mod.common.net.messages.client.SetClientPlayerDataPacket
import com.cobblemon.mod.common.net.messages.client.animation.PlayPosableAnimationPacket
import com.cobblemon.mod.common.net.messages.client.battle.*
import com.cobblemon.mod.common.net.messages.client.camera.CameraDebugPacket
import com.cobblemon.mod.common.net.messages.client.camera.CameraEndPacket
import com.cobblemon.mod.common.net.messages.client.camera.CameraFocusPacket
import com.cobblemon.mod.common.net.messages.client.camera.CameraStartPacket
import com.cobblemon.mod.common.net.messages.client.camera.CameraStatePacket
import com.cobblemon.mod.common.net.messages.client.camera.CameraTransformPacket
import com.cobblemon.mod.common.net.messages.client.camera.CompositorPacket
import com.cobblemon.mod.common.net.messages.client.camera.SplitScreenPacket
import com.cobblemon.mod.common.net.messages.client.callback.OpenMoveCallbackPacket
import com.cobblemon.mod.common.net.messages.client.callback.OpenPartyCallbackPacket
import com.cobblemon.mod.common.net.messages.client.callback.OpenPartyMoveCallbackPacket
@@ -101,9 +84,6 @@ import com.cobblemon.mod.common.net.messages.client.cooking.SeasoningRegistrySyn
import com.cobblemon.mod.common.net.messages.client.cooking.ToggleCookingPotLidPacket
import com.cobblemon.mod.common.net.messages.client.data.*
import com.cobblemon.mod.common.net.messages.client.debug.RequestOpenRidingStatsDebugGUIPacket
import com.cobblemon.mod.common.net.messages.client.molangui.MolangUiClosePacket
import com.cobblemon.mod.common.net.messages.client.molangui.MolangUiOpenPacket
import com.cobblemon.mod.common.net.messages.client.molangui.MolangUiUpdatePacket
import com.cobblemon.mod.common.net.messages.client.dialogue.DialogueClosedPacket
import com.cobblemon.mod.common.net.messages.client.dialogue.DialogueOpenedPacket
import com.cobblemon.mod.common.net.messages.client.effect.PokeSnackBlockParticlesPacket
@@ -111,6 +91,7 @@ import com.cobblemon.mod.common.net.messages.client.effect.RunPosableMoLangPacke
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.habitat.OpenHabitatBlockEditorPacket
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
@@ -124,9 +105,9 @@ import com.cobblemon.mod.common.net.messages.client.pokedex.ServerConfirmedRegis
import com.cobblemon.mod.common.net.messages.client.pokemon.update.*
import com.cobblemon.mod.common.net.messages.client.pokemon.update.evolution.AddEvolutionPacket
import com.cobblemon.mod.common.net.messages.client.pokemon.update.evolution.ClearEvolutionsPacket
import com.cobblemon.mod.common.net.messages.client.pokemon.update.evolution.ClientboundSeatAssignmentPacket
import com.cobblemon.mod.common.net.messages.client.pokemon.update.evolution.RemoveEvolutionPacket
import com.cobblemon.mod.common.net.messages.client.settings.OpenCobblemonConfigScreenPacket
import com.cobblemon.mod.common.net.messages.client.stadium.OpenStadiumConfigPacket
import com.cobblemon.mod.common.net.messages.client.settings.ServerSettingsPacket
import com.cobblemon.mod.common.net.messages.client.sound.UnvalidatedPlaySoundS2CPacket
import com.cobblemon.mod.common.net.messages.client.spawn.SpawnGenericBedrockPacket
@@ -151,6 +132,7 @@ import com.cobblemon.mod.common.net.messages.client.storage.pc.wallpaper.ChangeP
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.tms.TechnicalMachineRegistrySyncPacket
import com.cobblemon.mod.common.net.messages.client.toast.ToastPacket
import com.cobblemon.mod.common.net.messages.client.trade.TradeAcceptanceChangedPacket
import com.cobblemon.mod.common.net.messages.client.trade.TradeCancelledPacket
@@ -163,8 +145,17 @@ 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.SetActiveTMPacket
import com.cobblemon.mod.common.net.messages.client.ui.SetTMMachineContainerDataPacket
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.client.ui.SynchronizeActiveTMPacket
import com.cobblemon.mod.common.net.messages.server.BattleChallengePacket
import com.cobblemon.mod.common.net.messages.server.BattleChallengeResponsePacket
import com.cobblemon.mod.common.net.messages.server.BenchMovePacket
import com.cobblemon.mod.common.net.messages.server.RequestMoveSwapPacket
import com.cobblemon.mod.common.net.messages.server.RequestPlayerInteractionsPacket
import com.cobblemon.mod.common.net.messages.server.SelectStarterPacket
import com.cobblemon.mod.common.net.messages.server.SendOutPokemonPacket
import com.cobblemon.mod.common.net.messages.server.battle.BattleSelectActionsPacket
import com.cobblemon.mod.common.net.messages.server.battle.BattleTeamLeavePacket
import com.cobblemon.mod.common.net.messages.server.battle.BattleTeamRequestPacket
@@ -174,6 +165,7 @@ 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
import com.cobblemon.mod.common.net.messages.server.block.TMMachineTeachMovePacket
import com.cobblemon.mod.common.net.messages.server.callback.move.MoveSelectCancelledPacket
import com.cobblemon.mod.common.net.messages.server.callback.move.MoveSelectedPacket
import com.cobblemon.mod.common.net.messages.server.callback.party.PartyPokemonSelectedPacket
@@ -186,13 +178,8 @@ import com.cobblemon.mod.common.net.messages.server.debug.ServerboundUpdateRidin
import com.cobblemon.mod.common.net.messages.server.debug.ServerboundUpdateRidingStatsPacket
import com.cobblemon.mod.common.net.messages.server.dialogue.EscapeDialoguePacket
import com.cobblemon.mod.common.net.messages.server.dialogue.InputToDialoguePacket
import com.cobblemon.mod.common.net.messages.server.molangui.MolangUiActionPacket
import com.cobblemon.mod.common.net.messages.server.molangui.MolangUiClosedPacket
import com.cobblemon.mod.common.net.messages.server.molangui.MolangUiVersionPacket
import com.cobblemon.mod.common.net.messages.server.habitat.SaveHabitatBlockSettingsPacket
import com.cobblemon.mod.common.net.messages.server.npc.SaveNPCPacket
import com.cobblemon.mod.common.net.messages.server.stadium.RequestStadiumPlacementWandPacket
import com.cobblemon.mod.common.net.messages.server.stadium.StadiumPlacementSetPacket
import com.cobblemon.mod.common.net.messages.server.stadium.UpdateStadiumBlockPacket
import com.cobblemon.mod.common.net.messages.server.orientation.ServerboundUpdateOrientationPacket
import com.cobblemon.mod.common.net.messages.server.pasture.PasturePokemonPacket
import com.cobblemon.mod.common.net.messages.server.pasture.SetPastureConflictPacket
@@ -209,6 +196,7 @@ import com.cobblemon.mod.common.net.messages.server.pokemon.update.SetNicknamePa
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
import com.cobblemon.mod.common.net.messages.server.riding.ServerboundUpdatePassengerPositionPacket
import com.cobblemon.mod.common.net.messages.server.riding.ServerboundUpdateRiderRotationPacket
import com.cobblemon.mod.common.net.messages.server.starter.RequestStarterScreenPacket
import com.cobblemon.mod.common.net.messages.server.storage.SwapPCPartyPokemonPacket
@@ -235,6 +223,7 @@ import com.cobblemon.mod.common.net.serverhandling.battle.TeamRequestResponseHan
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
import com.cobblemon.mod.common.net.serverhandling.block.TMMachineTeachMoveHandler
import com.cobblemon.mod.common.net.serverhandling.callback.move.MoveSelectCancelledHandler
import com.cobblemon.mod.common.net.serverhandling.callback.move.MoveSelectedHandler
import com.cobblemon.mod.common.net.serverhandling.callback.party.PartyPokemonSelectedHandler
@@ -247,16 +236,10 @@ import com.cobblemon.mod.common.net.serverhandling.debug.ServerboundUpdateRiding
import com.cobblemon.mod.common.net.serverhandling.debug.ServerboundUpdateRidingStatsHandler
import com.cobblemon.mod.common.net.serverhandling.dialogue.EscapeDialogueHandler
import com.cobblemon.mod.common.net.serverhandling.dialogue.InputToDialogueHandler
import com.cobblemon.mod.common.net.serverhandling.molangui.MolangUiActionHandler
import com.cobblemon.mod.common.net.serverhandling.molangui.MolangUiClosedHandler
import com.cobblemon.mod.common.net.serverhandling.molangui.MolangUiVersionHandler
import com.cobblemon.mod.common.net.serverhandling.evolution.AcceptEvolutionHandler
import com.cobblemon.mod.common.net.serverhandling.habitat.SaveHabitatBlockSettingsHandler
import com.cobblemon.mod.common.net.serverhandling.npc.SaveNPCHandler
import com.cobblemon.mod.common.net.serverhandling.stadium.RequestStadiumPlacementWandHandler
import com.cobblemon.mod.common.net.serverhandling.stadium.StadiumPlacementSetHandler
import com.cobblemon.mod.common.net.serverhandling.stadium.UpdateStadiumBlockHandler
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
@@ -271,6 +254,7 @@ import com.cobblemon.mod.common.net.serverhandling.pokemon.update.SetMarkingsHan
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.ServerboundUpdatePassengerPositionHandler
import com.cobblemon.mod.common.net.serverhandling.riding.ServerboundUpdateRiderRotationHandler
import com.cobblemon.mod.common.net.serverhandling.starter.RequestStarterScreenHandler
import com.cobblemon.mod.common.net.serverhandling.starter.SelectStarterPacketHandler
@@ -279,6 +263,7 @@ import com.cobblemon.mod.common.net.serverhandling.storage.RequestMoveSwapHandle
import com.cobblemon.mod.common.net.serverhandling.storage.SendOutPokemonHandler
import com.cobblemon.mod.common.net.serverhandling.storage.SwapPCPartyPokemonHandler
import com.cobblemon.mod.common.net.serverhandling.storage.party.MovePartyPokemonHandler
import com.cobblemon.mod.common.net.serverhandling.storage.party.PartyTutorialPacketHandler
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.*
@@ -357,6 +342,8 @@ object CobblemonNetwork {
list.add(PacketRegisterInfo(MarkingsUpdatePacket.ID, MarkingsUpdatePacket::decode, PokemonUpdatePacketHandler()))
list.add(PacketRegisterInfo(RideBoostsUpdatePacket.ID, RideBoostsUpdatePacket::decode, PokemonUpdatePacketHandler()))
list.add(PacketRegisterInfo(RideStaminaUpdatePacket.ID, RideStaminaUpdatePacket::decode, PokemonUpdatePacketHandler()))
list.add(PacketRegisterInfo(AlphaUpdatePacket.ID, AlphaUpdatePacket::decode, PokemonUpdatePacketHandler()))
list.add(PacketRegisterInfo(ScaleModifierUpdatePacket.ID, ScaleModifierUpdatePacket::decode, PokemonUpdatePacketHandler()))
// Evolution start
list.add(PacketRegisterInfo(AddEvolutionPacket.ID, AddEvolutionPacket::decode, PokemonUpdatePacketHandler()))
@@ -390,6 +377,7 @@ object CobblemonNetwork {
list.add(PacketRegisterInfo(PlayerInteractOptionsPacket.ID, PlayerInteractOptionsPacket::decode, PlayerInteractOptionsHandler))
list.add(PacketRegisterInfo(PokedexUIPacket.ID, PokedexUIPacket::decode, PokedexUIPacketHandler))
list.add(PacketRegisterInfo(ExpGainedDataPacket.ID, ExpGainedDataPacket::decode, ExpGainedDataPacketHandler))
list.add(PacketRegisterInfo(SynchronizeActiveTMPacket.ID, SynchronizeActiveTMPacket::decode, SynchronizeActiveTMHandler))
// Starter packets
list.add(PacketRegisterInfo(OpenStarterUIPacket.ID, OpenStarterUIPacket::decode, StarterUIPacketHandler))
@@ -415,85 +403,9 @@ object CobblemonNetwork {
list.add(PacketRegisterInfo(BattlePersistentStatusPacket.ID, BattlePersistentStatusPacket::decode, BattlePersistentStatusHandler))
list.add(PacketRegisterInfo(BattleMadeInvalidChoicePacket.ID, BattleMadeInvalidChoicePacket::decode, BattleMadeInvalidChoiceHandler))
list.add(PacketRegisterInfo(BattleMusicPacket.ID, BattleMusicPacket::decode, BattleMusicHandler))
list.add(
PacketRegisterInfo(
BattleChallengeExpiredPacket.ID,
BattleChallengeExpiredPacket::decode,
BattleChallengeExpiredHandler
)
)
list.add(
PacketRegisterInfo(
BattleReplacePokemonPacket.ID,
BattleReplacePokemonPacket::decode,
BattleReplacePokemonHandler
)
)
list.add(
PacketRegisterInfo(
BattleTransformPokemonPacket.ID,
BattleTransformPokemonPacket::decode,
BattleTransformPokemonHandler
)
)
// Camera packets
list.add(
PacketRegisterInfo(
CameraStartPacket.ID,
CameraStartPacket::decode,
CameraStartHandler
)
)
list.add(
PacketRegisterInfo(
CameraEndPacket.ID,
CameraEndPacket::decode,
CameraEndHandler
)
)
list.add(
PacketRegisterInfo(
CameraDebugPacket.ID,
CameraDebugPacket::decode,
CameraDebugHandler
)
)
list.add(
PacketRegisterInfo(
CameraTransformPacket.ID,
CameraTransformPacket::decode,
CameraTransformHandler
)
)
list.add(
PacketRegisterInfo(
CameraFocusPacket.ID,
CameraFocusPacket::decode,
CameraFocusHandler
)
)
list.add(
PacketRegisterInfo(
CameraStatePacket.ID,
CameraStatePacket::decode,
CameraStateHandler
)
)
list.add(
PacketRegisterInfo(
SplitScreenPacket.ID,
SplitScreenPacket::decode,
SplitScreenHandler
)
)
list.add(
PacketRegisterInfo(
CompositorPacket.ID,
CompositorPacket::decode,
CompositorHandler
)
)
list.add(PacketRegisterInfo(BattleChallengeExpiredPacket.ID, BattleChallengeExpiredPacket::decode, BattleChallengeExpiredHandler))
list.add(PacketRegisterInfo(BattleReplacePokemonPacket.ID, BattleReplacePokemonPacket::decode, BattleReplacePokemonHandler))
list.add(PacketRegisterInfo(BattleTransformPokemonPacket.ID, BattleTransformPokemonPacket::decode, BattleTransformPokemonHandler))
// MultiBattleTeam Packets
list.add(PacketRegisterInfo(TeamRequestNotificationPacket.ID, TeamRequestNotificationPacket::decode, TeamRequestNotificationHandler))
@@ -531,11 +443,7 @@ object CobblemonNetwork {
list.add(PacketRegisterInfo(BehaviourSyncPacket.ID, BehaviourSyncPacket::decode, DataRegistrySyncPacketHandler()))
list.add(PacketRegisterInfo(MarkRegistrySyncPacket.ID, MarkRegistrySyncPacket::decode, DataRegistrySyncPacketHandler()))
list.add(PacketRegisterInfo(RideSettingsSyncPacket.ID, RideSettingsSyncPacket::decode, RideSettingsSyncHandler))
// Molang UI packets
list.add(PacketRegisterInfo(MolangUiOpenPacket.ID, MolangUiOpenPacket::decode, MolangUiOpenHandler))
list.add(PacketRegisterInfo(MolangUiClosePacket.ID, MolangUiClosePacket::decode, MolangUiCloseHandler))
list.add(PacketRegisterInfo(MolangUiUpdatePacket.ID, MolangUiUpdatePacket::decode, MolangUiUpdateHandler))
list.add(PacketRegisterInfo(TechnicalMachineRegistrySyncPacket.ID, TechnicalMachineRegistrySyncPacket::decode, DataRegistrySyncPacketHandler()))
// Effects
list.add(PacketRegisterInfo(SpawnSnowstormParticlePacket.ID, SpawnSnowstormParticlePacket::decode, SpawnSnowstormParticleHandler))
@@ -566,23 +474,8 @@ object CobblemonNetwork {
list.add(PacketRegisterInfo(OpenPasturePacket.ID, OpenPasturePacket::decode, OpenPastureHandler))
list.add(PacketRegisterInfo(ClosePasturePacket.ID, ClosePasturePacket::decode, ClosePastureHandler))
list.add(PacketRegisterInfo(PokemonPasturedPacket.ID, PokemonPasturedPacket::decode, PokemonPasturedHandler))
list.add(
PacketRegisterInfo(
PokemonUnpasturedPacket.ID,
PokemonUnpasturedPacket::decode,
PokemonUnpasturedHandler
)
)
list.add(
PacketRegisterInfo(
UpdatePastureConflictFlagPacket.ID,
UpdatePastureConflictFlagPacket::decode,
UpdatePastureConflictFlagHandler
)
)
// Stadium
list.add(PacketRegisterInfo(OpenStadiumConfigPacket.ID, OpenStadiumConfigPacket::decode, OpenStadiumConfigHandler))
list.add(PacketRegisterInfo(PokemonUnpasturedPacket.ID, PokemonUnpasturedPacket::decode, PokemonUnpasturedHandler))
list.add(PacketRegisterInfo(UpdatePastureConflictFlagPacket.ID, UpdatePastureConflictFlagPacket::decode, UpdatePastureConflictFlagHandler))
// Orientation
list.add(PacketRegisterInfo(ClientboundUpdateOrientationPacket.ID, ClientboundUpdateOrientationPacket::decode, ClientboundUpdateOrientationHandler))
@@ -613,16 +506,18 @@ object CobblemonNetwork {
// Pokédex scanning
list.add(PacketRegisterInfo(ServerConfirmedRegisterPacket.ID, ServerConfirmedRegisterPacket::decode, ServerConfirmedRegisterHandler))
// Debug / cheats
list.add(PacketRegisterInfo(CalculateSeatPositionsPacket.ID, CalculateSeatPositionsPacket::decode, CalculateSeatPositionsHandler))
// Riding
list.add(PacketRegisterInfo(ClientboundUpdateRidingStatePacket.ID, ClientboundUpdateRidingStatePacket::decode, ClientboundUpdateRidingStateHandler))
list.add(PacketRegisterInfo(ClientboundUpdateDriverInputPacket.ID, ClientboundUpdateDriverInputPacket::decode, ClientboundUpdateDriverInputHandler))
list.add(PacketRegisterInfo(ClientboundSeatAssignmentPacket.ID, ClientboundSeatAssignmentPacket::decode, ClientboundSeatAssignmentPacketHandler))
// Habitat blocks
list.add(PacketRegisterInfo(OpenHabitatBlockEditorPacket.ID, OpenHabitatBlockEditorPacket::decode, OpenHabitatBlockEditorHandler))
// Debug
list.add(PacketRegisterInfo(OpenRidingStatsDebugGUIPacket.ID, OpenRidingStatsDebugGUIPacket::decode, OpenRidingStatsDebugGUIHandler))
return list
}
@@ -702,6 +597,7 @@ object CobblemonNetwork {
// Block entity
list.add(PacketRegisterInfo(AdjustBlockEntityViewerCountPacket.ID, AdjustBlockEntityViewerCountPacket::decode, AdjustBlockEntityViewerCountHandler))
list.add(PacketRegisterInfo(TMMachineTeachMovePacket.ID, TMMachineTeachMovePacket::decode, TMMachineTeachMoveHandler))
// Move select packets
list.add(PacketRegisterInfo(MoveSelectedPacket.ID, MoveSelectedPacket::decode, MoveSelectedHandler))
@@ -734,39 +630,26 @@ object CobblemonNetwork {
list.add(PacketRegisterInfo(DismountPokemonPacket.ID, DismountPokemonPacket::decode, DismountPokemonPacketHandler))
list.add(PacketRegisterInfo(ServerboundUpdateDriverInputPacket.ID, ServerboundUpdateDriverInputPacket::decode, DriverInputPacketHandler))
list.add(PacketRegisterInfo(ServerboundUpdateRiderRotationPacket.ID, ServerboundUpdateRiderRotationPacket::decode, ServerboundUpdateRiderRotationHandler))
list.add(PacketRegisterInfo(ServerboundUpdatePassengerPositionPacket.ID, ServerboundUpdatePassengerPositionPacket::decode, ServerboundUpdatePassengerPositionHandler))
// Cooking
list.add(PacketRegisterInfo(ToggleCookingPotLidPacket.ID, ToggleCookingPotLidPacket::decode, ToggleCookingPotLidHandler))
// TM Machine
list.add(PacketRegisterInfo(SetActiveTMPacket.ID, SetActiveTMPacket::decode, SetActiveTMPacketHandler))
list.add(PacketRegisterInfo(SetTMMachineContainerDataPacket.ID, SetTMMachineContainerDataPacket::decode, SetTMMachineContainerDataPacketHandler))
// Behaviour Packets
list.add(
PacketRegisterInfo(
SetEntityBehaviourPacket.ID,
SetEntityBehaviourPacket::decode,
SetEntityBehaviourHandler
)
)
list.add(
PacketRegisterInfo(
DamageOnCollisionPacket.ID,
DamageOnCollisionPacket::decode,
DamageOnCollisionPacketHandler
)
)
list.add(PacketRegisterInfo(SetEntityBehaviourPacket.ID, SetEntityBehaviourPacket::decode, SetEntityBehaviourHandler))
list.add(PacketRegisterInfo(DamageOnCollisionPacket.ID, DamageOnCollisionPacket::decode, DamageOnCollisionPacketHandler))
// Molang UI packets
list.add(PacketRegisterInfo(MolangUiActionPacket.ID, MolangUiActionPacket::decode, MolangUiActionHandler))
list.add(PacketRegisterInfo(MolangUiClosedPacket.ID, MolangUiClosedPacket::decode, MolangUiClosedHandler))
list.add(PacketRegisterInfo(MolangUiVersionPacket.ID, MolangUiVersionPacket::decode, MolangUiVersionHandler))
// Habitat blocks
list.add(PacketRegisterInfo(SaveHabitatBlockSettingsPacket.ID, SaveHabitatBlockSettingsPacket::decode, SaveHabitatBlockSettingsHandler))
// Stadium
list.add(PacketRegisterInfo(UpdateStadiumBlockPacket.ID, UpdateStadiumBlockPacket::decode, UpdateStadiumBlockHandler))
list.add(PacketRegisterInfo(RequestStadiumPlacementWandPacket.ID, RequestStadiumPlacementWandPacket::decode, RequestStadiumPlacementWandHandler))
list.add(PacketRegisterInfo(StadiumPlacementSetPacket.ID, StadiumPlacementSetPacket::decode, StadiumPlacementSetHandler))
// Debug
// Debug / cheats
list.add(PacketRegisterInfo(RequestOpenRidingStatsDebugGUIPacket.ID, RequestOpenRidingStatsDebugGUIPacket::decode, RequestOpenRidingStatsDebugGUIHandler))
return list
}
@@ -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)
}
}
@@ -30,6 +30,10 @@ object CobblemonPoiTypes: PlatformRegistry<Registry<PoiType>, ResourceKey<Regist
// TODO after 1.7
// @JvmField
// val INCENSE_SWEET_KEY = createKey("incense_sweet", CobblemonBlocks.INCENSE_SWEET, 0, 1)
@JvmField
val HABITAT_BLOCK_KEY: ResourceKey<PoiType> = createKey("habitat_block", CobblemonBlocks.HABITAT_BLOCK, 0, 1)
@JvmField
val HABITAT_BLOCK = create(HABITAT_BLOCK_KEY.location().path, PoiType(getBlockStates(CobblemonBlocks.HABITAT_BLOCK), 0, 1))
private fun createKey(string: String, block: Block, maxTickets: Int, validRange: Int ): ResourceKey<PoiType> =
ResourceKey.create(Registries.POINT_OF_INTEREST_TYPE, cobblemonResource(string)).also { resourceKey ->
@@ -37,6 +37,9 @@ object CobblemonSensors {
@JvmField
val POKEMON_DEFEND_OWNER = register("pokemon_owner_under_attack", ::DefendOwnerSensor)
@JvmField
val ALPHA_LEVEL_MATCHING = register("alpha_level_matching", ::AlphaLevelMatchingSensor)
@JvmField
val NEARBY_GROWABLE_CROPS = register("nearby_growable_crops", ::PokemonGrowableCropSensor)
@@ -108,6 +108,9 @@ object CobblemonSounds : PlatformRegistry<Registry<SoundEvent>, ResourceKey<Regi
@JvmField
val LEVELUP = this.create("gui.levelup")
@JvmField
val MOVE_LEARN = this.create("gui.move_learn")
@JvmField
val PVN_BATTLE = this.create("battle.pvn.default")
@JvmField
@@ -136,6 +139,15 @@ object CobblemonSounds : PlatformRegistry<Registry<SoundEvent>, ResourceKey<Regi
@JvmField
val MULCH_REMOVE = this.create("block.mulch.remove")
@JvmField
val MONITOR_BREAK = this.create("block.monitor.break")
@JvmField
val MONITOR_INSERT = this.create("block.monitor.insert")
@JvmField
val MONITOR_LOADING = this.create("block.monitor.loading")
@JvmField
val MONITOR_GLITCHING = this.create("block.monitor.glitching")
@JvmField
val FOSSIL_MACHINE_ACTIVATE = this.create("block.fossil_machine.activate")
@JvmField
@@ -200,6 +212,28 @@ object CobblemonSounds : PlatformRegistry<Registry<SoundEvent>, ResourceKey<Regi
@JvmField
val TUMBLESTONE_STEP = this.create("block.tumblestone.step")
@JvmField
val TM_USE = this.create("item.tm.use")
@JvmField
val TM_MACHINE_BURN_LOOP = this.create("block.tm_machine.burn_loop")
@JvmField
val TM_MACHINE_CRAFT = this.create("block.tm_machine.craft")
@JvmField
val TM_MACHINE_START = this.create("block.tm_machine.start")
@JvmField
val TM_MACHINE_OPEN = this.create("block.tm_machine.open")
@JvmField
val TM_MACHINE_CLOSE = this.create("block.tm_machine.close")
@JvmField
val TM_MACHINE_TM_INSERT = this.create("block.tm_machine.tm_insert")
@JvmField
val TM_MACHINE_TM_RETRIEVE = this.create("block.tm_machine.tm_retrieve")
@JvmField
val TM_MACHINE_ITEM_INSERT = this.create("block.tm_machine.item_insert")
@JvmField
val TM_MACHINE_ITEM_RETRIEVE = this.create("block.tm_machine.item_retrieve")
@JvmField
val EVOLUTION_STONE_BLOCK_BREAK = this.create("block.evolution_stone_block.break")
@JvmField
@@ -238,6 +272,9 @@ object CobblemonSounds : PlatformRegistry<Registry<SoundEvent>, ResourceKey<Regi
@JvmField
val BERRY_EAT_FULL = this.create("item.berry.eat.full")
@JvmField
val APRICORN_HARVEST = this.create("block.apricorn.harvest")
@JvmField
val BIG_ROOT_BREAK = this.create("block.big_root.break")
@JvmField
@@ -312,9 +349,13 @@ object CobblemonSounds : PlatformRegistry<Registry<SoundEvent>, ResourceKey<Regi
)
@JvmField
val RIDE_LOOP_LEATHER = create("ride.loop.leather")
val RIDE_LOOP_LEATHER_MONO = create("ride.loop.leather.mono")
@JvmField
val RIDE_LOOP_PLUMAGE = create("ride.loop.plumage")
val RIDE_LOOP_PLUMAGE_MONO = create("ride.loop.plumage.mono")
@JvmField
val RIDE_LOOP_LEATHER_STEREO = create("ride.loop.leather.stereo")
@JvmField
val RIDE_LOOP_PLUMAGE_STEREO = create("ride.loop.plumage.stereo")
@JvmField
val MOVE_QUICKATTACK_TARGET = this.create("move.quickattack.target")
@@ -380,6 +421,35 @@ object CobblemonSounds : PlatformRegistry<Registry<SoundEvent>, ResourceKey<Regi
TUMBLESTONE_STEP
)
@JvmField
val TYPE_GEM_BLOCK_BREAK = this.create("block.type_gem_block.break")
@JvmField
val TYPE_GEM_CLUSTER_BREAK = this.create("block.type_gem_cluster.break")
@JvmField
val TYPE_GEM_BLOCK_HIT = this.create("block.type_gem_block.hit")
@JvmField
val TYPE_GEM_BLOCK_PLACE = this.create("block.type_gem_block.place")
@JvmField
val TYPE_GEM_BLOCK_STEP = this.create("block.type_gem_block.step")
@JvmField
val TYPE_GEM_CLUSTER_SOUNDS = SoundType(1f, 1.1f,
TYPE_GEM_CLUSTER_BREAK,
TYPE_GEM_BLOCK_STEP,
TYPE_GEM_BLOCK_PLACE,
TYPE_GEM_BLOCK_HIT,
TYPE_GEM_BLOCK_STEP
)
@JvmField
val TYPE_GEM_BLOCK_SOUNDS = SoundType(1f, 1.1f,
TYPE_GEM_BLOCK_BREAK,
TYPE_GEM_BLOCK_STEP,
TYPE_GEM_BLOCK_PLACE,
TYPE_GEM_BLOCK_HIT,
TYPE_GEM_BLOCK_STEP
)
@JvmField
val EVOLUTION_STONE_BLOCK_SOUNDS = SoundType(1f, 1.1f,
EVOLUTION_STONE_BLOCK_BREAK,
@@ -561,5 +631,31 @@ object CobblemonSounds : PlatformRegistry<Registry<SoundEvent>, ResourceKey<Regi
CAMPFIRE_POT_STEP
)
@JvmField
val ITEM_BLOCK_PAPER_SMALL_PLACE = this.create("block.item_block.paper_small.place")
@JvmField
val ITEM_BLOCK_PAPER_SMALL_BREAK = this.create("block.item_block.paper_small.break")
@JvmField
val ITEM_BLOCK_PAPER_SMALL_SOUNDS = SoundType(1f, 1.1f,
ITEM_BLOCK_PAPER_SMALL_BREAK,
SoundEvents.WOOL_STEP,
ITEM_BLOCK_PAPER_SMALL_PLACE,
SoundEvents.WOOL_HIT,
SoundEvents.WOOL_FALL
)
@JvmField
val ITEM_BLOCK_PAPER_LARGE_PLACE = this.create("block.item_block.paper_large.place")
@JvmField
val ITEM_BLOCK_PAPER_LARGE_BREAK = this.create("block.item_block.paper_large.break")
@JvmField
val ITEM_BLOCK_PAPER_LARGE_SOUNDS = SoundType(1f, 1.1f,
ITEM_BLOCK_PAPER_LARGE_BREAK,
SoundEvents.WOOL_STEP,
ITEM_BLOCK_PAPER_LARGE_PLACE,
SoundEvents.WOOL_HIT,
SoundEvents.WOOL_FALL
)
private fun create(name: String): SoundEvent = this.create(name, SoundEvent.createVariableRangeEvent(cobblemonResource(name)))
}
@@ -32,6 +32,9 @@ object CobblemonCriteria : PlatformRegistry<Registry<CriterionTrigger<*>>, Resou
@JvmField
val CATCH_SHINY_POKEMON = this.create("catch_shiny_pokemon", SimpleCriterionTrigger(CountableCriterion.CODEC))
@JvmField
val CATCH_ALPHA_POKEMON = this.create("catch_alpha_pokemon", SimpleCriterionTrigger(CountableCriterion.CODEC))
@JvmField
val EGG_COLLECT = this.create("eggs_collected", SimpleCriterionTrigger(CountableCriterion.CODEC))
@@ -78,8 +81,20 @@ object CobblemonCriteria : PlatformRegistry<Registry<CriterionTrigger<*>>, Resou
@JvmField
val PLANT_TUMBLESTONE = this.create("plant_tumblestone", SimpleCriterionTrigger(PlantTumblestoneCriterion.CODEC))
@JvmField
val PLANT_TYPE_GEM = this.create("plant_type_gem", SimpleCriterionTrigger(PlantTypeGemCriterion.CODEC))
val RIDING_STAT_BOOST = this.create("riding_stat_boost", SimpleCriterionTrigger(RidingStatBoostCriterion.CODEC))
@JvmField
val LEARN_TM = this.create("has_learn_specific_tm", SimpleCriterionTrigger(LearnTMCriterion.CODEC))
@JvmField
val LEARN_ALL_TM = this.create("has_learn_all_tm", SimpleCriterionTrigger(LearnAllTMCriterion.CODEC))
@JvmField
val LEARN_TM_COUNT = this.create("tms_learned", SimpleCriterionTrigger(CountableCriterion.CODEC))
override val registry = BuiltInRegistries.TRIGGER_TYPES
override val resourceKey = Registries.TRIGGER_TYPE
}
@@ -0,0 +1,50 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.advancement.criterion
import com.cobblemon.mod.common.util.asIdentifierDefaultingNamespace
import com.mojang.serialization.Codec
import com.mojang.serialization.codecs.RecordCodecBuilder
import net.minecraft.advancements.critereon.ContextAwarePredicate
import net.minecraft.advancements.critereon.EntityPredicate
import net.minecraft.resources.ResourceLocation
import net.minecraft.server.level.ServerPlayer
import java.util.Optional
class LearnTMContext(val tm: ResourceLocation)
class LearnTMCriterion(
playerCtx: Optional<ContextAwarePredicate>,
val tm: String
) : SimpleCriterionCondition<LearnTMContext>(playerCtx) {
companion object {
val CODEC: Codec<LearnTMCriterion> = RecordCodecBuilder.create { it.group(
EntityPredicate.ADVANCEMENT_CODEC.optionalFieldOf("player").forGetter(LearnTMCriterion::playerCtx),
Codec.STRING.optionalFieldOf("tm", "any").forGetter(LearnTMCriterion::tm)
).apply(it, ::LearnTMCriterion) }
}
override fun matches(player: ServerPlayer, context: LearnTMContext): Boolean {
return tm == "any" || context.tm == tm.asIdentifierDefaultingNamespace()
}
}
class LearnAllTMContext
class LearnAllTMCriterion(
playerCtx: Optional<ContextAwarePredicate>
) : SimpleCriterionCondition<LearnAllTMContext>(playerCtx) {
companion object {
val CODEC: Codec<LearnAllTMCriterion> = RecordCodecBuilder.create { it.group(
EntityPredicate.ADVANCEMENT_CODEC.optionalFieldOf("player").forGetter(LearnAllTMCriterion::playerCtx)
).apply(it, ::LearnAllTMCriterion) }
}
override fun matches(player: ServerPlayer, context: LearnAllTMContext) = true
}
@@ -14,7 +14,7 @@ import com.mojang.serialization.codecs.RecordCodecBuilder
import net.minecraft.advancements.critereon.ContextAwarePredicate
import net.minecraft.core.BlockPos
import net.minecraft.server.level.ServerPlayer
import java.util.Optional
import java.util.*
class PlantTumblestoneContext(val pos: BlockPos, val block: TumblestoneBlock)
@@ -29,42 +29,6 @@ class PlantTumblestoneCriterion(
}
override fun matches(player: ServerPlayer, context: PlantTumblestoneContext): Boolean {
return context.block.canGrow(context.pos, player.level())
return context.block.canGrow(player.level().getBlockState(context.pos), context.pos, player.level())
}
}
///**
// * A criterion condition for when a tumblestone block is planted
// * @param id The identifier of the criterion
// * @param predicate The predicate for the criterion
// *
// * @author Aethen
// * @since 02/28/2024
// */
//class PlantTumblestoneCriterionCondition(id: Identifier, predicate: LootContextPredicate) :
// SimpleCriterionCondition<PlantTumblestoneContext>(id, predicate) {
// override fun toJson(json: JsonObject) {
// // Add properties to json if needed. None needed for this criterion
// }
//
// override fun fromJson(json: JsonObject) {
// // Parse properties from json if needed. None needed for this criterion
// }
//
// /**
// * Checks if the tumblestone block can grow at the given position
// * @param player The player that planted the tumblestone block
// * @param context The context of the criterion
// * @return True if the tumblestone block can grow at the given position, false otherwise
// */
// override fun matches(player: ServerPlayer, context: PlantTumblestoneContext): Boolean {
// return context.tumbleStoneBlock.canGrow(context.pos, player.level())
// }
//}
//
///**
// * The context of the [PlantTumblestoneCriterionCondition]
// * @param pos The position of the tumblestone block
// * @param tumbleStoneBlock The tumblestone block
// */
//open class PlantTumblestoneContext(var pos: BlockPos, var tumbleStoneBlock: TumblestoneBlock)
}
@@ -0,0 +1,35 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.advancement.criterion
import com.cobblemon.mod.common.block.TypeGemClusterBlock
import com.cobblemon.mod.common.block.TypeGemCoreBlock
import com.mojang.serialization.Codec
import com.mojang.serialization.codecs.RecordCodecBuilder
import net.minecraft.advancements.critereon.ContextAwarePredicate
import net.minecraft.core.BlockPos
import net.minecraft.server.level.ServerPlayer
import java.util.*
class PlantTypeGemContext(val pos: BlockPos, val block: TypeGemClusterBlock)
class PlantTypeGemCriterion(
playerCtx: Optional<ContextAwarePredicate>
): SimpleCriterionCondition<PlantTypeGemContext>(playerCtx) {
companion object {
val CODEC: Codec<PlantTypeGemCriterion> = RecordCodecBuilder.create { it.group(
ContextAwarePredicate.CODEC.optionalFieldOf("player").forGetter(PlantTypeGemCriterion::playerCtx)
).apply(it, ::PlantTypeGemCriterion) }
}
override fun matches(player: ServerPlayer, context: PlantTypeGemContext): Boolean {
return player.level().getBlockState(context.pos).block is TypeGemCoreBlock
}
}
@@ -48,7 +48,7 @@ class RidingStatBoostCriterion(
val max = context.pokemon.pokemon.getMaxRideBoost(rideStat).toDouble()
val min = context.pokemon.pokemon.getBaseRideStat(rideStat).toDouble()
val value = context.pokemon.getRideStat(rideStat, ridingStyle, min, max)
val isSufficient = (value >= this.statValue && this.statValue > 0.0) || !context.pokemon.pokemon.canAddRideBoost(rideStat)
val isSufficient = (value >= this.statValue && this.statValue > 0.0) || !context.pokemon.pokemon.canApplyRideBoost(rideStat)
if (isSufficient && this.rideStat == "any") {
return true
} else if (!isSufficient && this.rideStat == "all") {
@@ -85,9 +85,7 @@ open class PokemonBattle(
/** Whether logging will be silenced for this battle. */
var mute = !CobblemonBuildDetails.SNAPSHOT
val struct = this.asMoLangValue()
val runtime = MoLangRuntime().also {
it.environment.query = struct
}
val runtime = MoLangRuntime().also { it.environment.query = struct }
val onEndHandlers: MutableList<(PokemonBattle) -> Unit> = mutableListOf()
@@ -139,7 +137,6 @@ open class PokemonBattle(
var dispatchResult = GO
val dispatches = ConcurrentLinkedDeque<BattleDispatch>()
val afterDispatches = mutableListOf<() -> Unit>()
val captureActions = mutableListOf<BattleCaptureAction>()
@@ -402,12 +399,10 @@ open class PokemonBattle(
fun dispatch(dispatcher: () -> DispatchResult) {
dispatches.add(BattleDispatch { dispatcher() })
}
fun dispatchToFront(dispatcher: () -> DispatchResult) {
dispatches.addFirst(BattleDispatch { dispatcher() })
}
fun dispatchWaitingToFront(delaySeconds: Float = 1F, dispatcher: () -> Unit) {
@@ -458,21 +453,12 @@ open class PokemonBattle(
dispatches.addFirst(dispatcher)
}
fun doWhenClear(action: () -> Unit) {
afterDispatches.add(action)
}
fun tick() {
try {
while (dispatchResult.canProceed()) {
val dispatch = dispatches.poll() ?: break
dispatchResult = dispatch(this)
}
if (dispatches.isEmpty()) {
afterDispatches.toList().forEach { it() }
afterDispatches.clear()
}
} catch (e: Exception) {
LOGGER.error("Exception while ticking a battle. Saving battle log.", e)
val message = battleLang("crash").red()
@@ -8,8 +8,6 @@
package com.cobblemon.mod.common.api.battles.model.actor
import com.bedrockk.molang.runtime.struct.QueryStruct
import com.bedrockk.molang.runtime.value.StringValue
import com.cobblemon.mod.common.api.battles.model.PokemonBattle
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMoLangValue
import com.cobblemon.mod.common.api.net.NetworkPacket
@@ -26,9 +24,8 @@ import com.cobblemon.mod.common.net.messages.client.battle.BattleMakeChoicePacke
import com.cobblemon.mod.common.net.messages.client.battle.BattleMessagePacket
import net.minecraft.network.chat.Component
import net.minecraft.network.chat.MutableComponent
import net.minecraft.server.level.ServerPlayer
import net.minecraft.world.phys.Vec3
import java.util.UUID
import net.minecraft.server.level.ServerPlayer
abstract class BattleActor(
val uuid: UUID,
@@ -55,11 +52,6 @@ abstract class BattleActor(
var itemsUsed = mutableListOf<BagItem>()
/** For when battles start, it's the number of Pokémon that are still in the process of being sent out (animation wise) */
var stillSendingOutCount = 0
/**
* Optional override for send-out positions. When present the indexes follow the
* actor's active slot order (e.g. slot `a` -> index 0).
*/
var stadiumSendOutPositions: List<Vec3>? = null
abstract val type: ActorType
@@ -82,7 +74,7 @@ abstract class BattleActor(
fun turn() {
val request = request ?: return
responses.clear()
if(activePokemon.any { it.isAlive() }) {
if (activePokemon.any { it.isAlive() }) {
mustChoose = true
sendUpdate(BattleMakeChoicePacket())
}
@@ -96,15 +88,15 @@ abstract class BattleActor(
}
}
fun upkeep() {
fun postUpdate() {
val request = request ?: return
val forceSwitchPokemon = request.forceSwitch.mapIndexedNotNull { index, b -> if (b) activePokemon[index] else null }
if (forceSwitchPokemon.isEmpty()) {
return
}
mustChoose = true // This must happen before the sendUpdate, not after, otherwise AI-driven actors will get locked (they may reply instantly)
sendUpdate(BattleMakeChoicePacket())
mustChoose = true
}
fun setActionResponses(responses: List<ShowdownActionResponse>) {
@@ -160,6 +152,11 @@ abstract class BattleActor(
open fun sendMessage(component: Component) {
sendUpdate(BattleMessagePacket(component))
}
/**
* Called when this actor's Pokemon uses a move. Default implementation does nothing.
* Subclasses (NPC-backed actors, players, etc) may override to trigger animations or UI.
*/
open fun onUseMove(user: BattlePokemon, target: BattlePokemon?) {}
open fun awardExperience(battlePokemon: BattlePokemon, experience: Int) {}
open fun sendUpdate(packet: NetworkPacket<*>) {}
@@ -1,200 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.camera
import com.cobblemon.mod.common.Cobblemon
import net.minecraft.resources.ResourceKey
import net.minecraft.server.MinecraftServer
import net.minecraft.server.level.ServerLevel
import net.minecraft.world.level.ChunkPos
import net.minecraft.world.level.Level
import net.minecraft.world.level.chunk.LevelChunk
import net.minecraft.world.level.chunk.status.ChunkStatus
import java.util.ArrayDeque
import java.util.UUID
/**
* Handles chunk forceloading for cameras.
* Chunks are queued and processed in small batches each tick to avoid overwhelming the server.
*/
object CameraChunkLoader {
private const val MAX_CHUNKS_PER_TICK = 16
private data class CameraState(
var dimension: ResourceKey<Level>,
val chunks: MutableSet<Long>
)
private data class ChunkRequest(
val dimension: ResourceKey<Level>,
val chunkPos: ChunkPos,
val load: Boolean
)
private val cameraStates = mutableMapOf<UUID, CameraState>()
private val chunkOwners = mutableMapOf<ResourceKey<Level>, MutableMap<Long, MutableSet<UUID>>>()
private val pendingRequests: ArrayDeque<ChunkRequest> = ArrayDeque()
private val pendingAsyncLoads = mutableSetOf<Pair<ResourceKey<Level>, Long>>()
fun ensureArea(level: ServerLevel, cameraId: UUID, centerChunk: ChunkPos, radius: Int) {
val dimension = level.dimension()
val state = cameraStates[cameraId]?.takeIf { it.dimension == dimension } ?: run {
cameraStates.remove(cameraId)?.let { oldState ->
oldState.chunks.forEach { chunkLong ->
removeOwnership(oldState.dimension, chunkLong, cameraId)
}
}
CameraState(dimension, mutableSetOf()).also { cameraStates[cameraId] = it }
}
val newChunks = buildChunkSet(centerChunk, radius)
val currentChunks = state.chunks
val toRemove = currentChunks.minus(newChunks)
val toAdd = newChunks.minus(currentChunks)
if (toRemove.isNotEmpty()) {
toRemove.forEach { chunkLong ->
removeOwnership(dimension, chunkLong, cameraId)
currentChunks.remove(chunkLong)
}
}
if (toAdd.isNotEmpty()) {
toAdd.forEach { chunkLong ->
addOwnership(dimension, chunkLong, cameraId)
currentChunks.add(chunkLong)
}
}
}
fun clear(cameraId: UUID) {
val state = cameraStates.remove(cameraId) ?: return
val dimension = state.dimension
state.chunks.forEach { chunkLong ->
removeOwnership(dimension, chunkLong, cameraId)
}
}
fun tick(server: MinecraftServer) {
if (pendingRequests.isEmpty()) {
return
}
var processed = 0
while (processed < MAX_CHUNKS_PER_TICK && pendingRequests.isNotEmpty()) {
val request = pendingRequests.removeFirst()
val level = server.getLevel(request.dimension) ?: continue
level.setChunkForced(request.chunkPos.x, request.chunkPos.z, request.load)
if (request.load) {
scheduleAsyncLoad(level, request.dimension, request.chunkPos)
}
processed++
}
}
private fun addOwnership(dimension: ResourceKey<Level>, chunkLong: Long, cameraId: UUID) {
val ownersForDimension = chunkOwners.computeIfAbsent(dimension) { mutableMapOf() }
val owners = ownersForDimension.computeIfAbsent(chunkLong) { mutableSetOf() }
if (owners.add(cameraId) && owners.size == 1) {
pendingRequests.add(
ChunkRequest(
dimension,
ChunkPos(chunkLong),
true
)
)
}
}
private fun removeOwnership(dimension: ResourceKey<Level>, chunkLong: Long, cameraId: UUID) {
val ownersForDimension = chunkOwners[dimension] ?: return
val owners = ownersForDimension[chunkLong] ?: return
if (!owners.remove(cameraId)) {
return
}
if (owners.isEmpty()) {
ownersForDimension.remove(chunkLong)
if (ownersForDimension.isEmpty()) {
chunkOwners.remove(dimension)
}
pendingRequests.add(
ChunkRequest(
dimension,
ChunkPos(chunkLong),
false
)
)
}
}
private fun scheduleAsyncLoad(level: ServerLevel, dimension: ResourceKey<Level>, chunkPos: ChunkPos) {
val key = dimension to chunkPos.toLong()
if (!pendingAsyncLoads.add(key)) {
return
}
if (Cobblemon.LOGGER.isDebugEnabled) {
Cobblemon.LOGGER.debug(
"[CobblemonCamera] Scheduling async load for chunk {} in {}",
chunkPos,
dimension.location()
)
}
level.chunkSource
.getChunkFuture(chunkPos.x, chunkPos.z, ChunkStatus.FULL, true)
.thenAcceptAsync({ result ->
result.ifSuccess { chunkAccess ->
if (chunkAccess is LevelChunk && Cobblemon.LOGGER.isDebugEnabled) {
Cobblemon.LOGGER.debug(
"[CobblemonCamera] Async loaded chunk {} (light={}, entities={})",
chunkPos,
chunkAccess.isLightCorrect,
chunkAccess.blockEntities.size
)
}
}
pendingAsyncLoads.remove(key)
}, level.server)
.exceptionally { throwable ->
level.server.execute {
pendingAsyncLoads.remove(key)
Cobblemon.LOGGER.warn(
"[CobblemonCamera] Exception while async loading chunk {}: {}",
chunkPos,
throwable.message
)
}
null
}
}
private fun buildChunkSet(centerChunk: ChunkPos, radius: Int): MutableSet<Long> {
val chunks = mutableSetOf<Long>()
for (x in centerChunk.x - radius..centerChunk.x + radius) {
for (z in centerChunk.z - radius..centerChunk.z + radius) {
chunks.add(ChunkPos.asLong(x, z))
}
}
return chunks
}
}
@@ -1,203 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.camera
import com.bedrockk.molang.runtime.MoLangRuntime
import com.bedrockk.molang.runtime.MoParams
import com.bedrockk.molang.runtime.value.MoValue
import com.cobblemon.mod.common.Cobblemon
import com.cobblemon.mod.common.api.camera.integration.server.CameraExecutor
import com.cobblemon.mod.common.api.camera.integration.server.CameraInstance
import com.cobblemon.mod.common.api.camera.integration.server.CameraNetworkSync
import com.cobblemon.mod.common.api.camera.registry.TimelineRegistry
import com.cobblemon.mod.common.api.molang.MoLangFunctions.setup
import net.minecraft.core.SectionPos
import net.minecraft.server.level.ChunkTrackingView
import net.minecraft.server.level.ServerLevel
import net.minecraft.server.level.ServerPlayer
import net.minecraft.util.Mth
import net.minecraft.world.level.ChunkPos
import net.minecraft.world.phys.Vec3
import java.util.UUID
/**
* Server-side camera controller.
*
* Orchestrates camera instance, executor, network sync, and chunk/viewer management.
* Delegates responsibilities to focused components.
*/
class CameraController(
override val id: UUID = UUID.randomUUID(),
val context: Map<String, MoValue> = emptyMap(),
override val origin: Vec3 = Vec3.ZERO,
val queryFunctions: Map<String, java.util.function.Function<MoParams, Any>> = emptyMap()
) : ICameraController {
private val instance: CameraInstance
private val runtime: MoLangRuntime
private lateinit var executor: CameraExecutor
private lateinit var networkSync: CameraNetworkSync
private val viewers = mutableSetOf<UUID>()
private val viewerChunkStates = mutableMapOf<UUID, ViewerChunkState>()
private var level: ServerLevel? = null
init {
runtime = MoLangRuntime().setup()
runtime.environment.query.functions.putAll(queryFunctions)
instance = CameraInstance(id, origin, context, queryFunctions)
executor = CameraExecutor(instance, runtime, context)
networkSync = CameraNetworkSync(id, viewers)
Cobblemon.LOGGER.debug("[CameraController] Initialized $id")
}
private data class ViewerChunkState(
val viewDistance: Int,
var centerChunk: ChunkPos,
var chunkView: ChunkTrackingView
)
override fun startTimeline(timelineId: String): Boolean {
val timeline = TimelineRegistry.getTimeline(timelineId)
if (timeline == null) {
Cobblemon.LOGGER.error("[CameraController] Timeline '$timelineId' not found")
return false
}
return if (instance.startTimeline(timeline)) {
Cobblemon.LOGGER.info("[CameraController] Started '$timelineId'")
true
} else {
Cobblemon.LOGGER.error("[CameraController] Engine start failed for '$timelineId'")
false
}
}
override fun tick() {
val currentLevel = level ?: return
val stillActive = executor.tick(currentLevel, networkSync) { chunkPos ->
updateViewerChunkViews(chunkPos)
}
// If timeline ended, stop the camera and notify all viewers
if (!stillActive && viewers.isNotEmpty()) {
Cobblemon.LOGGER.info("[CameraController] Timeline ended naturally, stopping camera")
stop()
}
}
private fun updateViewerChunkViews(chunkPos: ChunkPos) {
viewerChunkStates.forEach { (viewerId, state) ->
if (state.centerChunk == chunkPos) return@forEach
state.centerChunk = chunkPos
val newView = ChunkTrackingView.of(chunkPos, state.viewDistance)
state.chunkView = newView
CameraManager.registerViewerChunkView(viewerId, newView)
}
val serverLevel = level
if (serverLevel != null && viewerChunkStates.isNotEmpty()) {
val maxDistance = viewerChunkStates.values.maxOf { it.viewDistance }
CameraChunkLoader.ensureArea(serverLevel, id, chunkPos, maxDistance)
}
}
override fun addViewer(player: ServerPlayer) {
viewers.add(player.uuid)
registerViewerChunkView(player, origin)
networkSync.sendStart(origin)
}
/**
* Adds a player as a feed viewer without sending CameraStartPacket.
*
* The player receives transform/focus updates like a normal viewer, but
* the camera will NOT become the primary camera on the client. This is
* used for secondary cameras (e.g. Camera B in split-screen) that render
* to an off-screen RenderTarget via CameraFeedHandler.
*/
fun addFeedViewer(player: ServerPlayer) {
viewers.add(player.uuid)
registerViewerChunkView(player, origin)
// No sendStart() — intentionally skipped so the client doesn't set this as primary
}
private fun registerViewerChunkView(player: ServerPlayer, centerPosition: Vec3) {
val playerLevel = player.serverLevel()
if (level == null || level != playerLevel) {
level?.let { CameraChunkLoader.clear(id) }
level = playerLevel
}
val maxViewDistance = player.server.playerList.viewDistance
val viewDistance = Mth.clamp(player.requestedViewDistance(), 2, maxViewDistance)
val chunkPos = chunkPosFrom(centerPosition)
val chunkView = ChunkTrackingView.of(chunkPos, viewDistance)
viewerChunkStates[player.uuid] = ViewerChunkState(viewDistance, chunkPos, chunkView)
CameraManager.registerViewerChunkView(player.uuid, chunkView)
val maxDistance = viewerChunkStates.values.maxOfOrNull { it.viewDistance } ?: viewDistance
CameraChunkLoader.ensureArea(playerLevel, id, chunkPos, maxDistance)
}
override fun removeViewer(player: ServerPlayer) {
// Send end packet to THIS player specifically
networkSync.sendEndToPlayer(player)
viewers.remove(player.uuid)
viewerChunkStates.remove(player.uuid)
CameraManager.clearViewerChunkView(player.uuid)
if (viewers.isEmpty()) {
CameraChunkLoader.clear(id)
level = null
} else {
val serverLevel = level
if (serverLevel != null && viewerChunkStates.isNotEmpty()) {
val state = viewerChunkStates.values.first()
val maxDistance = viewerChunkStates.values.maxOf { it.viewDistance }
CameraChunkLoader.ensureArea(serverLevel, id, state.centerChunk, maxDistance)
}
}
}
override fun stop() {
instance.stop()
networkSync.sendEnd()
viewerChunkStates.keys.toList().forEach { CameraManager.clearViewerChunkView(it) }
viewerChunkStates.clear()
CameraChunkLoader.clear(id)
level = null
viewers.clear()
}
override fun isActive() = instance.isActive()
fun setFlag(name: String, value: Boolean) = setVariable(name, if (value) 1.0 else 0.0)
override fun setVariable(name: String, value: Double) = instance.setVariable(name, value)
override fun setFocusOverride(position: Vec3?) {
instance.focusOverride = position
}
override fun triggerInstantTransition() = instance.triggerInstantTransition()
override fun addQueryFunctions(functions: Map<String, java.util.function.Function<MoParams, Any>>) {
runtime.environment.query.functions.putAll(functions)
instance.addQueryFunctions(functions)
}
private fun chunkPosFrom(position: Vec3): ChunkPos {
val chunkX = SectionPos.blockToSectionCoord(Mth.floor(position.x))
val chunkZ = SectionPos.blockToSectionCoord(Mth.floor(position.z))
return ChunkPos(chunkX, chunkZ)
}
}
@@ -1,164 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.camera
import com.bedrockk.molang.runtime.MoParams
import com.bedrockk.molang.runtime.value.MoValue
import com.cobblemon.mod.common.Cobblemon
import com.cobblemon.mod.common.api.camera.components.CameraChunkManager
import com.cobblemon.mod.common.api.camera.components.CameraLifecycleManager
import com.cobblemon.mod.common.api.camera.components.CameraViewerManager
import com.cobblemon.mod.common.api.events.CobblemonEvents
import com.cobblemon.mod.common.api.events.camera.CameraStartedEvent
import com.cobblemon.mod.common.api.events.camera.CameraStoppedEvent
import com.cobblemon.mod.common.api.events.camera.CameraViewerAddedEvent
import com.cobblemon.mod.common.api.events.camera.CameraViewerRemovedEvent
import com.cobblemon.mod.common.battles.stadium.StadiumBattleCameraCoordinator
import net.minecraft.server.level.ChunkTrackingView
import net.minecraft.server.level.ServerPlayer
import net.minecraft.world.phys.Vec3
import java.util.UUID
import java.util.function.Function
object CameraManager : ICameraManager {
private val lifecycleManager = CameraLifecycleManager()
private val viewerManager = CameraViewerManager()
private val chunkManager = CameraChunkManager()
override fun startCamera(
timelineId: String,
context: Map<String, MoValue>,
viewers: List<ServerPlayer>,
origin: Vec3,
queryFunctions: Map<String, Function<MoParams, Any>>
): UUID? {
val camera = CameraController(
context = context,
origin = origin,
queryFunctions = queryFunctions
)
val preEvent = CameraStartedEvent.Pre(camera.id, camera, timelineId, viewers)
CobblemonEvents.CAMERA_STARTED_PRE.emit(preEvent)
if (preEvent.isCanceled) {
Cobblemon.LOGGER.info("[CobblemonCamera] Camera start canceled by event listener")
return null
}
if (!camera.startTimeline(timelineId)) {
Cobblemon.LOGGER.warn("[CobblemonCamera] Failed to start timeline '$timelineId'")
return null
}
lifecycleManager.registerCamera(camera)
viewers.forEach { player ->
camera.addViewer(player)
viewerManager.assignViewerToCamera(player.uuid, camera.id)
CobblemonEvents.CAMERA_VIEWER_ADDED.emit(
CameraViewerAddedEvent(camera.id, camera, player)
)
}
CobblemonEvents.CAMERA_STARTED_POST.emit(
CameraStartedEvent.Post(camera.id, camera, timelineId, viewers)
)
Cobblemon.LOGGER.info("[CobblemonCamera] Started camera ${camera.id} with timeline '$timelineId' for ${viewers.size} viewers")
return camera.id
}
override fun addViewerToCamera(player: ServerPlayer, cameraId: UUID): Boolean {
val camera = lifecycleManager.getCamera(cameraId) ?: return false
camera.addViewer(player)
viewerManager.assignViewerToCamera(player.uuid, camera.id)
CobblemonEvents.CAMERA_VIEWER_ADDED.emit(
CameraViewerAddedEvent(camera.id, camera, player)
)
return true
}
override fun stopCamera(cameraId: UUID) {
lifecycleManager.getCamera(cameraId)?.let { camera ->
CobblemonEvents.CAMERA_STOPPED_PRE.emit(
CameraStoppedEvent.Pre(cameraId, camera, CameraStoppedEvent.StopReason.MANUAL)
)
camera.stop()
lifecycleManager.unregisterCamera(cameraId)
viewerManager.removeViewersForCamera(cameraId)
CobblemonEvents.CAMERA_STOPPED_POST.emit(
CameraStoppedEvent.Post(cameraId, camera, CameraStoppedEvent.StopReason.MANUAL)
)
Cobblemon.LOGGER.info("[CobblemonCamera] Stopped camera $cameraId")
}
}
override fun stopCameraForPlayer(player: ServerPlayer) {
viewerManager.getCameraForPlayer(player.uuid)?.let { cameraId ->
lifecycleManager.getCamera(cameraId)?.let { camera ->
camera.removeViewer(player)
viewerManager.removeViewer(player.uuid)
CobblemonEvents.CAMERA_VIEWER_REMOVED.emit(
CameraViewerRemovedEvent(cameraId, camera, player)
)
}
}
}
override fun getPlayerCamera(player: ServerPlayer): ICameraController? {
val cameraId = viewerManager.getCameraForPlayer(player.uuid) ?: return null
return lifecycleManager.getCamera(cameraId)
}
override fun getCamera(cameraId: UUID): ICameraController? {
return lifecycleManager.getCamera(cameraId)
}
override fun tick() {
lifecycleManager.tick()
StadiumBattleCameraCoordinator.tickSecondaryCameras()
}
override fun clear() {
lifecycleManager.clear()
viewerManager.clear()
chunkManager.clear()
}
internal fun registerViewerChunkView(playerId: UUID, newView: ChunkTrackingView) {
chunkManager.registerViewerChunkView(playerId, newView)
}
internal fun clearViewerChunkView(playerId: UUID) {
chunkManager.clearViewerChunkView(playerId)
}
@JvmStatic
fun getPlayerChunkView(player: ServerPlayer): ChunkTrackingView? {
return chunkManager.getPlayerChunkView(player.uuid)
}
@JvmStatic
fun consumeChunkViewUpdate(player: ServerPlayer): ChunkViewUpdate? {
return chunkManager.consumeChunkViewUpdate(player.uuid)?.let {
ChunkViewUpdate(it.previous, it.current)
}
}
data class ChunkViewUpdate(val previous: ChunkTrackingView?, val current: ChunkTrackingView?)
}
@@ -1,20 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.camera
/**
* Represents a camera rotation in 3D space.
*
* @property yaw Horizontal rotation (left/right) in degrees
* @property pitch Vertical rotation (up/down) in degrees
*/
data class CameraRotation(
val yaw: Float,
val pitch: Float
)
@@ -1,43 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.camera
import com.cobblemon.mod.common.Cobblemon
import com.cobblemon.mod.common.api.camera.model.CameraTrack
import com.google.gson.JsonObject
object CameraTrackRegistry {
private val trackDeserializers = mutableMapOf<String, (JsonObject) -> CameraTrack>()
fun registerTrackType(trackType: String, deserializer: (JsonObject) -> CameraTrack) {
if (trackDeserializers.containsKey(trackType)) {
Cobblemon.LOGGER.warn("[CameraTrackRegistry] Track type '$trackType' is already registered, overwriting")
}
trackDeserializers[trackType] = deserializer
Cobblemon.LOGGER.debug("[CameraTrackRegistry] Registered camera track type: $trackType")
}
fun deserializeTrack(trackType: String, json: JsonObject): CameraTrack? {
val deserializer = trackDeserializers[trackType]
if (deserializer == null) {
Cobblemon.LOGGER.warn("[CameraTrackRegistry] Unknown track type: $trackType")
return null
}
return try {
deserializer(json)
} catch (e: Exception) {
Cobblemon.LOGGER.error("[CameraTrackRegistry] Failed to deserialize track type '$trackType': ${e.message}", e)
null
}
}
fun getRegisteredTrackTypes(): Set<String> = trackDeserializers.keys.toSet()
fun isTrackTypeRegistered(trackType: String): Boolean = trackDeserializers.containsKey(trackType)
}
@@ -1,32 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.camera
import com.bedrockk.molang.runtime.MoParams
import net.minecraft.server.level.ServerPlayer
import net.minecraft.world.phys.Vec3
import java.util.UUID
import java.util.function.Function
interface ICameraController {
val id: UUID
val origin: Vec3
fun startTimeline(timelineId: String): Boolean
fun tick()
fun stop()
fun isActive(): Boolean
fun addViewer(player: ServerPlayer)
fun removeViewer(player: ServerPlayer)
fun setVariable(name: String, value: Double)
fun setFocusOverride(position: Vec3?)
/** Triggers an instant camera transition (no client-side interpolation) on the next tick. */
fun triggerInstantTransition()
/** Injects additional MoLang query functions into the camera's runtime after creation. */
fun addQueryFunctions(functions: Map<String, Function<MoParams, Any>>)
}
@@ -1,17 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.camera
import java.util.UUID
interface ICameraCoordinator {
fun bind(cameraId: UUID)
fun release()
fun getCameraId(): UUID?
}
@@ -1,34 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.camera
import com.bedrockk.molang.runtime.MoParams
import com.bedrockk.molang.runtime.value.MoValue
import net.minecraft.server.level.ServerPlayer
import net.minecraft.world.phys.Vec3
import java.util.UUID
import java.util.function.Function
interface ICameraManager {
fun startCamera(
timelineId: String,
context: Map<String, MoValue> = emptyMap(),
viewers: List<ServerPlayer> = emptyList(),
origin: Vec3 = Vec3.ZERO,
queryFunctions: Map<String, Function<MoParams, Any>> = emptyMap()
): UUID?
fun addViewerToCamera(player: ServerPlayer, cameraId: UUID): Boolean
fun stopCamera(cameraId: UUID)
fun stopCameraForPlayer(player: ServerPlayer)
fun getPlayerCamera(player: ServerPlayer): ICameraController?
fun getCamera(cameraId: UUID): ICameraController?
fun tick()
fun clear()
}
@@ -1,45 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.camera.components
import net.minecraft.server.level.ChunkTrackingView
import java.util.UUID
import java.util.concurrent.ConcurrentHashMap
class CameraChunkManager {
private val playerChunkViews = ConcurrentHashMap<UUID, ChunkTrackingView>()
private val chunkViewUpdates = ConcurrentHashMap<UUID, ChunkViewUpdate>()
data class ChunkViewUpdate(val previous: ChunkTrackingView?, val current: ChunkTrackingView?)
fun registerViewerChunkView(playerId: UUID, newView: ChunkTrackingView) {
val previous = playerChunkViews.put(playerId, newView)
if (previous == null || previous != newView) {
chunkViewUpdates[playerId] = ChunkViewUpdate(previous, newView)
}
}
fun clearViewerChunkView(playerId: UUID) {
val previous = playerChunkViews.remove(playerId)
if (previous != null) {
chunkViewUpdates[playerId] = ChunkViewUpdate(previous, null)
}
}
fun getPlayerChunkView(playerId: UUID): ChunkTrackingView? = playerChunkViews[playerId]
fun consumeChunkViewUpdate(playerId: UUID): ChunkViewUpdate? = chunkViewUpdates.remove(playerId)
fun clear() {
playerChunkViews.clear()
chunkViewUpdates.clear()
}
}
@@ -1,58 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.camera.components
import com.cobblemon.mod.common.api.camera.ICameraController
import com.cobblemon.mod.common.api.events.CobblemonEvents
import com.cobblemon.mod.common.api.events.camera.CameraStoppedEvent
import java.util.UUID
import java.util.concurrent.ConcurrentHashMap
class CameraLifecycleManager {
private val cameras = ConcurrentHashMap<UUID, ICameraController>()
fun registerCamera(camera: ICameraController) {
cameras[camera.id] = camera
}
fun unregisterCamera(cameraId: UUID): ICameraController? {
return cameras.remove(cameraId)
}
fun getCamera(cameraId: UUID): ICameraController? = cameras[cameraId]
fun getAllCameras(): Collection<ICameraController> = cameras.values
fun tick() {
cameras.values.forEach { it.tick() }
cameras.entries.removeIf { (id, camera) ->
if (!camera.isActive()) {
CobblemonEvents.CAMERA_STOPPED_POST.emit(
CameraStoppedEvent.Post(id, camera, CameraStoppedEvent.StopReason.COMPLETED)
)
true
} else {
false
}
}
}
fun clear() {
cameras.values.forEach {
it.stop()
CobblemonEvents.CAMERA_STOPPED_POST.emit(
CameraStoppedEvent.Post(it.id, it, CameraStoppedEvent.StopReason.MANUAL)
)
}
cameras.clear()
}
fun size(): Int = cameras.size
}
@@ -1,36 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.camera.components
import java.util.UUID
import java.util.concurrent.ConcurrentHashMap
class CameraViewerManager {
private val playerCameras = ConcurrentHashMap<UUID, UUID>()
fun assignViewerToCamera(playerId: UUID, cameraId: UUID) {
playerCameras[playerId] = cameraId
}
fun removeViewer(playerId: UUID): UUID? {
return playerCameras.remove(playerId)
}
fun getCameraForPlayer(playerId: UUID): UUID? {
return playerCameras[playerId]
}
fun removeViewersForCamera(cameraId: UUID) {
playerCameras.entries.removeIf { it.value == cameraId }
}
fun clear() {
playerCameras.clear()
}
}
@@ -1,591 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.camera.engine
import com.bedrockk.molang.runtime.MoLangRuntime
import com.bedrockk.molang.runtime.value.DoubleValue
import com.bedrockk.molang.runtime.value.MoValue
import com.bedrockk.molang.runtime.value.StringValue
import com.cobblemon.mod.common.Cobblemon
import com.cobblemon.mod.common.api.camera.CameraRotation
import com.cobblemon.mod.common.api.camera.model.*
import com.cobblemon.mod.common.api.camera.result.ValidationError
import com.cobblemon.mod.common.api.camera.track.EventTrack
import com.cobblemon.mod.common.api.camera.track.FiredGuiAction
import com.cobblemon.mod.common.api.camera.track.GuiTrack
import com.cobblemon.mod.common.api.tween.EasingRegistry
import com.cobblemon.mod.common.client.camera.CameraInterpolationUtils
import com.cobblemon.mod.common.util.resolve
import com.cobblemon.mod.common.util.resolveBoolean
import net.minecraft.world.phys.Vec3
import java.util.*
import java.util.concurrent.ConcurrentHashMap
/**
* Thread-safe timeline execution engine.
*
* Uses immutable state snapshots for thread safety. MoLang evaluation is NOT
* thread-safe - callers must ensure tick() is called from the same thread.
*
* @param id Unique identifier for this engine instance
* @param timeline The timeline to execute
* @param origin The world position origin for relative coordinates
* @param runtime The MoLang runtime for expression evaluation
* @param providedContext Initial context values (parameter values) to inject into MoLang
*/
class TimelineEngine(
val id: UUID,
private val timeline: Timeline,
val origin: Vec3,
private val runtime: MoLangRuntime,
private val providedContext: Map<String, MoValue> = emptyMap()
) {
@Volatile
private var state: ExecutionState = ExecutionState.Stopped
private var previousExecutionState: ExecutionState.Playing? = null
private var instantTransitionOccurred = false
private val customVariables = ConcurrentHashMap<String, Double>()
/** GUI actions fired during the current tick, consumed by the executor. */
private val pendingGuiActions = mutableListOf<FiredGuiAction>()
private val timeOnCurrentPathValue = DoubleValue(0.0)
private val totalTimeValue = DoubleValue(0.0)
private val runnerIdValue = StringValue(id.toString())
fun start(): Boolean {
if (state !is ExecutionState.Stopped) {
Cobblemon.LOGGER.warn("[TimelineEngine] Cannot start: already active (id=$id)")
return false
}
val errors = timeline.validate()
if (errors.any { it.severity == ValidationError.Severity.ERROR }) {
Cobblemon.LOGGER.error("[TimelineEngine] Timeline '${timeline.id}' validation failed: ${errors.joinToString { it.toString() }}")
return false
}
if (!validateAndInjectParameters()) {
return false
}
val startState = timeline.getState(timeline.startStateId)
if (startState == null) {
Cobblemon.LOGGER.error("[TimelineEngine] Start state '${timeline.startStateId}' not found in timeline '${timeline.id}'")
return false
}
state = ExecutionState.Playing(
currentState = startState,
stateTime = 0f,
totalTime = 0f,
lastTickNanos = System.nanoTime(),
transitionState = TransitionState.None,
progressMemory = emptyMap(),
executedEvents = emptySet()
)
Cobblemon.LOGGER.info("[TimelineEngine] Started timeline '${timeline.id}' in state '${startState.id}'")
return true
}
/**
* Validates that all required parameters are provided and injects parameters
* (including defaults) into the MoLang runtime.
*/
private fun validateAndInjectParameters(): Boolean {
if (timeline.parameters.isEmpty()) return true
val providedVarNames = providedContext.keys
val missingParams = timeline.validateParameters(providedVarNames)
if (missingParams.isNotEmpty()) {
Cobblemon.LOGGER.error("[TimelineEngine] Timeline '${timeline.id}' missing required parameters: ${missingParams.joinToString(", ")}")
return false
}
providedContext.forEach { (name, value) ->
runtime.environment.variable.map[name] = value
}
for ((paramName, definition) in timeline.parameters) {
val default = definition.default ?: continue
when (default) {
is ParameterDefault.NumberDefault -> {
if (paramName !in providedVarNames) {
runtime.environment.variable.map[paramName] = DoubleValue(default.value)
Cobblemon.LOGGER.debug("[TimelineEngine] Using default for parameter '$paramName': ${default.value}")
}
}
is ParameterDefault.Vec3Default -> {
val varNames = definition.getVariableNames(paramName)
val xVar = varNames[0]
val yVar = varNames[1]
val zVar = varNames[2]
if (xVar !in providedVarNames) {
runtime.environment.variable.map[xVar] = DoubleValue(default.x)
}
if (yVar !in providedVarNames) {
runtime.environment.variable.map[yVar] = DoubleValue(default.y)
}
if (zVar !in providedVarNames) {
runtime.environment.variable.map[zVar] = DoubleValue(default.z)
}
if (xVar !in providedVarNames || yVar !in providedVarNames || zVar !in providedVarNames) {
Cobblemon.LOGGER.debug("[TimelineEngine] Using default for parameter '$paramName': (${default.x}, ${default.y}, ${default.z})")
}
}
}
}
return true
}
fun tick(): CameraTransform? {
val current = state
if (current !is ExecutionState.Playing) {
return null
}
previousExecutionState = current
instantTransitionOccurred = false
val nowNanos = System.nanoTime()
val deltaNanos = nowNanos - current.lastTickNanos
val deltaSeconds = (deltaNanos / 1_000_000_000.0).toFloat()
.coerceIn(0f, 0.5f)
val newStateTime = current.stateTime + deltaSeconds * current.currentState.speed
val newTotalTime = current.totalTime + deltaSeconds
val transitionResult = checkTransitions(current, newStateTime, newTotalTime)
if (transitionResult is TransitionCheckResult.TransitionNow) {
val targetState = timeline.getState(transitionResult.targetStateId)
?: run {
Cobblemon.LOGGER.error("[TimelineEngine] Transition target state '${transitionResult.targetStateId}' not found")
return null
}
state = when (transitionResult.type) {
TransitionType.INSTANT -> {
instantTransitionOccurred = true
val savedSnapshot = if (targetState.rememberProgress) {
current.progressMemory[targetState.id]
} else null
val restoredTime = savedSnapshot?.normalizedProgress?.let {
it * targetState.getEffectiveDuration()
} ?: 0f
val restoredFocus = savedSnapshot?.lastFocus
val currentSnapshot = StateSnapshot(
normalizedProgress = normalizeProgress(current.stateTime, current.currentState),
lastFocus = current.lastEvaluatedFocus
)
ExecutionState.Playing(
currentState = targetState,
stateTime = restoredTime,
totalTime = newTotalTime,
lastTickNanos = nowNanos,
transitionState = TransitionState.None,
progressMemory = current.progressMemory + (current.currentState.id to currentSnapshot),
executedEvents = if (targetState.rememberProgress) current.executedEvents else emptySet(),
lastEvaluatedFocus = restoredFocus
)
}
TransitionType.BLEND -> {
val currentTransform = evaluateState(current.currentState, current.stateTime)
ExecutionState.Playing(
currentState = current.currentState,
stateTime = newStateTime,
totalTime = newTotalTime,
lastTickNanos = nowNanos,
transitionState = TransitionState.Blending(
targetState = targetState,
startTime = newTotalTime,
duration = transitionResult.blendDuration,
startTransform = currentTransform
),
progressMemory = current.progressMemory,
executedEvents = current.executedEvents
)
}
}
} else {
val effectiveDuration = current.currentState.getEffectiveDuration()
val (finalStateTime, finalEvents) = if (current.currentState.isLooping && effectiveDuration > 0f && newStateTime >= effectiveDuration) {
newStateTime % effectiveDuration to emptySet<EventKey>()
} else {
val clampedTime = if (!current.currentState.isLooping && effectiveDuration > 0f) {
newStateTime.coerceAtMost(effectiveDuration)
} else {
newStateTime
}
clampedTime to current.executedEvents
}
state = current.copy(
stateTime = finalStateTime,
totalTime = newTotalTime,
lastTickNanos = nowNanos,
executedEvents = finalEvents
)
}
val updatedState = state
if (updatedState is ExecutionState.Playing && updatedState.transitionState is TransitionState.Blending) {
val blend = updatedState.transitionState
val blendProgress = if (blend.duration > 0f) {
((updatedState.totalTime - blend.startTime) / blend.duration).coerceIn(0f, 1f)
} else 1f
if (blendProgress >= 1f) {
val savedSnapshot = updatedState.progressMemory[blend.targetState.id]
val restoredTime = if (blend.targetState.rememberProgress && savedSnapshot != null) {
savedSnapshot.normalizedProgress * blend.targetState.getEffectiveDuration()
} else 0f
val currentSnapshot = StateSnapshot(
normalizedProgress = normalizeProgress(updatedState.stateTime, updatedState.currentState),
lastFocus = null
)
state = ExecutionState.Playing(
currentState = blend.targetState,
stateTime = restoredTime,
totalTime = updatedState.totalTime,
lastTickNanos = nowNanos,
transitionState = TransitionState.None,
progressMemory = updatedState.progressMemory + (updatedState.currentState.id to currentSnapshot),
executedEvents = if (blend.targetState.rememberProgress) updatedState.executedEvents else emptySet()
)
}
}
executeEvents()
executeGuiActions()
return calculateTransform()
}
fun stop() {
state = ExecutionState.Stopped
customVariables.clear()
// Clear MoLang runtime to prevent memory leaks
runtime.environment.variable.map.clear()
runtime.environment.query.functions.clear()
}
fun setVariable(name: String, value: Double) {
customVariables[name] = value
}
/** Triggers an instant transition on the next update (no client-side interpolation). */
fun triggerInstantTransition() {
instantTransitionOccurred = true
}
fun isActive(): Boolean = state is ExecutionState.Playing
fun getCurrentStateId(): String? = (state as? ExecutionState.Playing)?.currentState?.id
fun getCurrentRenderPlayerBody(): Boolean = (state as? ExecutionState.Playing)?.currentState?.renderPlayerBody ?: true
fun getCurrentHiddenHudElements(): Set<HudElement> = (state as? ExecutionState.Playing)?.currentState?.hiddenHudElements ?: emptySet()
fun consumeInstantTransitionFlag(): Boolean {
val result = instantTransitionOccurred
instantTransitionOccurred = false
return result
}
private fun checkTransitions(
current: ExecutionState.Playing,
newStateTime: Float,
newTotalTime: Float
): TransitionCheckResult {
if (current.transitionState !is TransitionState.None) {
return TransitionCheckResult.NoTransition
}
val context = createMoLangContext(current.currentState, newStateTime, newTotalTime)
for (transition in timeline.getTransitionsFrom(current.currentState.id)) {
try {
val shouldTransition = runtime.resolveBoolean(transition.condition, context)
if (shouldTransition) {
return TransitionCheckResult.TransitionNow(
targetStateId = transition.targetStateId,
type = transition.type,
blendDuration = transition.blendDuration
)
}
} catch (e: Exception) {
Cobblemon.LOGGER.error("[TimelineEngine] Error evaluating transition condition: ${e.message}", e)
}
}
return TransitionCheckResult.NoTransition
}
private fun executeEvents() {
val current = state as? ExecutionState.Playing ?: return
val previousState = previousExecutionState ?: return
val context = createMoLangContext(current.currentState, current.stateTime, current.totalTime)
val previousTime = previousState.stateTime
val currentTime = current.stateTime
current.currentState.tracks.filterIsInstance<EventTrack>().forEach { track ->
track.events.forEach { timedEvent ->
val eventKey = EventKey(current.currentState.id, timedEvent.eventId, timedEvent.time.toInt())
if (eventKey in current.executedEvents) return@forEach
val crossedEvent = if (previousTime <= currentTime) {
timedEvent.time in previousTime..currentTime
} else {
timedEvent.time <= currentTime
}
if (crossedEvent) {
try {
runtime.resolve(timedEvent.expression, context)
state = current.copy(
executedEvents = current.executedEvents + eventKey
)
if (timedEvent.eventId != null) {
Cobblemon.LOGGER.debug("[TimelineEngine] Executed event '${timedEvent.eventId}' at time ${timedEvent.time}s")
}
} catch (e: Exception) {
Cobblemon.LOGGER.error("[TimelineEngine] Failed to execute event: ${e.message}", e)
}
}
}
}
}
/**
* Checks GUI tracks for actions whose time has been crossed and queues them.
* Follows the same pattern as [executeEvents].
*/
private fun executeGuiActions() {
val current = state as? ExecutionState.Playing ?: return
val previousState = previousExecutionState ?: return
val previousTime = previousState.stateTime
val currentTime = current.stateTime
current.currentState.tracks.filterIsInstance<GuiTrack>().forEach { track ->
track.actions.forEach { guiAction ->
val actionKey = EventKey(current.currentState.id, "gui_${guiAction.guiId}_${guiAction.action}", guiAction.time.toInt())
if (actionKey in current.executedEvents) return@forEach
val crossedAction = if (previousTime <= currentTime) {
guiAction.time in previousTime..currentTime
} else {
guiAction.time <= currentTime
}
if (crossedAction) {
pendingGuiActions.add(FiredGuiAction(
action = guiAction.action,
guiId = guiAction.guiId,
args = guiAction.args,
argsExpressions = guiAction.argsExpressions
))
state = current.copy(
executedEvents = current.executedEvents + actionKey
)
Cobblemon.LOGGER.debug("[TimelineEngine] Fired GUI action ${guiAction.action} for '${guiAction.guiId}' at time ${guiAction.time}s")
}
}
}
}
/**
* Consumes and returns all pending GUI actions since the last tick.
* Called by the CameraExecutor after tick().
*/
fun consumeGuiActions(): List<FiredGuiAction> {
if (pendingGuiActions.isEmpty()) return emptyList()
val actions = pendingGuiActions.toList()
pendingGuiActions.clear()
return actions
}
private fun calculateTransform(): CameraTransform {
val current = state as? ExecutionState.Playing ?: return CameraTransform(origin, null, null)
return when (val transition = current.transitionState) {
is TransitionState.None -> {
evaluateState(current.currentState, current.stateTime)
}
is TransitionState.Blending -> {
val targetTransform = evaluateState(transition.targetState, 0f)
val progress = if (transition.duration > 0f) {
((current.totalTime - transition.startTime) / transition.duration).coerceIn(0f, 1f)
} else 1f
val easedProgress = EasingRegistry.easeOutQuad(progress)
blendTransforms(transition.startTransform, targetTransform, easedProgress)
}
}
}
private fun evaluateState(state: State, time: Float): CameraTransform {
val context = createMoLangContext(state, time, (this.state as? ExecutionState.Playing)?.totalTime ?: 0f)
var position: Vec3? = null
var focus: CameraFocus? = null
var rotation: CameraRotation? = null
for (track in state.tracks) {
val outputs = track.evaluate(time, context, runtime, origin)
for (output in outputs) {
when (output) {
is TrackOutput.Position -> {
if (position == null) position = output.position
}
is TrackOutput.Focus -> {
if (focus == null) focus = output.target
}
is TrackOutput.Rotation -> {
if (rotation == null) rotation = output.rotation
}
is TrackOutput.Event -> {
// Events handled separately
}
}
}
}
return CameraTransform(
position = position ?: origin,
focus = focus,
rotation = rotation
)
}
private fun blendTransforms(
from: CameraTransform,
to: CameraTransform,
progress: Float
): CameraTransform {
val blendedPosition = CameraInterpolationUtils.lerpPosition(from.position, to.position, progress)
val blendedRotation = if (from.rotation != null && to.rotation != null) {
CameraInterpolationUtils.slerpRotation(from.rotation, to.rotation, progress)
} else {
to.rotation ?: from.rotation
}
return CameraTransform(
position = blendedPosition,
focus = to.focus ?: from.focus,
rotation = blendedRotation
)
}
private fun createMoLangContext(
state: State,
stateTime: Float,
totalTime: Float
): Map<String, MoValue> {
timeOnCurrentPathValue.value = stateTime.toDouble()
totalTimeValue.value = totalTime.toDouble()
runtime.environment.variable.apply {
map["time_on_current_path"] = timeOnCurrentPathValue
map["total_time"] = totalTimeValue
map["runner_id"] = runnerIdValue
customVariables.forEach { (name, value) ->
map[name] = DoubleValue(value)
}
}
return emptyMap() // Context passed via runtime.environment
}
private fun normalizeProgress(time: Float, state: State): Float {
val duration = state.getEffectiveDuration()
return if (duration > 0f) {
(time / duration).coerceIn(0f, 1f)
} else 0f
}
}
data class CameraTransform(
val position: Vec3,
val focus: CameraFocus?,
val rotation: CameraRotation?
)
private sealed class ExecutionState {
object Stopped : ExecutionState()
data class Playing(
val currentState: State,
val stateTime: Float,
val totalTime: Float,
val lastTickNanos: Long,
val transitionState: TransitionState,
val progressMemory: Map<String, StateSnapshot>,
val executedEvents: Set<EventKey>,
val lastEvaluatedFocus: CameraFocus? = null
) : ExecutionState()
}
private sealed class TransitionState {
object None : TransitionState()
data class Blending(
val targetState: State,
val startTime: Float,
val duration: Float,
val startTransform: CameraTransform
) : TransitionState()
}
private sealed class TransitionCheckResult {
object NoTransition : TransitionCheckResult()
data class TransitionNow(
val targetStateId: String,
val type: TransitionType,
val blendDuration: Float
) : TransitionCheckResult()
}
private data class EventKey(
val stateId: String,
val eventId: String?,
val timeMillis: Int
)
private data class StateSnapshot(
val normalizedProgress: Float,
val lastFocus: CameraFocus?
)
@@ -1,129 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.camera.integration.server
import com.bedrockk.molang.runtime.MoLangRuntime
import com.bedrockk.molang.runtime.value.MoValue
import com.cobblemon.mod.common.Cobblemon
import com.cobblemon.mod.common.api.camera.model.CameraFocus
import com.cobblemon.mod.common.api.camera.track.FiredGuiAction
import com.cobblemon.mod.common.api.camera.track.GuiActionType
import net.minecraft.core.SectionPos
import net.minecraft.server.level.ServerLevel
import net.minecraft.util.Mth
import net.minecraft.world.level.ChunkPos
import net.minecraft.world.phys.Vec3
/**
* Executes camera timeline and manages focus resolution.
*
* Coordinates between CameraInstance, viewer/chunk managers, and network sync.
*/
class CameraExecutor(
private val instance: CameraInstance,
private val runtime: MoLangRuntime,
private val context: Map<String, MoValue>,
private val guiActionHandler: ((FiredGuiAction) -> Unit)? = null
) {
companion object {
private const val CHUNK_UPDATE_DISTANCE_SQ = (16 * 16).toDouble()
}
private var lastCenterChunkUpdate: Vec3? = null
fun tick(
level: ServerLevel,
networkSync: CameraNetworkSync,
onChunkUpdate: (ChunkPos) -> Unit
): Boolean {
if (!instance.isActive()) return false
val transform = instance.tick() ?: run {
if (!instance.isActive()) instance.stop()
return false
}
val shouldUpdateCenter = lastCenterChunkUpdate?.let { last ->
transform.position.distanceToSqr(last) > CHUNK_UPDATE_DISTANCE_SQ
} ?: true
if (shouldUpdateCenter) {
val chunkPos = chunkPosFrom(transform.position)
onChunkUpdate(chunkPos)
lastCenterChunkUpdate = transform.position
}
val instantTransition = instance.consumeInstantTransitionFlag()
networkSync.sendTransform(transform, shouldUpdateCenter)
when (val focus = transform.focus) {
null -> networkSync.sendFocusNone()
is CameraFocus.Bone -> networkSync.sendFocusBone(focus, context, runtime)
else -> {
val resolvedFocus = resolveFocusPosition(focus)
val finalFocusPos = instance.focusOverride ?: resolvedFocus
networkSync.sendFocusPoint(finalFocusPos)
}
}
networkSync.sendState(
instantTransition = instantTransition,
renderPlayerBody = instance.getCurrentRenderPlayerBody(),
hiddenHudElements = instance.getCurrentHiddenHudElements()
)
if (guiActionHandler != null) {
val guiActions = instance.consumeGuiActions()
for (action in guiActions) {
guiActionHandler.invoke(action)
}
}
return true
}
fun resolveFocusPosition(focus: CameraFocus): Vec3? {
return when (focus) {
is CameraFocus.Entity -> {
val entity = CameraFocus.resolveEntity(focus.selector, context, runtime)
if (entity != null) {
val position = entity.position()
instance.updateLastValidFocusPosition(position)
position
} else {
val cached = instance.lastValidFocusPosition
if (cached != null) {
Cobblemon.LOGGER.debug("[CameraExecutor] Entity focus invalid, using last valid position")
cached
} else {
Cobblemon.LOGGER.warn("[CameraExecutor] Entity focus invalid and no cached position, using origin")
instance.origin
}
}
}
is CameraFocus.Point -> {
val position = focus.position.toVec3(context, runtime, instance.origin, false)
instance.updateLastValidFocusPosition(position)
position
}
is CameraFocus.Bone -> {
// Bone focus is resolved client-side, so return entity position as fallback
CameraFocus.resolveEntity(focus.selector, context, runtime)?.position()
?: instance.lastValidFocusPosition
}
}
}
private fun chunkPosFrom(position: Vec3): ChunkPos {
val chunkX = SectionPos.blockToSectionCoord(Mth.floor(position.x))
val chunkZ = SectionPos.blockToSectionCoord(Mth.floor(position.z))
return ChunkPos(chunkX, chunkZ)
}
}
@@ -1,95 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.camera.integration.server
import com.bedrockk.molang.runtime.MoLangRuntime
import com.bedrockk.molang.runtime.MoParams
import com.bedrockk.molang.runtime.value.MoValue
import com.cobblemon.mod.common.api.camera.engine.TimelineEngine
import com.cobblemon.mod.common.api.camera.model.State
import com.cobblemon.mod.common.api.camera.model.Timeline
import com.cobblemon.mod.common.api.molang.MoLangFunctions.setup
import net.minecraft.world.phys.Vec3
import java.util.UUID
/**
* Server-side camera instance - pure state and identity.
*
* Represents a single camera with its configuration and execution engine.
* Does NOT handle networking, chunk loading, or viewer management.
*
* @param id Unique identifier for this camera instance
* @param origin The world position origin for relative coordinates
* @param initialContext Initial context values (parameter values) to inject into MoLang.
* These are validated against the timeline's declared parameters when starting.
* @param queryFunctions Custom MoLang query functions to register
*/
class CameraInstance(
val id: UUID = UUID.randomUUID(),
val origin: Vec3,
private val initialContext: Map<String, MoValue> = emptyMap(),
queryFunctions: Map<String, java.util.function.Function<MoParams, Any>> = emptyMap()
) {
private val runtime: MoLangRuntime = MoLangRuntime().setup().apply {
environment.query.functions.putAll(queryFunctions)
}
private var engine: TimelineEngine = TimelineEngine(id, createStubTimeline(), origin, runtime, initialContext)
@Volatile
var focusOverride: Vec3? = null
var lastValidFocusPosition: Vec3? = null
private set
fun startTimeline(timeline: Timeline): Boolean {
engine = TimelineEngine(id, timeline, origin, runtime, initialContext)
return engine.start()
}
fun tick() = engine.tick()
fun stop() = engine.stop()
fun isActive() = engine.isActive()
fun getCurrentRenderPlayerBody() = engine.getCurrentRenderPlayerBody()
fun getCurrentHiddenHudElements() = engine.getCurrentHiddenHudElements()
fun setVariable(name: String, value: Double) = engine.setVariable(name, value)
fun triggerInstantTransition() = engine.triggerInstantTransition()
fun addQueryFunctions(functions: Map<String, java.util.function.Function<MoParams, Any>>) {
runtime.environment.query.functions.putAll(functions)
}
fun consumeInstantTransitionFlag() = engine.consumeInstantTransitionFlag()
fun consumeGuiActions() = engine.consumeGuiActions()
fun updateLastValidFocusPosition(position: Vec3) {
lastValidFocusPosition = position
}
private fun createStubTimeline(): Timeline {
return Timeline(
id = "stub",
startStateId = "stub",
states = mapOf(
"stub" to State(
id = "stub",
tracks = emptyList()
)
),
transitions = emptyList()
)
}
}
@@ -1,184 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.camera.integration.server
import com.bedrockk.molang.runtime.MoLangRuntime
import com.bedrockk.molang.runtime.value.MoValue
import com.cobblemon.mod.common.Cobblemon
import com.cobblemon.mod.common.CobblemonNetwork.sendPacket
import com.cobblemon.mod.common.api.camera.engine.CameraTransform
import com.cobblemon.mod.common.api.camera.model.CameraFocus
import com.cobblemon.mod.common.api.camera.model.HudElement
import com.cobblemon.mod.common.net.messages.client.camera.CameraEndPacket
import com.cobblemon.mod.common.net.messages.client.camera.CameraFocusPacket
import com.cobblemon.mod.common.net.messages.client.camera.CameraStartPacket
import com.cobblemon.mod.common.net.messages.client.camera.CameraStatePacket
import com.cobblemon.mod.common.net.messages.client.camera.CameraTransformPacket
import net.minecraft.server.level.ServerPlayer
import net.minecraft.world.phys.Vec3
import java.util.UUID
/**
* Handles camera packet transmission to clients.
*
* Manages synchronization of camera state with connected viewers.
* Uses modular packets with change tracking to minimize network traffic.
*/
class CameraNetworkSync(
private val cameraId: UUID,
private val viewers: Set<UUID>
) {
private var lastFocusPosition: Vec3? = null
private var lastRenderPlayerBody: Boolean = true
private var lastHiddenHudElements: Set<HudElement> = emptySet()
private var lastInstantTransition: Boolean = false
fun sendStart(startPosition: Vec3) {
getPlayers().forEach { player ->
player.sendPacket(CameraStartPacket(cameraId, startPosition))
}
sendFocusNone(force = true)
sendState(
instantTransition = false,
renderPlayerBody = true,
hiddenHudElements = emptySet(),
force = true
)
}
fun sendTransform(
transform: CameraTransform,
updateCenterChunk: Boolean
) {
val packet = CameraTransformPacket(
cameraId = cameraId,
position = transform.position,
rotation = transform.rotation,
updateCenterChunk = updateCenterChunk
)
getPlayers().forEach { it.sendPacket(packet) }
}
fun sendFocusNone(force: Boolean = false) {
if (!force && lastFocusPosition == null) {
return
}
val packet = CameraFocusPacket(
cameraId = cameraId,
focus = CameraFocusPacket.FocusData.None
)
getPlayers().forEach { it.sendPacket(packet) }
lastFocusPosition = null
}
fun sendFocusPoint(focusPosition: Vec3?, force: Boolean = false) {
if (!force && focusPosition == lastFocusPosition) {
return
}
val focusData = when (focusPosition) {
null -> CameraFocusPacket.FocusData.None
else -> CameraFocusPacket.FocusData.Point(focusPosition)
}
val packet = CameraFocusPacket(
cameraId = cameraId,
focus = focusData
)
getPlayers().forEach { it.sendPacket(packet) }
lastFocusPosition = focusPosition
}
fun sendFocusBone(
boneFocus: CameraFocus.Bone,
context: Map<String, MoValue>,
runtime: MoLangRuntime,
force: Boolean = false
) {
val entity = CameraFocus.resolveEntity(boneFocus.selector, context, runtime)
if (entity == null) {
Cobblemon.LOGGER.debug("[CameraNetworkSync] Bone focus entity invalid")
sendFocusNone(force)
return
}
val offset = boneFocus.offset.toVec3(context, runtime)
Cobblemon.LOGGER.debug("[CameraNetworkSync] Sending bone focus: entityId=${entity.id}, bone=${boneFocus.boneName}, offset=$offset, smooth=${boneFocus.smooth}")
val focusData = CameraFocusPacket.FocusData.Bone(
entityId = entity.id,
boneName = boneFocus.boneName,
offset = offset,
smooth = boneFocus.smooth
)
val packet = CameraFocusPacket(
cameraId = cameraId,
focus = focusData
)
getPlayers().forEach { it.sendPacket(packet) }
// Invalidate lastFocusPosition when switching to bone focus.
// This ensures that when transitioning back to a point focus,
// the packet will always be sent (not incorrectly deduplicated).
lastFocusPosition = null
}
fun sendState(
instantTransition: Boolean,
renderPlayerBody: Boolean,
hiddenHudElements: Set<HudElement>,
force: Boolean = false
) {
if (!force &&
instantTransition == lastInstantTransition &&
renderPlayerBody == lastRenderPlayerBody &&
hiddenHudElements == lastHiddenHudElements) {
return
}
val packet = CameraStatePacket(
cameraId = cameraId,
instantTransition = instantTransition,
renderPlayerBody = renderPlayerBody,
hiddenHudElements = hiddenHudElements
)
getPlayers().forEach { it.sendPacket(packet) }
lastInstantTransition = instantTransition
lastRenderPlayerBody = renderPlayerBody
lastHiddenHudElements = hiddenHudElements
}
fun sendEnd() {
val packet = CameraEndPacket(cameraId)
getPlayers().forEach { it.sendPacket(packet) }
}
/**
* Send end packet to a specific player.
* Used when removing a single viewer without stopping the entire camera.
*/
fun sendEndToPlayer(player: ServerPlayer) {
player.sendPacket(CameraEndPacket(cameraId))
}
private fun getPlayers(): List<ServerPlayer> {
val server = Cobblemon.implementation.server() ?: return emptyList()
return viewers.mapNotNull { server.playerList.getPlayer(it) }
}
}
@@ -1,38 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.camera.integration.server
import com.cobblemon.mod.common.CobblemonNetwork.sendPacket
import com.cobblemon.mod.common.client.render.camera.compositor.CompositorLayout
import com.cobblemon.mod.common.net.messages.client.camera.CompositorPacket
import net.minecraft.server.level.ServerPlayer
import java.util.UUID
class CompositorSession(
val compositorId: UUID = UUID.randomUUID(),
private val viewers: () -> Collection<ServerPlayer>,
val fullscreen: Boolean = true,
val width: Int = 1920,
val height: Int = 1080
) {
fun sendCreate(layout: CompositorLayout) {
val packet = CompositorPacket.create(compositorId, layout, fullscreen, width, height)
viewers().forEach { it.sendPacket(packet) }
}
fun sendLayoutUpdate(layout: CompositorLayout) {
val packet = CompositorPacket.updateLayout(compositorId, layout)
viewers().forEach { it.sendPacket(packet) }
}
fun sendDestroy() {
val packet = CompositorPacket.destroy(compositorId)
viewers().forEach { it.sendPacket(packet) }
}
}
@@ -1,252 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.camera.model
import com.bedrockk.molang.runtime.MoLangRuntime
import com.bedrockk.molang.runtime.value.MoValue
import com.cobblemon.mod.common.Cobblemon
import com.cobblemon.mod.common.api.molang.ExpressionLike
import com.cobblemon.mod.common.api.molang.ObjectValue
import com.cobblemon.mod.common.util.asExpressionLike
import com.cobblemon.mod.common.util.resolve
import com.google.gson.JsonElement
import com.google.gson.JsonObject
import net.minecraft.world.entity.Entity
import net.minecraft.world.phys.Vec3
/**
* Represents where the camera should look.
*/
sealed class CameraFocus {
abstract fun resolve(
context: Map<String, MoValue>,
runtime: MoLangRuntime,
fallback: Vec3?
): Vec3?
data class Point(val position: PositionExpression) : CameraFocus() {
override fun resolve(
context: Map<String, MoValue>,
runtime: MoLangRuntime,
fallback: Vec3?
): Vec3 {
return position.toVec3(context, runtime)
}
}
data class Entity(val selector: ExpressionLike) : CameraFocus() {
override fun resolve(
context: Map<String, MoValue>,
runtime: MoLangRuntime,
fallback: Vec3?
): Vec3? {
return resolveEntity(selector, context, runtime)?.position() ?: fallback
}
}
data class Bone(
val selector: ExpressionLike,
val boneName: String,
val offset: PositionExpression = PositionExpression(
CoordinateValue.Static(0.0),
CoordinateValue.Static(0.0),
CoordinateValue.Static(0.0)
),
val smooth: Boolean = true
) : CameraFocus() {
override fun resolve(
context: Map<String, MoValue>,
runtime: MoLangRuntime,
fallback: Vec3?
): Vec3? {
// Server-side: just resolve the entity position as fallback
// Client-side bone resolution happens in BoneFocusResolver
return resolveEntity(selector, context, runtime)?.position() ?: fallback
}
}
companion object {
/**
* Resolves a MoLang entity selector to a live Entity, or null if the selector
* doesn't resolve, the entity is removed, or the entity is dead.
*/
fun resolveEntity(
selector: ExpressionLike,
context: Map<String, MoValue>,
runtime: MoLangRuntime
): net.minecraft.world.entity.Entity? {
return try {
val result = runtime.resolve(selector, context)
if (result is ObjectValue<*>) {
val entity = result.obj as? net.minecraft.world.entity.Entity
if (entity != null && !entity.isRemoved && entity.isAlive) entity else null
} else null
} catch (e: Exception) {
Cobblemon.LOGGER.error("[CameraFocus] Failed to resolve entity from selector", e)
null
}
}
fun fromJson(obj: JsonObject): CameraFocus {
val type = obj.get("type")?.asString
?: throw IllegalArgumentException("CameraFocus missing 'type' field")
return when (type) {
"entity" -> {
val selector = obj.get("selector")?.asString
?: throw IllegalArgumentException("Entity focus missing 'selector' field")
Entity(selector.asExpressionLike())
}
"position", "point" -> {
val posElement = obj.get("position")
?: obj // If no nested position, use the object itself
Point(PositionExpression.fromJson(posElement))
}
"bone" -> {
val selector = obj.get("selector")?.asString
?: throw IllegalArgumentException("Bone focus missing 'selector' field")
val boneName = obj.get("bone")?.asString
?: obj.get("boneName")?.asString
?: throw IllegalArgumentException("Bone focus missing 'bone' field")
val offset = if (obj.has("offset")) {
PositionExpression.fromJson(obj.get("offset"))
} else {
PositionExpression(
CoordinateValue.Static(0.0),
CoordinateValue.Static(0.0),
CoordinateValue.Static(0.0)
)
}
val smooth = obj.get("smooth")?.asBoolean ?: true
Bone(selector.asExpressionLike(), boneName, offset, smooth)
}
else -> {
throw IllegalArgumentException("Unknown CameraFocus type: $type")
}
}
}
}
}
/**
* Position defined by three coordinates (x, y, z), each either static or dynamic.
*/
data class PositionExpression(
val x: CoordinateValue,
val y: CoordinateValue,
val z: CoordinateValue
) {
fun toVec3(
context: Map<String, MoValue> = emptyMap(),
runtime: MoLangRuntime,
origin: Vec3 = Vec3.ZERO,
isRelative: Boolean = false
): Vec3 {
val base = Vec3(
x.evaluate(context, runtime),
y.evaluate(context, runtime),
z.evaluate(context, runtime)
)
return if (isRelative) base.add(origin) else base
}
fun isFinite(context: Map<String, MoValue>, runtime: MoLangRuntime): Boolean {
val vec = toVec3(context, runtime)
return vec.x.isFinite() && vec.y.isFinite() && vec.z.isFinite()
}
companion object {
fun fromJson(element: JsonElement): PositionExpression {
return when {
element.isJsonObject -> {
val obj = element.asJsonObject
PositionExpression(
x = deserializeCoordinate(obj.get("x")),
y = deserializeCoordinate(obj.get("y")),
z = deserializeCoordinate(obj.get("z"))
)
}
element.isJsonArray -> {
val arr = element.asJsonArray
if (arr.size() != 3) {
throw IllegalArgumentException("Position array must have exactly 3 elements [x, y, z], got ${arr.size()}")
}
PositionExpression(
x = deserializeCoordinate(arr[0]),
y = deserializeCoordinate(arr[1]),
z = deserializeCoordinate(arr[2])
)
}
else -> {
throw IllegalArgumentException("Position must be either an object {x, y, z} or array [x, y, z]")
}
}
}
private fun deserializeCoordinate(element: JsonElement?): CoordinateValue {
if (element == null) {
return CoordinateValue.Static(0.0)
}
return when {
element.isJsonPrimitive && element.asJsonPrimitive.isNumber -> {
CoordinateValue.Static(element.asDouble)
}
element.isJsonPrimitive && element.asJsonPrimitive.isString -> {
// String is treated as expression
CoordinateValue.Dynamic(element.asString.asExpressionLike())
}
element.isJsonObject -> {
val obj = element.asJsonObject
val type = obj.get("type")?.asString
val expression = obj.get("expression")?.asString
when (type) {
"expression" -> {
if (expression == null) {
throw IllegalArgumentException("Expression coordinate missing 'expression' field")
}
CoordinateValue.Dynamic(expression.asExpressionLike())
}
else -> {
throw IllegalArgumentException("Unknown coordinate type: $type")
}
}
}
else -> {
throw IllegalArgumentException("Invalid coordinate value: $element")
}
}
}
}
}
sealed class CoordinateValue {
data class Static(val value: Double) : CoordinateValue()
data class Dynamic(val expression: ExpressionLike) : CoordinateValue()
fun evaluate(
context: Map<String, MoValue>,
runtime: MoLangRuntime
): Double {
return when (this) {
is Static -> value
is Dynamic -> {
try {
runtime.resolve(expression, context).asDouble()
} catch (e: Exception) {
// Log error but don't crash - coordinate expressions shouldn't break cameras
0.0
}
}
}
}
}
@@ -1,34 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.camera.model
enum class HudElement(val id: String) {
CROSSHAIR("crosshair"),
HOTBAR("hotbar"),
EXPERIENCE_BAR("experience_bar"),
PLAYER_HEALTH("player_health"),
ARMOR("armor"),
FOOD("food"),
AIR("air"),
EFFECTS("effects"),
BOSS_BAR("boss_bar"),
SCOREBOARD("scoreboard"),
CHAT("chat"),
PLAYER_LIST("player_list"),
SELECTED_ITEM_NAME("selected_item_name"),
COBBLEMON_OVERLAY("cobblemon_overlay");
companion object {
val ALL: Set<HudElement> = entries.toSet()
private val BY_ID = entries.associateBy { it.id }
fun fromId(id: String): HudElement? = BY_ID[id]
}
}
@@ -1,79 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.camera.model
/**
* Defines a parameter that can be passed to a camera timeline.
*
* Parameters allow timelines to be reusable with different values.
* For example, an arena camera can accept `arena_center` as a Vec3 parameter
* to position the camera relative to any arena location.
*
* @property type The type of the parameter (NUMBER or VEC3)
* @property description Optional description for documentation
* @property default Optional default value. If null, the parameter is required.
*/
data class ParameterDefinition(
val type: ParameterType,
val description: String? = null,
val default: ParameterDefault? = null
) {
/**
* Whether this parameter must be provided when starting the timeline.
* Parameters with defaults are optional.
*/
val isRequired: Boolean get() = default == null
/**
* Gets the variable names this parameter will inject into the MoLang runtime.
* - NUMBER type: returns just the parameter name
* - VEC3 type: returns name_x, name_y, name_z
*/
fun getVariableNames(paramName: String): List<String> {
return when (type) {
ParameterType.NUMBER -> listOf(paramName)
ParameterType.VEC3 -> listOf("${paramName}_x", "${paramName}_y", "${paramName}_z")
}
}
}
/**
* Types of parameters supported by camera timelines.
*/
enum class ParameterType {
/**
* A single numeric value (Double).
* Accessible in MoLang as `variable.param_name`
*/
NUMBER,
/**
* A 3D vector value.
* Expands to three variables in MoLang:
* - `variable.param_name_x`
* - `variable.param_name_y`
* - `variable.param_name_z`
*/
VEC3
}
/**
* Default value for a parameter.
*/
sealed class ParameterDefault {
/**
* Default value for a NUMBER parameter.
*/
data class NumberDefault(val value: Double) : ParameterDefault()
/**
* Default value for a VEC3 parameter.
*/
data class Vec3Default(val x: Double, val y: Double, val z: Double) : ParameterDefault()
}
@@ -1,243 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.camera.model
import com.cobblemon.mod.common.api.camera.result.ValidationError
import com.cobblemon.mod.common.api.molang.ExpressionLike
/**
* Immutable timeline definition - a state machine of camera animations with transitions.
*
* Timelines can declare required and optional parameters that must be provided when
* starting the camera. Parameters are injected into the MoLang runtime as variables,
* allowing tracks to use dynamic values like `variable.arena_center_x`.
*
* @property id Unique identifier for this timeline
* @property startStateId The ID of the initial state when the timeline starts
* @property parameters Map of parameter names to their definitions. Parameters without
* defaults are required and must be provided when starting the camera.
* @property states Map of state IDs to state definitions
* @property transitions List of transitions between states
*/
data class Timeline(
val id: String,
val startStateId: String,
val parameters: Map<String, ParameterDefinition> = emptyMap(),
val states: Map<String, State>,
val transitions: List<Transition>
) {
fun getState(stateId: String): State? = states[stateId]
fun getTransitionsFrom(stateId: String): List<Transition> =
transitions.filter { it.sourceStateId == stateId }
/**
* Gets the names of all required parameters (those without defaults).
*/
fun getRequiredParameterNames(): Set<String> =
parameters.filter { it.value.isRequired }.keys
/**
* Gets all variable names that this timeline's parameters will inject.
* For NUMBER parameters, returns the parameter name.
* For VEC3 parameters, returns name_x, name_y, name_z.
*/
fun getAllParameterVariableNames(): Set<String> =
parameters.flatMap { (name, def) -> def.getVariableNames(name) }.toSet()
/**
* Validates that all required parameters are provided in the given context.
*
* @param providedVariables Set of variable names provided in the context
* @return List of missing parameter names, empty if all required params are present
*/
fun validateParameters(providedVariables: Set<String>): List<String> {
val missingParams = mutableListOf<String>()
for ((paramName, definition) in parameters) {
if (!definition.isRequired) continue
val requiredVars = definition.getVariableNames(paramName)
val allProvided = requiredVars.all { it in providedVariables }
if (!allProvided) {
missingParams.add(paramName)
}
}
return missingParams
}
fun validate(): List<ValidationError> {
val errors = mutableListOf<ValidationError>()
// Check start state exists
if (startStateId !in states) {
errors.add(ValidationError(
path = "startStateId",
message = "Start state '$startStateId' not found in states map"
))
}
// Check all transition states exist
transitions.forEachIndexed { index, transition ->
if (transition.sourceStateId !in states) {
errors.add(ValidationError(
path = "transitions[$index].sourceStateId",
message = "Source state '${transition.sourceStateId}' not found"
))
}
if (transition.targetStateId !in states) {
errors.add(ValidationError(
path = "transitions[$index].targetStateId",
message = "Target state '${transition.targetStateId}' not found"
))
}
}
states.forEach { (stateId, state) ->
if (state.tracks.isEmpty()) {
errors.add(ValidationError(
path = "states[$stateId].tracks",
message = "State has no tracks defined",
severity = ValidationError.Severity.WARNING
))
}
}
val reachableStates = findReachableStates()
states.keys.forEach { stateId ->
if (stateId !in reachableStates) {
errors.add(ValidationError(
path = "states[$stateId]",
message = "State is unreachable from start state '$startStateId'",
severity = ValidationError.Severity.WARNING
))
}
}
val cycles = detectCycles()
if (cycles.isNotEmpty()) {
errors.add(ValidationError(
path = "transitions",
message = "Detected transition cycles: ${cycles.joinToString(", ") { it.joinToString(" -> ") }}",
severity = ValidationError.Severity.WARNING
))
}
return errors
}
private fun findReachableStates(): Set<String> {
val reachable = mutableSetOf<String>()
val queue = ArrayDeque<String>()
if (startStateId in states) {
queue.add(startStateId)
reachable.add(startStateId)
}
while (queue.isNotEmpty()) {
val current = queue.removeFirst()
transitions
.filter { it.sourceStateId == current }
.forEach { transition ->
if (transition.targetStateId !in reachable && transition.targetStateId in states) {
reachable.add(transition.targetStateId)
queue.add(transition.targetStateId)
}
}
}
return reachable
}
private fun detectCycles(): List<List<String>> {
val cycles = mutableListOf<List<String>>()
val visited = mutableSetOf<String>()
val recStack = mutableSetOf<String>()
fun dfs(node: String, path: MutableList<String>): Boolean {
if (node !in states) return false
visited.add(node)
recStack.add(node)
path.add(node)
for (transition in getTransitionsFrom(node)) {
val target = transition.targetStateId
if (target !in visited) {
if (dfs(target, path)) return true
} else if (target in recStack) {
val cycleStart = path.indexOf(target)
if (cycleStart >= 0) {
cycles.add(path.subList(cycleStart, path.size) + target)
}
}
}
path.removeAt(path.size - 1)
recStack.remove(node)
return false
}
states.keys.forEach { stateId ->
if (stateId !in visited) {
dfs(stateId, mutableListOf())
}
}
return cycles
}
}
/**
* Immutable camera state definition - a collection of tracks that play together.
*/
data class State(
val id: String,
val tracks: List<CameraTrack>,
val duration: Float? = null,
val isLooping: Boolean = false,
val speed: Float = 1.0f,
val rememberProgress: Boolean = false,
val renderPlayerBody: Boolean = true,
val hiddenHudElements: Set<HudElement> = emptySet()
) {
init {
require(speed > 0f) { "State speed must be positive, got $speed" }
duration?.let { d ->
require(d >= 0f) { "State duration must be non-negative, got $d" }
}
}
fun getEffectiveDuration(): Float {
return duration ?: tracks.maxOfOrNull { it.duration } ?: 0f
}
}
/**
* Immutable transition definition - defines when and how to move from one state to another.
*/
data class Transition(
val sourceStateId: String,
val targetStateId: String,
val condition: ExpressionLike,
val type: TransitionType = TransitionType.BLEND,
val blendDuration: Float = 0.4f
) {
init {
require(blendDuration >= 0f) { "Blend duration must be non-negative, got $blendDuration" }
}
}
enum class TransitionType {
INSTANT,
BLEND
}
@@ -1,59 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.camera.model
import com.bedrockk.molang.runtime.MoLangRuntime
import com.bedrockk.molang.runtime.value.MoValue
import com.cobblemon.mod.common.api.camera.CameraRotation
import com.cobblemon.mod.common.api.molang.ExpressionLike
import net.minecraft.world.phys.Vec3
/**
* Type-safe track evaluation result.
*/
sealed class TrackOutput {
data class Position(val position: Vec3) : TrackOutput()
data class Focus(val target: CameraFocus) : TrackOutput()
data class Rotation(val rotation: CameraRotation) : TrackOutput()
data class Event(val expression: ExpressionLike, val eventId: String?) : TrackOutput()
}
/**
* Camera track interface - produces outputs over time.
*/
interface CameraTrack {
val trackType: String
val duration: Float
fun evaluate(
time: Float,
context: Map<String, MoValue>,
runtime: MoLangRuntime,
origin: Vec3
): List<TrackOutput>
}
enum class TrackCapability {
POSITION,
FOCUS,
ROTATION,
EVENTS
}
fun CameraTrack.capabilities(): Set<TrackCapability> {
val outputs = evaluate(0f, emptyMap(), MoLangRuntime(), Vec3.ZERO)
return outputs.mapTo(mutableSetOf()) { output ->
when (output) {
is TrackOutput.Position -> TrackCapability.POSITION
is TrackOutput.Focus -> TrackCapability.FOCUS
is TrackOutput.Rotation -> TrackCapability.ROTATION
is TrackOutput.Event -> TrackCapability.EVENTS
}
}
}
@@ -1,222 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.camera.registry
import com.cobblemon.mod.common.Cobblemon
import com.cobblemon.mod.common.api.camera.CameraTrackRegistry
import com.cobblemon.mod.common.api.camera.model.*
import com.cobblemon.mod.common.util.asExpressionLike
import com.google.gson.*
import java.lang.reflect.Type
/**
* JSON deserializer for Timeline (V2 format).
*
* Deserializes directly into the immutable Timeline model without legacy conversion.
*/
object TimelineDeserializer : JsonDeserializer<Timeline> {
override fun deserialize(json: JsonElement, typeOfT: Type, ctx: JsonDeserializationContext): Timeline {
val obj = json.asJsonObject
val id = obj.get("timelineId")?.asString
?: throw JsonParseException("Timeline missing 'timelineId' field")
val startStateId = obj.get("startStateId")?.asString
?: throw JsonParseException("Timeline '$id' missing 'startStateId' field")
val statesObj = obj.get("states")?.asJsonObject
?: throw JsonParseException("Timeline '$id' missing 'states' object")
val transitionsArray = obj.get("transitions")?.asJsonArray ?: JsonArray()
// Parse parameters (optional)
val parametersObj = obj.get("parameters")?.asJsonObject
val parameters = parametersObj?.entrySet()?.associate { (paramName, paramValue) ->
try {
paramName to deserializeParameter(paramValue.asJsonObject, paramName, id)
} catch (e: Exception) {
Cobblemon.LOGGER.error("[Timeline] Error parsing parameter '$paramName' in timeline '$id': ${e.message}")
throw JsonParseException("Invalid parameter '$paramName' in timeline '$id'", e)
}
} ?: emptyMap()
val states = statesObj.entrySet().associate { (key, value) ->
try {
key to deserializeState(value.asJsonObject, id)
} catch (e: Exception) {
Cobblemon.LOGGER.error("[Timeline] Error parsing state '$key' in timeline '$id': ${e.message}")
throw JsonParseException("Invalid state '$key' in timeline '$id'", e)
}
}
val transitions = transitionsArray.mapIndexed { index, element ->
try {
deserializeTransition(element.asJsonObject, id)
} catch (e: Exception) {
Cobblemon.LOGGER.error("[Timeline] Error parsing transition $index in timeline '$id': ${e.message}")
throw JsonParseException("Invalid transition $index in timeline '$id'", e)
}
}
return Timeline(
id = id,
startStateId = startStateId,
parameters = parameters,
states = states,
transitions = transitions
)
}
private fun deserializeParameter(obj: JsonObject, paramName: String, timelineId: String): ParameterDefinition {
val typeStr = obj.get("type")?.asString
?: throw JsonParseException("Parameter '$paramName' missing 'type' field")
val type = when (typeStr.lowercase()) {
"number" -> ParameterType.NUMBER
"vec3" -> ParameterType.VEC3
else -> throw JsonParseException("Parameter '$paramName' has unknown type '$typeStr'. Valid types: number, vec3")
}
val description = obj.get("description")?.asString
val default: ParameterDefault? = when {
!obj.has("default") -> null
type == ParameterType.NUMBER -> {
val defaultValue = obj.get("default")
if (defaultValue.isJsonPrimitive && defaultValue.asJsonPrimitive.isNumber) {
ParameterDefault.NumberDefault(defaultValue.asDouble)
} else {
throw JsonParseException("Parameter '$paramName' default must be a number")
}
}
type == ParameterType.VEC3 -> {
val defaultObj = obj.get("default")
if (defaultObj.isJsonObject) {
val vec = defaultObj.asJsonObject
val x = vec.get("x")?.asDouble
?: throw JsonParseException("Parameter '$paramName' vec3 default missing 'x' field")
val y = vec.get("y")?.asDouble
?: throw JsonParseException("Parameter '$paramName' vec3 default missing 'y' field")
val z = vec.get("z")?.asDouble
?: throw JsonParseException("Parameter '$paramName' vec3 default missing 'z' field")
ParameterDefault.Vec3Default(x, y, z)
} else {
throw JsonParseException("Parameter '$paramName' vec3 default must be an object with x, y, z fields")
}
}
else -> null
}
return ParameterDefinition(
type = type,
description = description,
default = default
)
}
private fun deserializeState(obj: JsonObject, timelineId: String): State {
val stateId = obj.get("stateId")?.asString
?: throw JsonParseException("State missing 'stateId' field")
val tracksArray = obj.get("tracks")?.asJsonArray
?: throw JsonParseException("State '$stateId' missing 'tracks' array")
val tracks = tracksArray.mapIndexedNotNull { index, element ->
try {
deserializeTrack(element.asJsonObject)
} catch (e: Exception) {
Cobblemon.LOGGER.error("[Timeline] Error parsing track $index in state '$stateId': ${e.message}", e)
null
}
}
val duration = obj.get("duration")?.asFloat
val isLooping = obj.get("isLooping")?.asBoolean ?: false
val speed = obj.get("speed")?.asFloat ?: 1.0f
val rememberProgress = obj.get("rememberProgress")?.asBoolean ?: false
val renderPlayerBody = obj.get("renderPlayerBody")?.asBoolean ?: true
val hiddenHudElements = when (val hideHudElement = obj.get("hideHud")) {
null -> emptySet()
is JsonPrimitive -> {
if (hideHudElement.isBoolean) {
if (hideHudElement.asBoolean) HudElement.ALL else emptySet()
} else {
Cobblemon.LOGGER.warn("[Timeline] Invalid hideHud value in state '$stateId', expected boolean or array")
emptySet()
}
}
is JsonArray -> {
hideHudElement.mapNotNull { element ->
val id = element.asString
HudElement.fromId(id) ?: run {
Cobblemon.LOGGER.warn("[Timeline] Unknown HUD element '$id' in state '$stateId'")
null
}
}.toSet()
}
else -> {
Cobblemon.LOGGER.warn("[Timeline] Invalid hideHud value in state '$stateId', expected boolean or array")
emptySet()
}
}
return State(
id = stateId,
tracks = tracks,
duration = duration,
isLooping = isLooping,
speed = speed,
rememberProgress = rememberProgress,
renderPlayerBody = renderPlayerBody,
hiddenHudElements = hiddenHudElements
)
}
private fun deserializeTrack(obj: JsonObject): CameraTrack {
val trackType = obj.get("trackType")?.asString
?: throw JsonParseException("Track missing 'trackType' field")
return CameraTrackRegistry.deserializeTrack(trackType, obj)
?: throw JsonParseException("Unknown track type: $trackType")
}
private fun deserializeTransition(obj: JsonObject, timelineId: String): Transition {
val sourceStateId = obj.get("sourceStateId")?.asString
?: throw JsonParseException("Transition missing 'sourceStateId' field")
val targetStateId = obj.get("targetStateId")?.asString
?: throw JsonParseException("Transition missing 'targetStateId' field")
val conditionStr = obj.get("condition")?.asString
?: throw JsonParseException("Transition from '$sourceStateId' to '$targetStateId' missing 'condition' field")
val blendDuration = obj.get("blendDuration")?.asFloat ?: 0.4f
val transitionType = obj.get("transitionType")?.asString?.let { typeStr ->
when (typeStr.lowercase()) {
"blend" -> TransitionType.BLEND
"instant" -> TransitionType.INSTANT
else -> {
Cobblemon.LOGGER.warn("[Timeline] Unknown transition type '$typeStr' in timeline '$timelineId', using BLEND")
TransitionType.BLEND
}
}
} ?: TransitionType.BLEND
return Transition(
sourceStateId = sourceStateId,
targetStateId = targetStateId,
condition = conditionStr.asExpressionLike(),
type = transitionType,
blendDuration = blendDuration
)
}
}
@@ -1,117 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.camera.registry
import com.cobblemon.mod.common.Cobblemon
import com.cobblemon.mod.common.api.camera.model.Timeline
import com.cobblemon.mod.common.api.camera.result.ValidationError
import com.cobblemon.mod.common.api.data.DataRegistry
import com.cobblemon.mod.common.api.reactive.SimpleObservable
import com.cobblemon.mod.common.util.cobblemonResource
import com.google.gson.GsonBuilder
import net.minecraft.server.level.ServerPlayer
import net.minecraft.server.packs.PackType
import net.minecraft.server.packs.resources.ResourceManager
import java.io.InputStreamReader
/**
* Registry for loading Timeline (V2 format) from JSON files.
*
* Loads timelines directly into the new immutable Timeline model
* without legacy conversion.
*/
object TimelineRegistry : DataRegistry {
override val id = cobblemonResource("camera_timelines")
override val type = PackType.SERVER_DATA
override val observable = SimpleObservable<TimelineRegistry>()
private val gson = GsonBuilder()
.registerTypeAdapter(Timeline::class.java, TimelineDeserializer)
.create()
private val timelines = mutableMapOf<String, Timeline>()
override fun reload(manager: ResourceManager) {
timelines.clear()
val resources = manager.listResources("camera_timelines") { path ->
path.path.endsWith(".json")
}
for ((identifier, resource) in resources) {
try {
resource.open().use { stream ->
val reader = InputStreamReader(stream)
val timeline = gson.fromJson(reader, Timeline::class.java)
val errors = timeline.validate()
val hasErrors = errors.any { it.severity == ValidationError.Severity.ERROR }
if (hasErrors) {
Cobblemon.LOGGER.error("[TimelineRegistry] Validation failed for '$identifier':")
errors.forEach { error ->
val level = if (error.severity == ValidationError.Severity.ERROR) "ERROR" else "WARN"
Cobblemon.LOGGER.error(" [$level] ${error.path}: ${error.message}")
}
continue
}
if (errors.isNotEmpty()) {
Cobblemon.LOGGER.warn("[TimelineRegistry] Warnings for timeline '${timeline.id}':")
errors.forEach { Cobblemon.LOGGER.warn(" ${it.path}: ${it.message}") }
}
if (timelines.containsKey(timeline.id)) {
Cobblemon.LOGGER.warn("[TimelineRegistry] Duplicate timeline ID '${timeline.id}' in $identifier, overwriting")
}
timelines[timeline.id] = timeline
Cobblemon.LOGGER.debug("[TimelineRegistry] Loaded timeline '${timeline.id}' from $identifier")
}
} catch (e: Exception) {
Cobblemon.LOGGER.error("[TimelineRegistry] Error loading timeline from $identifier", e)
}
}
Cobblemon.LOGGER.info("[TimelineRegistry] Loaded ${timelines.size} timelines")
observable.emit(this)
}
override fun sync(player: ServerPlayer) {
// Timelines are server-driven, no sync needed
}
fun getTimeline(id: String): Timeline? {
val timeline = timelines[id]
if (timeline == null) {
Cobblemon.LOGGER.error("[TimelineRegistry] Timeline '$id' not found")
}
return timeline
}
fun hasTimeline(id: String): Boolean = timelines.containsKey(id)
fun registerTimeline(timeline: Timeline) {
val errors = timeline.validate()
if (errors.any { it.severity == ValidationError.Severity.ERROR }) {
Cobblemon.LOGGER.error("[TimelineRegistry] Cannot register invalid timeline '${timeline.id}':")
errors.forEach { Cobblemon.LOGGER.error(" ${it.path}: ${it.message}") }
return
}
if (timelines.containsKey(timeline.id)) {
Cobblemon.LOGGER.warn("[TimelineRegistry] Timeline '${timeline.id}' already registered, overwriting")
}
timelines[timeline.id] = timeline
Cobblemon.LOGGER.debug("[TimelineRegistry] Registered timeline '${timeline.id}' programmatically")
}
fun getAllTimelines(): Collection<Timeline> = timelines.values
}
@@ -1,22 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.camera.result
/**
* Validation error with location context.
*/
data class ValidationError(
val path: String,
val message: String,
val severity: Severity = Severity.ERROR
) {
enum class Severity { WARNING, ERROR }
override fun toString(): String = "[$severity] $path: $message"
}
@@ -1,243 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.camera.track
import com.cobblemon.mod.common.Cobblemon
import com.cobblemon.mod.common.api.camera.CameraTrackRegistry
import com.cobblemon.mod.common.api.tween.InterpolationMethod
import com.cobblemon.mod.common.api.camera.model.CameraFocus
import com.cobblemon.mod.common.api.camera.model.PositionExpression
import com.cobblemon.mod.common.util.asExpressionLike
import com.google.gson.JsonObject
object CameraTrackDeserializers {
/** Should be called during mod initialization. */
fun registerBuiltinTracks() {
CameraTrackRegistry.registerTrackType("position", ::deserializePositionTrack)
CameraTrackRegistry.registerTrackType("focus", ::deserializeFocusTrack)
CameraTrackRegistry.registerTrackType("event", ::deserializeEventTrack)
CameraTrackRegistry.registerTrackType("reference", ::deserializeReferenceTrack)
CameraTrackRegistry.registerTrackType("gui", ::deserializeGuiTrack)
Cobblemon.LOGGER.debug("[CameraTrackDeserializers] Registered built-in track types: position, focus, event, reference, gui")
}
/**
* Deserializes a position track from JSON.
*
* Expected JSON format:
* ```json
* {
* "trackType": "position",
* "keyframes": [
* {
* "time": 0.0,
* "position": { "x": 10.0, "y": 64.0, "z": 10.0 },
* "easing": "ease_in_out_quad"
* }
* ],
* "interpolationType": "bezier",
* "easing": "linear",
* "isRelative": false
* }
* ```
*/
private fun deserializePositionTrack(json: JsonObject): PositionTrack {
val keyframesArray = json.getAsJsonArray("keyframes")
?: throw IllegalArgumentException("Position track missing 'keyframes' array")
val keyframes = keyframesArray.map { element ->
val kfObj = element.asJsonObject
val time = kfObj.get("time")?.asFloat
?: throw IllegalArgumentException("Position keyframe missing 'time' field")
val positionElement = kfObj.get("position")
?: throw IllegalArgumentException("Position keyframe missing 'position' field")
val position = PositionExpression.fromJson(positionElement)
val easing = kfObj.get("easing")?.asString
PositionKeyframe(time, position, easing)
}
val interpolationTypeStr = json.get("interpolationType")?.asString ?: "linear"
val interpolationType = when (interpolationTypeStr.lowercase()) {
"linear" -> InterpolationMethod.LINEAR
"bezier", "cubic_bezier" -> InterpolationMethod.BEZIER
"hermite", "catmull_rom" -> InterpolationMethod.BEZIER // Map legacy types to available ones
else -> {
Cobblemon.LOGGER.warn("[CameraTrackDeserializers] Unknown interpolation type '$interpolationTypeStr', using LINEAR")
InterpolationMethod.LINEAR
}
}
val defaultEasing = json.get("easing")?.asString ?: "linear"
val isRelative = json.get("isRelative")?.asBoolean ?: false
return PositionTrack(keyframes, interpolationType, defaultEasing, isRelative)
}
/**
* Deserializes a focus track from JSON.
*
* Expected JSON format:
* ```json
* {
* "trackType": "focus",
* "keyframes": [
* {
* "time": 0.0,
* "target": { "type": "position", "x": 20.0, "y": 60.0, "z": 20.0 },
* "easing": "linear"
* }
* ],
* "easing": "linear"
* }
* ```
*/
private fun deserializeFocusTrack(json: JsonObject): FocusTrack {
val keyframesArray = json.getAsJsonArray("keyframes")
?: throw IllegalArgumentException("Focus track missing 'keyframes' array")
val keyframes = keyframesArray.map { element ->
val kfObj = element.asJsonObject
val time = kfObj.get("time")?.asFloat
?: throw IllegalArgumentException("Focus keyframe missing 'time' field")
val targetObj = kfObj.getAsJsonObject("target")
?: throw IllegalArgumentException("Focus keyframe missing 'target' field")
val target = CameraFocus.fromJson(targetObj)
val easing = kfObj.get("easing")?.asString
FocusKeyframe(time, target, easing)
}
val defaultEasing = json.get("easing")?.asString ?: "linear"
return FocusTrack(keyframes, defaultEasing)
}
/**
* Deserializes an event track from JSON.
*
* Expected JSON format:
* ```json
* {
* "trackType": "event",
* "events": [
* {
* "time": 0.5,
* "expression": "q.play_sound('cobblemon:poke_ball.open')",
* "eventId": "ball_open"
* }
* ]
* }
* ```
*/
private fun deserializeEventTrack(json: JsonObject): EventTrack {
val eventsArray = json.getAsJsonArray("events")
?: throw IllegalArgumentException("Event track missing 'events' array")
val events = eventsArray.map { element ->
val eventObj = element.asJsonObject
val time = eventObj.get("time")?.asFloat
?: throw IllegalArgumentException("Event missing 'time' field")
val expressionStr = eventObj.get("expression")?.asString
?: throw IllegalArgumentException("Event missing 'expression' field")
val eventId = eventObj.get("eventId")?.asString
TimedEvent(time, expressionStr.asExpressionLike(), eventId)
}
return EventTrack(events)
}
/**
* Deserializes a reference track from JSON.
*
* Expected JSON format:
* ```json
* {
* "trackType": "reference",
* "trackId": "intro_camera_movement"
* }
* ```
*/
private fun deserializeReferenceTrack(json: JsonObject): ReferenceTrack {
val trackId = json.get("trackId")?.asString
?: throw IllegalArgumentException("Reference track missing 'trackId' field")
return ReferenceTrack(trackId)
}
/**
* Deserializes a GUI track from JSON.
*
* Expected JSON format:
* ```json
* {
* "trackType": "gui",
* "actions": [
* {
* "time": 0.0,
* "action": "OPEN",
* "guiId": "cobblemon:battle_intro",
* "args": { "title": "Stadium Battle" },
* "argsExpressions": {
* "player_party_count": "variable.player_party_count"
* }
* },
* {
* "time": 5.0,
* "action": "CLOSE",
* "guiId": "cobblemon:battle_intro"
* }
* ]
* }
* ```
*/
private fun deserializeGuiTrack(json: JsonObject): GuiTrack {
val actionsArray = json.getAsJsonArray("actions")
?: throw IllegalArgumentException("GUI track missing 'actions' array")
val actions = actionsArray.map { element ->
val actionObj = element.asJsonObject
val time = actionObj.get("time")?.asFloat
?: throw IllegalArgumentException("GUI action missing 'time' field")
val actionType = actionObj.get("action")?.asString
?: throw IllegalArgumentException("GUI action missing 'action' field")
val guiId = actionObj.get("guiId")?.asString
?: throw IllegalArgumentException("GUI action missing 'guiId' field")
val args = mutableMapOf<String, String>()
actionObj.getAsJsonObject("args")?.entrySet()?.forEach { (key, value) ->
args[key] = value.asString
}
val argsExpressions = mutableMapOf<String, String>()
actionObj.getAsJsonObject("argsExpressions")?.entrySet()?.forEach { (key, value) ->
argsExpressions[key] = value.asString
}
TimedGuiAction(
time = time,
action = GuiActionType.valueOf(actionType.uppercase()),
guiId = guiId,
args = args,
argsExpressions = argsExpressions
)
}
return GuiTrack(actions)
}
}
@@ -1,56 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.camera.track
import com.bedrockk.molang.runtime.MoLangRuntime
import com.bedrockk.molang.runtime.value.MoValue
import com.cobblemon.mod.common.api.camera.model.CameraTrack
import com.cobblemon.mod.common.api.camera.model.TrackOutput
import com.cobblemon.mod.common.api.molang.ExpressionLike
import net.minecraft.world.phys.Vec3
/**
* Track that executes MoLang expressions at specific times.
*/
data class EventTrack(
val events: List<TimedEvent>
) : CameraTrack {
override val trackType = "event"
override val duration: Float
get() = events.maxOfOrNull { it.time } ?: 0f
override fun evaluate(
time: Float,
context: Map<String, MoValue>,
runtime: MoLangRuntime,
origin: Vec3
): List<TrackOutput> {
return emptyList()
}
init {
require(events.zipWithNext().all { (a, b) -> a.time <= b.time }) {
"EventTrack events must be sorted by time"
}
}
}
/**
* Timed event - execute expression at specific time.
*/
data class TimedEvent(
val time: Float,
val expression: ExpressionLike,
val eventId: String? = null
) {
init {
require(time >= 0f) { "Event time must be non-negative, got $time" }
}
}
@@ -1,126 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.camera.track
import com.bedrockk.molang.runtime.MoLangRuntime
import com.bedrockk.molang.runtime.value.MoValue
import com.cobblemon.mod.common.api.tween.EasingRegistry
import com.cobblemon.mod.common.api.tween.Interpolator
import com.cobblemon.mod.common.api.tween.Keyframe
import com.cobblemon.mod.common.api.camera.model.*
import net.minecraft.util.Mth
import net.minecraft.world.phys.Vec3
/**
* Track that animates camera look-at target over time.
* Point targets interpolate smoothly; entity targets switch instantly.
*/
data class FocusTrack(
val keyframes: List<FocusKeyframe>,
val defaultEasing: String = "linear"
) : CameraTrack {
override val trackType = "focus"
override val duration: Float
get() = keyframes.maxOfOrNull { it.time } ?: 0f
override fun evaluate(
time: Float,
context: Map<String, MoValue>,
runtime: MoLangRuntime,
origin: Vec3
): List<TrackOutput> {
if (keyframes.isEmpty()) return emptyList()
val segment = findFocusSegment(time) ?: return emptyList()
val focus = when {
// Both are Point targets - interpolate
segment.start is CameraFocus.Point && segment.end is CameraFocus.Point -> {
val startPos = segment.start.position.toVec3(context, runtime)
val endPos = segment.end.position.toVec3(context, runtime)
// Interpolate positions
val easedProgress = EasingRegistry.getEasingFunction(segment.easing)(segment.progress)
val interpolatedPos = Vec3(
Mth.lerp(easedProgress.toDouble(), startPos.x, endPos.x),
Mth.lerp(easedProgress.toDouble(), startPos.y, endPos.y),
Mth.lerp(easedProgress.toDouble(), startPos.z, endPos.z)
)
CameraFocus.Point(
PositionExpression(
CoordinateValue.Static(interpolatedPos.x),
CoordinateValue.Static(interpolatedPos.y),
CoordinateValue.Static(interpolatedPos.z)
)
)
}
// Entity targets or mixed - use instant switching
else -> {
if (segment.progress < 0.5f) segment.start else segment.end
}
}
return listOf(TrackOutput.Focus(focus))
}
private fun findFocusSegment(time: Float): FocusSegment? {
if (keyframes.isEmpty()) return null
if (keyframes.size == 1) {
val kf = keyframes[0]
return FocusSegment(kf.target, kf.target, kf.time, kf.time, 1f, defaultEasing)
}
for (i in 0 until keyframes.size - 1) {
val start = keyframes[i]
val end = keyframes[i + 1]
if (time <= end.time) {
val duration = end.time - start.time
val progress = if (duration > 0f) {
((time - start.time) / duration).coerceIn(0f, 1f)
} else 1f
val easing = end.easing ?: defaultEasing
return FocusSegment(start.target, end.target, start.time, end.time, progress, easing)
}
}
val last = keyframes.last()
return FocusSegment(last.target, last.target, last.time, last.time, 1f, defaultEasing)
}
init {
require(keyframes.isNotEmpty()) { "FocusTrack must have at least one keyframe" }
require(keyframes.zipWithNext().all { (a, b) -> a.time <= b.time }) {
"FocusTrack keyframes must be sorted by time"
}
}
private data class FocusSegment(
val start: CameraFocus,
val end: CameraFocus,
val startTime: Float,
val endTime: Float,
val progress: Float,
val easing: String
)
}
data class FocusKeyframe(
val time: Float,
val target: CameraFocus,
val easing: String? = null
) {
init {
require(time >= 0f) { "Keyframe time must be non-negative, got $time" }
}
}
@@ -1,86 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.camera.track
import com.bedrockk.molang.runtime.MoLangRuntime
import com.bedrockk.molang.runtime.value.MoValue
import com.cobblemon.mod.common.api.camera.model.CameraTrack
import com.cobblemon.mod.common.api.camera.model.TrackOutput
import net.minecraft.world.phys.Vec3
/**
* Track that fires timed GUI actions (open, close, update) during camera timelines.
*
* This track produces no camera outputs itself (no position/focus/rotation).
* The actions are executed by the CameraExecutor when their time is crossed.
*/
data class GuiTrack(
val actions: List<TimedGuiAction>
) : CameraTrack {
override val trackType = "gui"
override val duration: Float
get() = actions.maxOfOrNull { it.time } ?: 0f
override fun evaluate(
time: Float,
context: Map<String, MoValue>,
runtime: MoLangRuntime,
origin: Vec3
): List<TrackOutput> {
// GUI actions are handled by the engine/executor, not via TrackOutput
return emptyList()
}
init {
require(actions.zipWithNext().all { (a, b) -> a.time <= b.time }) {
"GuiTrack actions must be sorted by time"
}
}
}
/**
* Determines the type of GUI action to fire.
*/
enum class GuiActionType {
OPEN,
CLOSE,
UPDATE_ARGS
}
/**
* A timed GUI action within a timeline.
*
* @param time The time in seconds when this action should fire
* @param action The type of action
* @param guiId The scripted GUI resource location (e.g., "cobblemon:battle_intro")
* @param args Static argument values
* @param argsExpressions MoLang expressions to evaluate at fire time, merged with static args
*/
data class TimedGuiAction(
val time: Float,
val action: GuiActionType,
val guiId: String,
val args: Map<String, String> = emptyMap(),
val argsExpressions: Map<String, String> = emptyMap()
) {
init {
require(time >= 0f) { "GUI action time must be non-negative, got $time" }
}
}
/**
* Represents a GUI action that has fired (time crossed).
*/
data class FiredGuiAction(
val action: GuiActionType,
val guiId: String,
val args: Map<String, String>,
val argsExpressions: Map<String, String>
)
@@ -1,79 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.camera.track
import com.bedrockk.molang.runtime.MoLangRuntime
import com.bedrockk.molang.runtime.value.MoValue
import com.cobblemon.mod.common.api.tween.*
import com.cobblemon.mod.common.api.camera.model.*
import net.minecraft.world.phys.Vec3
/**
* Track that animates camera position over time using keyframes.
*/
data class PositionTrack(
val keyframes: List<PositionKeyframe>,
val interpolation: InterpolationMethod = InterpolationMethod.LINEAR,
val defaultEasing: String = "linear",
val isRelative: Boolean = false
) : CameraTrack {
override val trackType = "position"
override val duration: Float
get() = keyframes.maxOfOrNull { it.time } ?: 0f
override fun evaluate(
time: Float,
context: Map<String, MoValue>,
runtime: MoLangRuntime,
origin: Vec3
): List<TrackOutput> {
if (keyframes.isEmpty()) return emptyList()
val interpolatableKeyframes = keyframes.map { kf ->
val vec = kf.position.toVec3(context, runtime, origin, isRelative)
Keyframe(kf.time, vec.asInterpolatable())
}
val interpolated = Interpolator.interpolate(
keyframes = interpolatableKeyframes,
time = time,
method = interpolation,
defaultEasing = defaultEasing,
getEasing = { value ->
// Find original keyframe to get easing
val index = interpolatableKeyframes.indexOfFirst { it.value == value }
keyframes.getOrNull(index)?.easing
}
)
return if (interpolated != null) {
listOf(TrackOutput.Position(interpolated.vec))
} else {
emptyList()
}
}
init {
require(keyframes.isNotEmpty()) { "PositionTrack must have at least one keyframe" }
require(keyframes.zipWithNext().all { (a, b) -> a.time <= b.time }) {
"PositionTrack keyframes must be sorted by time"
}
}
}
data class PositionKeyframe(
val time: Float,
val position: PositionExpression,
val easing: String? = null
) {
init {
require(time >= 0f) { "Keyframe time must be non-negative, got $time" }
}
}
@@ -1,50 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.camera.track
import com.bedrockk.molang.runtime.MoLangRuntime
import com.bedrockk.molang.runtime.value.MoValue
import com.cobblemon.mod.common.Cobblemon
import com.cobblemon.mod.common.api.camera.model.CameraTrack
import com.cobblemon.mod.common.api.camera.model.TrackOutput
import com.cobblemon.mod.common.client.camera.tracks.CameraTrackDefinitionRegistry
import net.minecraft.world.phys.Vec3
/**
* Track that references another track definition by ID.
*/
data class ReferenceTrack(
val trackId: String
) : CameraTrack {
override val trackType = "reference"
override val duration: Float
get() {
val referencedTrack = CameraTrackDefinitionRegistry.getTrack(trackId)
return referencedTrack?.duration ?: 0f
}
override fun evaluate(
time: Float,
context: Map<String, MoValue>,
runtime: MoLangRuntime,
origin: Vec3
): List<TrackOutput> {
val referencedTrack = CameraTrackDefinitionRegistry.getTrack(trackId)
if (referencedTrack == null) {
// Log warning but don't crash
Cobblemon.LOGGER.warn("[ReferenceTrack] Track '$trackId' not found in registry")
return emptyList()
}
// Delegate to referenced track
return referencedTrack.evaluate(time, context, runtime, origin)
}
}
@@ -8,6 +8,7 @@
package com.cobblemon.mod.common.api.cooking.effects
import net.minecraft.server.level.ServerPlayer
import net.minecraft.world.effect.MobEffect
import net.minecraft.world.effect.MobEffectCategory
import net.minecraft.world.entity.Entity
@@ -18,5 +19,13 @@ class CleanseAllEffect : MobEffect(MobEffectCategory.BENEFICIAL, 0xFFFFFF) {
override fun applyInstantenousEffect(source: Entity?, indirect: Entity?, target: LivingEntity, amplifier: Int, proximity: Double) {
target.removeAllEffects()
}
override fun shouldApplyEffectTickThisTick(duration: Int, amplifier: Int) = false
override fun applyEffectTick(livingEntity: LivingEntity, amplifier: Int): Boolean {
if (livingEntity is ServerPlayer){
livingEntity.removeAllEffects()
}
return true
}
override fun shouldApplyEffectTickThisTick(duration: Int, amplifier: Int) = true
}
@@ -8,6 +8,7 @@
package com.cobblemon.mod.common.api.cooking.effects
import net.minecraft.server.level.ServerPlayer
import net.minecraft.world.effect.MobEffect
import net.minecraft.world.effect.MobEffectCategory
import net.minecraft.world.entity.Entity
@@ -23,5 +24,18 @@ class CleanseNegativeEffect : MobEffect(MobEffectCategory.BENEFICIAL, 0xFFFFFF)
}
}
}
override fun shouldApplyEffectTickThisTick(duration: Int, amplifier: Int) = false
override fun applyEffectTick(livingEntity: LivingEntity, amplifier: Int): Boolean {
if (livingEntity is ServerPlayer){
val snapshot = livingEntity.activeEffects.toList()
for (ei in snapshot) {
if (ei.effect.value().category == MobEffectCategory.HARMFUL) {
livingEntity.removeEffect(ei.effect)
}
}
}
return true
}
override fun shouldApplyEffectTickThisTick(duration: Int, amplifier: Int) = true
}
@@ -1,33 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.data
import com.cobblemon.mod.common.api.net.Decodable
import com.cobblemon.mod.common.api.net.Encodable
// TODO this is implemented in multiple places but unused. Can we scratch this?
/**
* Represents an object that will possibly be synchronized to the client during datapack synchronization.
*
* @param T The type of the object being synchronized.
*
* @author Licious
* @since October 14th, 2022
*/
interface ClientDataSynchronizer<T> : Decodable, Encodable {
/**
* Compares an object of type [T] with this instance to see if synchronization is necessary.
*
* @param other The other instance of type [T].
* @return If synchronization is necessary.
*/
fun shouldSynchronize(other: T): Boolean
}
@@ -14,9 +14,11 @@ import com.cobblemon.mod.common.api.text.green
import com.cobblemon.mod.common.api.text.red
import com.cobblemon.mod.common.util.lang
import com.cobblemon.mod.common.util.toBlockPos
import net.minecraft.core.component.DataComponentMap
import com.google.gson.JsonElement
import com.mojang.serialization.JsonOps
import net.minecraft.core.component.DataComponentPatch
import net.minecraft.core.registries.Registries
import net.minecraft.resources.RegistryOps
import net.minecraft.network.RegistryFriendlyByteBuf
import net.minecraft.resources.ResourceLocation
import net.minecraft.server.level.ServerLevel
@@ -40,7 +42,7 @@ open class ItemDropEntry : DropEntry {
override var maxSelectableTimes = 1
open val dropMethod: ItemDropMethod? = null
open var item = ResourceLocation.parse("minecraft:fish")
open val components: DataComponentMap? = null
open val components: JsonElement? = null
override fun drop(entity: LivingEntity?, world: ServerLevel, pos: Vec3, player: ServerPlayer?) {
val item = world.registryAccess().registryOrThrow(Registries.ITEM).get(item) ?: return LOGGER.error("Unable to load drop item: $item")
@@ -53,11 +55,15 @@ open class ItemDropEntry : DropEntry {
it
}
}
val builder = DataComponentPatch.builder()
components?.forEach {
builder.set(it)
if (components != null) {
val registryOps = RegistryOps.create(JsonOps.INSTANCE, world.registryAccess())
val decodeResult = DataComponentPatch.CODEC.parse(registryOps, components)
decodeResult.ifSuccess { patch ->
stack.applyComponentsAndValidate(patch)
}.ifError { error ->
LOGGER.error("Unable to parse components for drop item $item: ${error.message()}")
}
}
stack.applyComponentsAndValidate(builder.build())
if (dropMethod == ItemDropMethod.ON_PLAYER && player != null) {
world.addFreshEntity(ItemEntity(player.level(), player.x, player.y, player.z, stack))
@@ -22,11 +22,22 @@ import com.cobblemon.mod.common.api.events.berry.BerryMutationOfferEvent
import com.cobblemon.mod.common.api.events.berry.BerryMutationResultEvent
import com.cobblemon.mod.common.api.events.berry.BerryYieldCalculationEvent
import com.cobblemon.mod.common.api.events.cooking.PokeSnackSpawnPokemonEvent
import com.cobblemon.mod.common.api.events.camera.*
import com.cobblemon.mod.common.api.events.drops.LootDroppedEvent
import com.cobblemon.mod.common.api.events.entity.*
import com.cobblemon.mod.common.api.events.entity.PokemonEntityLoadEvent
import com.cobblemon.mod.common.api.events.entity.PokemonEntitySaveEvent
import com.cobblemon.mod.common.api.events.entity.PokemonEntitySaveToWorldEvent
import com.cobblemon.mod.common.api.events.entity.SpawnBucketChosenEvent
import com.cobblemon.mod.common.api.events.entity.SpawnEvent
import com.cobblemon.mod.common.api.events.farming.ApricornHarvestEvent
import com.cobblemon.mod.common.api.events.fishing.*
import com.cobblemon.mod.common.api.events.fishing.BaitConsumedEvent
import com.cobblemon.mod.common.api.events.fishing.BaitEffectFunctionRegistryEvent
import com.cobblemon.mod.common.api.events.fishing.BaitSetEvent
import com.cobblemon.mod.common.api.events.fishing.BaitSpawnPokemonEvent
import com.cobblemon.mod.common.api.events.fishing.BobberSpawnPokemonEvent
import com.cobblemon.mod.common.api.events.fishing.PokerodCastEvent
import com.cobblemon.mod.common.api.events.fishing.PokerodReelEvent
import com.cobblemon.mod.common.api.events.habitats.HabitatSpawnActivatedEvent
import com.cobblemon.mod.common.api.events.habitats.SaveHabitatBlockSettingsEvent
import com.cobblemon.mod.common.api.events.item.LeftoversCreatedEvent
import com.cobblemon.mod.common.api.events.pokeball.PokeBallCaptureCalculatedEvent
import com.cobblemon.mod.common.api.events.pokeball.PokemonCatchRateEvent
@@ -41,7 +52,11 @@ import com.cobblemon.mod.common.api.events.pokemon.healing.PokemonHealedEvent
import com.cobblemon.mod.common.api.events.pokemon.interaction.ExperienceCandyUseEvent
import com.cobblemon.mod.common.api.events.pokemon.interaction.PokemonInteractionGUICreationEvent
import com.cobblemon.mod.common.api.events.starter.StarterChosenEvent
import com.cobblemon.mod.common.api.events.storage.*
import com.cobblemon.mod.common.api.events.storage.ChangePCBoxWallpaperEvent
import com.cobblemon.mod.common.api.events.storage.ReleasePokemonEvent
import com.cobblemon.mod.common.api.events.storage.RenamePCBoxEvent
import com.cobblemon.mod.common.api.events.storage.WallpaperCollectionEvent
import com.cobblemon.mod.common.api.events.storage.WallpaperUnlockedEvent
import com.cobblemon.mod.common.api.events.world.BigRootPropagatedEvent
import com.cobblemon.mod.common.api.reactive.CancelableObservable
import com.cobblemon.mod.common.api.reactive.EventObservable
@@ -367,32 +382,11 @@ object CobblemonEvents {
@JvmField
val SELECT_DRIVER = EventObservable<SelectDriverEvent>()
// -------------------------------------------------------------------------------------
//
// Camera System
//
// -------------------------------------------------------------------------------------
// Habitats
@JvmField
val CAMERA_STARTED_PRE = CancelableObservable<CameraStartedEvent.Pre>()
val HABITAT_SPAWN_ACTIVATED = CancelableObservable<HabitatSpawnActivatedEvent>()
@JvmField
val CAMERA_STARTED_POST = EventObservable<CameraStartedEvent.Post>()
val HABITAT_SETTINGS_SAVED_PRE = CancelableObservable<SaveHabitatBlockSettingsEvent.Pre>()
@JvmField
val CAMERA_STOPPED_PRE = EventObservable<CameraStoppedEvent.Pre>()
@JvmField
val CAMERA_STOPPED_POST = EventObservable<CameraStoppedEvent.Post>()
@JvmField
val CAMERA_STATE_TRANSITION = EventObservable<CameraStateTransitionEvent>()
@JvmField
val CAMERA_VIEWER_ADDED = EventObservable<CameraViewerAddedEvent>()
@JvmField
val CAMERA_VIEWER_REMOVED = EventObservable<CameraViewerRemovedEvent>()
@JvmField
val CAMERA_TICK = EventObservable<CameraTickEvent>()
val HABITAT_SETTINGS_SAVED_POST = EventObservable<SaveHabitatBlockSettingsEvent.Post>()
}
@@ -1,100 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.events.camera
import com.cobblemon.mod.common.api.camera.ICameraController
import com.cobblemon.mod.common.api.events.Cancelable
import net.minecraft.server.level.ServerPlayer
import net.minecraft.world.phys.Vec3
import java.util.UUID
/** Base interface for all camera events. */
interface CameraEvent {
val cameraId: UUID
val controller: ICameraController
}
/** Events fired when a camera starts. Pre is cancelable. */
interface CameraStartedEvent : CameraEvent {
val timelineId: String
val viewers: List<ServerPlayer>
/** Pre event - fired before camera starts. */
data class Pre(
override val cameraId: UUID,
override val controller: ICameraController,
override val timelineId: String,
override val viewers: List<ServerPlayer>
) : CameraStartedEvent, Cancelable()
/** Post event - fired after camera starts. */
data class Post(
override val cameraId: UUID,
override val controller: ICameraController,
override val timelineId: String,
override val viewers: List<ServerPlayer>
) : CameraStartedEvent
}
/** Events fired when a camera stops. */
interface CameraStoppedEvent : CameraEvent {
val reason: StopReason
enum class StopReason {
MANUAL,
COMPLETED,
VIEWER_LEFT,
ERROR
}
/** Pre event - fired before camera stops. */
data class Pre(
override val cameraId: UUID,
override val controller: ICameraController,
override val reason: StopReason
) : CameraStoppedEvent
/** Post event - fired after camera stops. */
data class Post(
override val cameraId: UUID,
override val controller: ICameraController,
override val reason: StopReason
) : CameraStoppedEvent
}
/** Fired when a camera transitions between states. */
data class CameraStateTransitionEvent(
override val cameraId: UUID,
override val controller: ICameraController,
val fromStateId: String,
val toStateId: String,
val transitionType: String
) : CameraEvent
/** Fired when a viewer is added to a camera. */
data class CameraViewerAddedEvent(
override val cameraId: UUID,
override val controller: ICameraController,
val viewer: ServerPlayer
) : CameraEvent
/** Fired when a viewer is removed from a camera. */
data class CameraViewerRemovedEvent(
override val cameraId: UUID,
override val controller: ICameraController,
val viewer: ServerPlayer
) : CameraEvent
/** Fired every tick while a camera is active. Fires 20 times per second. */
data class CameraTickEvent(
override val cameraId: UUID,
override val controller: ICameraController,
val currentPosition: Vec3,
val currentFocus: Vec3?
) : CameraEvent
@@ -8,7 +8,6 @@
package com.cobblemon.mod.common.api.events.entity
import com.cobblemon.mod.common.api.spawning.SpawnBucket
import com.cobblemon.mod.common.api.spawning.SpawnCause
import com.cobblemon.mod.common.api.spawning.spawner.Spawner
@@ -21,7 +20,7 @@ class SpawnBucketChosenEvent(
/** The cause of the spawn. */
val spawnCause: SpawnCause,
/** The bucket that was chosen. You can alter this. */
var bucket: SpawnBucket,
var bucket: String,
/** The final weights that were used to make the choice. */
val bucketWeights: Map<SpawnBucket, Float>
val bucketWeights: Map<String, Float>
)
@@ -10,7 +10,9 @@ package com.cobblemon.mod.common.api.events.entity
import com.cobblemon.mod.common.api.events.Cancelable
import com.cobblemon.mod.common.api.spawning.BestSpawner
import com.cobblemon.mod.common.api.spawning.SpawnCause
import com.cobblemon.mod.common.api.spawning.position.SpawnablePosition
import com.cobblemon.mod.common.api.spawning.spawner.Spawner
import net.minecraft.world.entity.Entity
/**
@@ -21,4 +23,9 @@ import net.minecraft.world.entity.Entity
* @author Hiroku
* @since April 22nd, 2023
*/
class SpawnEvent<T : Entity>(val entity: T, val spawnablePosition: SpawnablePosition) : Cancelable()
class SpawnEvent<T : Entity>(val entity: T, val spawnablePosition: SpawnablePosition) : Cancelable() {
val cause: SpawnCause
get() = spawnablePosition.cause
val spawner: Spawner
get() = spawnablePosition.spawner
}
@@ -9,7 +9,6 @@
package com.cobblemon.mod.common.api.events.fishing
import com.cobblemon.mod.common.api.events.Cancelable
import com.cobblemon.mod.common.api.spawning.SpawnBucket
import com.cobblemon.mod.common.entity.fishing.PokeRodFishingBobberEntity
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import net.minecraft.world.item.ItemStack
@@ -27,7 +26,7 @@ interface BaitSpawnPokemonEvent {
*/
data class Pre(
val bobber: PokeRodFishingBobberEntity, // todo replace this with the bait entity
val chosenBucket: SpawnBucket,
val chosenBucket: String,
val rod: ItemStack
) : Cancelable(), BobberSpawnPokemonEvent
@@ -38,7 +37,7 @@ interface BaitSpawnPokemonEvent {
* @param pokemon The Pokemon that is modified.
*/
data class Modify(
val chosenBucket: SpawnBucket,
val chosenBucket: String,
val rod: ItemStack,
val pokemon: PokemonEntity
) : BobberSpawnPokemonEvent
@@ -52,7 +51,7 @@ interface BaitSpawnPokemonEvent {
*/
data class Post(
val bobber: PokeRodFishingBobberEntity,
val chosenBucket: SpawnBucket,
val chosenBucket: String,
val bait: ItemStack,
val pokemon: PokemonEntity
) : BobberSpawnPokemonEvent
@@ -8,12 +8,10 @@
package com.cobblemon.mod.common.api.events.fishing
import com.cobblemon.mod.common.api.spawning.SpawnBucket
/**
* Event that is fired when a bucket is chosen by the bobber.
* @param chosenBucket The bucket that is chosen.
* @param buckets The list of buckets that the bobber can choose from.
* @param luckOfTheSeaLevel The level of the Luck of the Sea enchantment on the rod.
*/
class BobberBucketChosenEvent(var chosenBucket: SpawnBucket, val buckets: MutableList<SpawnBucket>, val luckOfTheSeaLevel: Int)
class BobberBucketChosenEvent(var chosenBucket: String, val buckets: MutableList<String>, val luckOfTheSeaLevel: Int)
@@ -12,10 +12,7 @@ import com.bedrockk.molang.runtime.value.MoValue
import com.bedrockk.molang.runtime.value.StringValue
import com.cobblemon.mod.common.api.events.Cancelable
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMoLangValue
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMostSpecificMoLangValue
import com.cobblemon.mod.common.api.molang.MoLangFunctions.moLangFunctionMap
import com.cobblemon.mod.common.api.molang.ObjectValue
import com.cobblemon.mod.common.api.spawning.SpawnBucket
import com.cobblemon.mod.common.api.spawning.detail.SpawnAction
import com.cobblemon.mod.common.entity.fishing.PokeRodFishingBobberEntity
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
@@ -73,8 +70,8 @@ interface BobberSpawnPokemonEvent {
val bait: ItemStack,
val pokemon: PokemonEntity
) : BobberSpawnPokemonEvent {
val context = mutableMapOf<String, MoValue>(
"chosen_bucket" to ObjectValue(spawnAction.bucket, { it.name }),
val context = mutableMapOf(
"chosen_bucket" to StringValue(spawnAction.bucket),
"bait" to pokemon.level().itemRegistry.wrapAsHolder(bait.item).asMoLangValue(Registries.ITEM),
"pokemon_entity" to pokemon.asMoLangValue()
)
@@ -0,0 +1,37 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.events.habitats
import com.cobblemon.mod.common.api.events.Cancelable
import com.cobblemon.mod.common.api.habitats.spawningstyle.ActivatedHabitatSpawning
import com.cobblemon.mod.common.api.spawning.SpawnCause
import com.cobblemon.mod.common.api.spawning.spawner.FixedAreaSpawner
import com.cobblemon.mod.common.block.habitat.HabitatBlockEntity
/**
* Event that fires when a habitat is about to attempt to spawn Pokémon. Cancelling this event will prevent
* the habitat block from attempting to spawn anything for this activation.
*
* @author Hiroku
* @since February 15th,2026
*/
class HabitatSpawnActivatedEvent(
/** The habitat block entity that is responsible for the spawn. */
val habitatBlockEntity: HabitatBlockEntity,
/** The activation settings. You could have got it from the block entity but this is easier. */
val activatedHabitatSpawning: ActivatedHabitatSpawning,
/** The [SpawnCause] that will be used in the spawn action. This may contain a player that is nearest to the block. */
var cause: SpawnCause,
/** The maximum number of Pokémon the block will consider spawning (provided there is space). */
var maxSpawns: Int
) : Cancelable() {
/** The spawner representing the habitat. */
val spawner: FixedAreaSpawner
get() = activatedHabitatSpawning.spawner
}
@@ -0,0 +1,40 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.events.habitats
import com.cobblemon.mod.common.api.events.Cancelable
import com.cobblemon.mod.common.api.habitats.dto.HabitatSettingsDTO
import com.cobblemon.mod.common.block.habitat.HabitatBlockEntity
import net.minecraft.core.BlockPos
import net.minecraft.server.level.ServerLevel
import net.minecraft.server.level.ServerPlayer
interface SaveHabitatBlockSettingsEvent {
val player: ServerPlayer
val world: ServerLevel
val blockPos: BlockPos
val habitatBlockEntity: HabitatBlockEntity
val settings: HabitatSettingsDTO
class Pre(
override val player: ServerPlayer,
override val world: ServerLevel,
override val blockPos: BlockPos,
override val habitatBlockEntity: HabitatBlockEntity,
override val settings: HabitatSettingsDTO
) : SaveHabitatBlockSettingsEvent, Cancelable()
class Post(
override val player: ServerPlayer,
override val world: ServerLevel,
override val blockPos: BlockPos,
override val habitatBlockEntity: HabitatBlockEntity,
override val settings: HabitatSettingsDTO
) : SaveHabitatBlockSettingsEvent
}
@@ -68,11 +68,14 @@ class SpawnBait(
val TYPING = cobblemonResource("typing")
val EGG_GROUP = cobblemonResource("egg_group")
val SHINY_REROLL = cobblemonResource("shiny_reroll")
val MARK_CHANCE = cobblemonResource("mark_chance")
val DROPS_REROLL = cobblemonResource("drops_reroll")
val HIDDEN_ABILITY_CHANCE = cobblemonResource("ha_chance")
val ALPHA_CHANCE = cobblemonResource("alpha_chance")
val POKEMON_CHANCE = cobblemonResource("pokemon_chance")
val FRIENDSHIP = cobblemonResource("friendship")
val RARITY_BUCKET = cobblemonResource("rarity_bucket")
val SIZE = cobblemonResource("size")
fun registerEffect(type: ResourceLocation, effect: (PokemonEntity, Effect) -> Unit) {
EFFECT_FUNCTIONS[type] = effect
@@ -86,11 +89,14 @@ class SpawnBait(
registerEffect(NATURE) { entity, effect -> FishingSpawnCause.alterNatureAttempt(entity, effect) }
registerEffect(IV) { entity, effect -> FishingSpawnCause.alterIVAttempt(entity, effect) }
registerEffect(SHINY_REROLL) { entity, effect -> FishingSpawnCause.shinyReroll(entity, effect) }
registerEffect(MARK_CHANCE) { entity, effect -> FishingSpawnCause.alterMarksAttempt(entity, effect) }
registerEffect(DROPS_REROLL) { entity, effect -> FishingSpawnCause.saveDropsReroll(entity, effect) }
registerEffect(GENDER_CHANCE) { entity, effect -> FishingSpawnCause.alterGenderAttempt(entity, effect) }
registerEffect(LEVEL_RAISE) { entity, effect -> FishingSpawnCause.alterLevelAttempt(entity, effect) }
registerEffect(HIDDEN_ABILITY_CHANCE) { entity, _ -> FishingSpawnCause.alterHAAttempt(entity) }
registerEffect(ALPHA_CHANCE) { entity, effect -> FishingSpawnCause.alterAlphaAttempt(entity) }
registerEffect(FRIENDSHIP) { entity, effect -> FishingSpawnCause.alterFriendshipAttempt(entity, effect) }
registerEffect(SIZE) { entity, effect -> FishingSpawnCause.alterSize(entity, effect) }
CobblemonEvents.BAIT_EFFECT_REGISTRATION.post(BaitEffectFunctionRegistryEvent()) { event ->
event.functions.forEach { (type, function) -> registerEffect(type, function) }
}
@@ -0,0 +1,30 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.habitats
import com.cobblemon.mod.common.api.habitats.spawningstyle.ActivatedHabitatSpawning
import com.cobblemon.mod.common.api.spawning.detail.SpawnAction
import com.cobblemon.mod.common.api.spawning.influence.SpawningInfluence
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import net.minecraft.world.entity.Entity
/**
* Influence added to the activated habitat spawner blocks so that they can track the entity and apply block modifiers.
*
* @author Hiroku
* @since February 15th, 2026
*/
class ActivatedHabitatSpawningInfluence(val activatedHabitatSpawning: ActivatedHabitatSpawning) : SpawningInfluence {
override fun affectSpawn(action: SpawnAction<*>, entity: Entity) {
if (entity is PokemonEntity) {
activatedHabitatSpawning.habitatBlockEntity.modifiers.apply(entity)
activatedHabitatSpawning.habitatBlockEntity.spawnedEntityIDs.add(entity.id)
}
}
}

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