Compare commits

...
499 Commits
Author SHA1 Message Date
Islana 17ca9a31f1 Fix for forewarn not displaying moves with spaces in them. 2023-08-19 03:55:54 -04:00
Islana c851f57e36 Fix for forewarn not displaying moves with spaces in them. 2023-08-19 03:53:31 -04:00
Islana 2b3497e63d Fix for forewarn not displaying moves with spaces in them. 2023-08-19 03:47:11 -04:00
Islana c014efa9a6 Merge remote-tracking branch 'origin/main' 2023-08-18 23:48:01 -04:00
Hiroku 6dc4b6af24 Merge branch 'Zackghast7-main-patch-07680' into 'main'
Updated evYield for overqwil.json

See merge request cable-mc/cobblemon!586
2023-08-14 05:12:06 +00:00
Zack 071278caa2 Updated evYield for overqwil.json 2023-08-12 16:37:57 +00:00
Hiroku 12a29d1289 Merge branch 'Zackghast7-main-patch-64696' into 'main'
Update wyrdeer.json with the correct evs

See merge request cable-mc/cobblemon!585
2023-08-11 22:05:15 +00:00
Zack bc85fdb778 Update wyrdeer.json with the correct evs 2023-08-11 22:00:37 +00:00
Hiroku 0d0d659ce5 Merge branch 'added-sounds' into 'main'
New Healing Machine sound, shortened Healing Machine's heal time, updated PC and UI sounds

See merge request cable-mc/cobblemon!584
2023-08-11 21:42:15 +00:00
SterrezoandHiroku 535e0b6f87 New Healing Machine sound, shortened Healing Machine's heal time, updated PC and UI sounds 2023-08-11 21:42:15 +00:00
Licious dd8cb49295 Merge branch 'spawning-improvements' into 'main'
Fixed Pokémon spawning in walls, improve canSeeSky spawn condition, use new...

See merge request cable-mc/cobblemon!583
2023-08-11 19:24:56 +00:00
Paul 2c5968986d Fixed Pokémon spawning in walls, improve canSeeSky spawn condition, use new FlatSelector selection algorithm, remove terrible width spawn condition 2023-08-11 21:12:27 +10:00
Licious 7b29d31009 Merge branch 'pokemon_loot_gamerule' into 'main'
Add doPokemonLoot gamerule

See merge request cable-mc/cobblemon!576
2023-08-09 07:53:17 +00:00
MiaandLicious 8820a546db Add doPokemonLoot gamerule 2023-08-09 07:53:17 +00:00
Nick c4eb422722 Merge branch 'new-held-items' into 'main'
Added in five more held items

See merge request cable-mc/cobblemon!581
2023-08-08 22:48:19 +00:00
DeltricandNick d8f4638806 Added in five more held items 2023-08-08 22:48:19 +00:00
Hiroku f92aa1777c Merge branch 'fix/pokemon-property-extractor' into 'main'
add createPokemonProperties(List)

See merge request cable-mc/cobblemon!578
2023-08-07 03:35:13 +00:00
FawksXandHiroku 8d864a3ff8 add createPokemonProperties(List) 2023-08-07 03:35:13 +00:00
Paul 17a1409619 Fixed stat hex colour bleeding into text 2023-08-06 16:18:56 +10:00
Paul 51f92e1635 Further improvements to stat hex 2023-08-06 16:14:51 +10:00
Hiroku 9c3f8c9e8f Merge branch 'main' into 'main'
Fixes issue #394. Also fixes an (unlisted?) issue where special ivs/evs are not allocatable via pokegive

Closes #394

See merge request cable-mc/cobblemon!574
2023-08-06 00:44:12 +00:00
ApionandHiroku 923f40ab68 Fixes issue #394. Also fixes an (unlisted?) issue where special ivs/evs are not allocatable via pokegive 2023-08-06 00:44:12 +00:00
Paul cd7c3a0319 Merge remote-tracking branch 'origin/main' 2023-08-06 10:17:02 +10:00
Paul 8311dd8785 Fixed chance of sheared Pokémon dropping no wool 2023-08-06 09:37:53 +10:00
Hiroku f489cd096f Merge branch 'solve_playerdata_cache' into 'main'
Solve playerdata cache

See merge request cable-mc/cobblemon!575
2023-08-05 21:46:43 +00:00
Pedro SouzaandHiroku 0a4dc34895 Solve playerdata cache 2023-08-05 21:46:42 +00:00
Paul b1bc867ef8 Merge remote-tracking branch 'origin/main' 2023-08-05 17:17:29 +10:00
Paul 3f6af25afa Added dire hit and guard spec to creative menu 2023-08-05 17:17:17 +10:00
Hiroku 9946c39de0 Merge branch 'sound_updates' into 'main'
Sound updates

See merge request cable-mc/cobblemon!573
2023-08-04 21:48:21 +00:00
LilyandHiroku 037ba953b7 Sound updates 2023-08-04 21:48:21 +00:00
Hiroku 5b7b9342e5 Merge branch 'plant-issues' into 'main'
Various new crop fixes

Closes #396 and #347

See merge request cable-mc/cobblemon!569
2023-08-04 06:35:03 +00:00
LiciousandHiroku c52b99270b Various new crop fixes 2023-08-04 06:35:03 +00:00
Licious 2e67e804a7 Merge branch 'healing-items' into 'main'
Added healing items / bag items

See merge request cable-mc/cobblemon!333
2023-07-31 12:01:18 +00:00
LandonandLicious de58d11f9e Added healing items / bag items 2023-07-31 12:01:17 +00:00
Paul ede62cc049 Fixed some Pokémon having eyelids blending into their eyes in GUIs (gross) 2023-07-25 21:01:05 +10:00
Hiroku ee92206b43 Merge branch '323-broken-spawn-file-spawns-random-species' into 'main'
Fixed name typos in the spawn_pool_world files result in any pokemon spawning

Closes #323

See merge request cable-mc/cobblemon!570
2023-07-25 09:29:33 +00:00
selfdotandHiroku e47dbd7b71 Fixed name typos in the spawn_pool_world files result in any pokemon spawning 2023-07-25 09:29:33 +00:00
Hiroku 3548ee1172 Merge branch '355-switch-menu-retains-species-name' into 'main'
Changed battle switch menu to show pokemon display name

Closes #355

See merge request cable-mc/cobblemon!571
2023-07-24 21:45:06 +00:00
David Sadler e20eb6963f Changed battle switch menu to show pokemon display name 2023-07-24 19:37:58 +01:00
Licious 0d8589daad Merge branch 'ai-improvements' into 'main'
Various AI pathing improvements

See merge request cable-mc/cobblemon!568
2023-07-24 10:55:57 +00:00
HirokuandLicious 69fd7f5b99 Various AI pathing improvements 2023-07-24 10:55:57 +00:00
Hiroku 52a6a51d5e Merge branch 'main' into 'main'
Add player data store factory

See merge request cable-mc/cobblemon!565
2023-07-23 21:37:48 +00:00
Pedro SouzaandHiroku 7583e865ee Add player data store factory 2023-07-23 21:37:47 +00:00
Hiroku 651ed9cbcf Merge branch 'missing_messages' into 'main'
Missing messages

See merge request cable-mc/cobblemon!566
2023-07-23 21:33:26 +00:00
LilyandHiroku d45a654433 Missing messages 2023-07-23 21:33:26 +00:00
Hiroku a69042d892 Merge branch 'ghost-bug-item-dupe-fix' into 'main'
Ghost bug item dupe fix

See merge request cable-mc/cobblemon!567
2023-07-21 23:28:01 +00:00
MoeBoy76andHiroku 9007a75d69 Ghost bug item dupe fix 2023-07-21 23:28:01 +00:00
Hiroku bbf9836212 Merge branch 'pc-upgrade-moar-ram' into 'main'
PC Recipe Update

See merge request cable-mc/cobblemon!559
2023-07-20 21:54:43 +00:00
dhi_holoandHiroku 0b08044298 PC Recipe Update 2023-07-20 21:54:42 +00:00
Hiroku e53aa10f79 Merge branch 'added-sounds' into 'main'
Renamed cries for the new system, added cries for Gen 9 starters and evos, made all ambients blank

See merge request cable-mc/cobblemon!564
2023-07-20 21:54:33 +00:00
SterrezoandHiroku 1393904bc0 Renamed cries for the new system, added cries for Gen 9 starters and evos, made all ambients blank 2023-07-20 21:54:33 +00:00
Paul 90d51385b3 Nicknaming fixes 2023-07-18 19:09:31 +10:00
Hiroku 960454794d Merge branch 'cry-more' into 'main'
Implemented improved Pokémon cry system for battles and sendout, migrated Treecko and Pidgeot to it

See merge request cable-mc/cobblemon!563
2023-07-18 07:29:11 +00:00
Hiroku 0648185b38 Implemented improved Pokémon cry system for battles and sendout, migrated Treecko and Pidgeot to it 2023-07-18 07:29:11 +00:00
Licious efb202070c Merge branch 'main-patch-ce51' into 'main'
add mulch to creative inventory

See merge request cable-mc/cobblemon!560
2023-07-16 18:09:08 +00:00
Lily 23fdda700c add mulch to creative inventory 2023-07-16 16:40:31 +00:00
Licious 67251d3724 Merge branch 'shedninja-ball-fix' into 'main'
make Shedninja be in the actualy Pokeball consumed when evolving from Nincada

See merge request cable-mc/cobblemon!558
2023-07-14 22:07:23 +00:00
MoeBoy76 9fba594ca5 make Shedninja be in the actualy Pokeball consumed when evolving from Nincada 2023-07-15 07:50:21 +10:00
Licious 967e714c37 Uncomment code used for debug. 2023-07-14 10:10:22 +01:00
Nick 8fac0e0697 Merge branch 'healing-machine-fixes' into 'main'
Healing machine rendering fixes

See merge request cable-mc/cobblemon!555
2023-07-13 21:42:42 +00:00
LiciousandNick cdde54c483 Healing machine rendering fixes 2023-07-13 21:42:42 +00:00
Nick 59ea3bb3f4 Merge branch 'party-swap-click-sound' into 'main'
Add missing sound to the party swap icon.

Closes #350

See merge request cable-mc/cobblemon!554
2023-07-13 21:39:34 +00:00
Licious cc4456e1e3 Add missing sound to the party swap icon. 2023-07-13 16:17:56 +01:00
Hiroku 36331c733b Merge branch 'pasture-connect-to-fence' into 'main'
Pasture block fence connection support

See merge request cable-mc/cobblemon!551
2023-07-12 11:44:10 +00:00
LiciousandHiroku be25dc8999 Pasture block fence connection support 2023-07-12 11:44:10 +00:00
Hiroku 1770b44547 Merge branch 'stat-submenu-click-sounds' into 'main'
Stat submenu click sounds

Closes #342

See merge request cable-mc/cobblemon!552
2023-07-12 09:01:33 +00:00
LiciousandHiroku e058a4ac86 Stat submenu click sounds 2023-07-12 09:01:33 +00:00
Hiroku 09f4d17e15 Merge branch 'who-let-dhi-cook' into 'main'
Vivichoke, Roasted Leek, Pasture Particle, and Saturation

See merge request cable-mc/cobblemon!550
2023-07-12 07:49:43 +00:00
dhi_holoandHiroku 5d57465a5f Vivichoke, Roasted Leek, Pasture Particle, and Saturation 2023-07-12 07:49:43 +00:00
Nick e1e0635d5d Merge branch 'pasture-safe-block-detection-improvement' into 'main'
Improve pasture spawn conditions

Closes #327

See merge request cable-mc/cobblemon!549
2023-07-11 22:31:12 +00:00
LiciousandNick 2652cfa6fa Improve pasture spawn conditions 2023-07-11 22:31:12 +00:00
Hiroku a33978d5a5 Merge branch 'apricorn-seed-rename' into 'main'
Rename Apricorn seeds to sprouts

Closes #324

See merge request cable-mc/cobblemon!548
2023-07-11 21:29:32 +00:00
LiciousandHiroku 78ff7628a6 Rename Apricorn seeds to sprouts 2023-07-11 21:29:32 +00:00
Hiroku bfa685a434 Merge branch 'pasture-item-drop' into 'main'
Fixes the pasture block not dropping itself on break and having no dedicate...

Closes #339

See merge request cable-mc/cobblemon!547
2023-07-11 20:53:53 +00:00
LiciousandHiroku c9aad028ac Fixes the pasture block not dropping itself on break and having no dedicate... 2023-07-11 20:53:53 +00:00
Nick 551b2f9ea6 Merge branch 'no-more-ghost-cries' into 'main'
Prevent Pokémon cries from playing while a Pokémon is inside a Pokéball being captured.

See merge request cable-mc/cobblemon!546
2023-07-11 18:21:24 +00:00
Licious 3bc44b3ba3 Prevent Pokémon cries from playing while a Pokémon is inside a Pokéball being captured. 2023-07-11 18:47:50 +01:00
Nick ea89e64e73 Merge branch 'remove-clones-after-battle' into 'main'
Fix battle clones persisting in the world

Closes #328

See merge request cable-mc/cobblemon!545
2023-07-10 17:17:25 +00:00
LiciousandNick dd788d9851 Fix battle clones persisting in the world 2023-07-10 17:17:25 +00:00
Nick 7894e1895b Merge branch 'battle-stat-awards-fix' into 'main'
Fix EV calculation

Closes #231

See merge request cable-mc/cobblemon!544
2023-07-10 17:05:23 +00:00
Licious 70ee9617ed Fix another crash due to usage of param before init 2023-07-10 12:52:07 +01:00
Licious 848cdcfc66 Fix crash due to usage of param before init 2023-07-10 12:27:54 +01:00
Hiroku dd4c289755 Merge branch '247-master-1-19-3-shoulder-pokemon-issues' into 'main'
Shoulder fixes & changes.

See merge request cable-mc/cobblemon!538
2023-07-10 10:52:49 +00:00
LiciousandHiroku 57cb10d5ce Shoulder fixes & changes. 2023-07-10 10:52:49 +00:00
Licious 9282f94a85 Fix EV calculation 2023-07-10 11:31:49 +01:00
Hiroku 8c7eddccbe Merge branch 'loadFromJSON/NBT-companions' into 'main'
add companion object methods for these for better syntax

See merge request cable-mc/cobblemon!542
2023-07-10 02:56:17 +00:00
Oliver Whitehead 06be0cc40b add companion object methods for these for better syntax 2023-07-10 03:21:50 +01:00
Hiroku 67fe5d0822 Merge branch 'fix-pipeline' into 'main'
fix pipeline

See merge request cable-mc/cobblemon!541
2023-07-10 02:16:45 +00:00
Oliver Whitehead eba4162db4 fix pipeline 2023-07-10 03:14:26 +01:00
Hiroku 5dcbb271a5 Merge branch 'render-refactor' into 'main'
Render refactor

See merge request cable-mc/cobblemon!537
2023-07-09 23:48:57 +00:00
Hiroku e7a5c23204 Render refactor 2023-07-09 23:48:56 +00:00
Hiroku e9d4827a9b Merge branch 'pasture-not-graveyard' into 'main'
Fix being able to place fainted Pokémon in the pasture.

Closes #334

See merge request cable-mc/cobblemon!540
2023-07-09 22:37:18 +00:00
LiciousandHiroku 02898701b9 Fix being able to place fainted Pokémon in the pasture. 2023-07-09 22:37:17 +00:00
Hiroku 0b8488ab0f Merge branch 'terralith-tag-fixes' into 'main'
Update Terralith biome tags

Closes #331

See merge request cable-mc/cobblemon!539
2023-07-09 21:35:50 +00:00
LiciousandHiroku bd3968c7c5 Update Terralith biome tags 2023-07-09 21:35:49 +00:00
Hiroku a5cb807bfa Merge branch '1.20.x' into 'main'
1.20.1

See merge request cable-mc/cobblemon!535
2023-07-08 23:10:22 +00:00
LiciousandHiroku afafe35d16 1.20.1 2023-07-08 23:10:22 +00:00
Hiroku 99c94a1765 Merge branch 'p4-leaves' into 'main'
New colour

See merge request cable-mc/cobblemon!536
2023-07-08 23:04:03 +00:00
dhi_holoandHiroku f12fd1bb93 New colour 2023-07-08 23:04:02 +00:00
Hiroku 621280df50 Merge branch 'added-sounds' into 'main'
New UI sounds, new evolution sounds, cries for Caterpie, Weedle and Pidgey lines

See merge request cable-mc/cobblemon!534
2023-07-08 12:48:20 +00:00
SterrezoandHiroku 68d13abb1d New UI sounds, new evolution sounds, cries for Caterpie, Weedle and Pidgey lines 2023-07-08 12:48:20 +00:00
Paul 897bf4e132 Import fix 2023-07-08 11:01:54 +10:00
Paul 5944313fe8 Merge remote-tracking branch 'origin/main'
# Conflicts:
#	common/src/main/kotlin/com/cobblemon/mod/common/CobblemonBlocks.kt
2023-07-08 11:00:42 +10:00
Hiroku aa078c1269 Merge branch 'ys/fix-waterloggable-pasture' into 'main'
Make pasture block implement waterloggable (dk how I missed this)

See merge request cable-mc/cobblemon!533
2023-07-07 23:03:09 +00:00
YaseenandHiroku 5ce0c2a749 Make pasture block implement waterloggable (dk how I missed this) 2023-07-07 23:03:09 +00:00
Nick 1665032341 Merge branch 'added-sounds' into 'main'
New Pokeball sounds, tweaks to volumes in code

See merge request cable-mc/cobblemon!531
2023-07-07 15:45:25 +00:00
SterrezoandNick 6739b2d1ac New Pokeball sounds, tweaks to volumes in code 2023-07-07 15:45:25 +00:00
Hiroku 0bb782f314 Merge branch 'Vivichoke' into 'main'
Added Vivichokes

See merge request cable-mc/cobblemon!527
2023-07-07 00:43:42 +00:00
Hiroku 452ff46815 Added Vivichokes 2023-07-07 00:43:42 +00:00
Paul ee9fafe4fb Merge remote-tracking branch 'origin/main'
# Conflicts:
#	common/src/main/kotlin/com/cobblemon/mod/common/CobblemonBlocks.kt
2023-07-07 09:31:03 +10:00
Hiroku 65a193bb84 Merge branch 'ai-fix' into 'main'
Ai fix

See merge request cable-mc/cobblemon!526
2023-07-06 23:09:20 +00:00
LilyandHiroku 0a922a91b0 Ai fix 2023-07-06 23:09:19 +00:00
Paul 98810914fa Merge remote-tracking branch 'origin/main' into tethers 2023-07-07 09:01:55 +10:00
Paul 75062f5c16 Removed debug stuff 2023-07-07 08:57:02 +10:00
Paul adaf17ee4f Merge remote-tracking branch 'origin/main' 2023-07-06 21:26:12 +10:00
Hiroku 307196e201 Merge branch 'aspects-are-triggering' into 'main'
Aspects are (not) triggering

See merge request cable-mc/cobblemon!499
2023-07-06 11:15:55 +00:00
MoeBoy76andHiroku 4e225afc6e Aspects are (not) triggering 2023-07-06 11:15:55 +00:00
Hiroku 9ccff2e547 Merge branch 'added-sounds' into 'main'
Added cries for Gen 1-4 and 8 starters and evolutions

See merge request cable-mc/cobblemon!525
2023-07-05 10:41:21 +00:00
SterrezoandHiroku 673baa178f Added cries for Gen 1-4 and 8 starters and evolutions 2023-07-05 10:41:21 +00:00
Paul 59242d3020 Little cleanup with mints 2023-07-05 20:15:10 +10:00
Hiroku 53156bcfdb Merge branch 'ys/waterlog-fix' into 'main'
make default state of pc water logged false

See merge request cable-mc/cobblemon!524
2023-07-03 21:16:17 +00:00
YaseenandHiroku 7fae9ac61f make default state of pc water logged false 2023-07-03 21:16:17 +00:00
Paul e9924a8920 Fixed R key glitchiness 2023-07-03 13:26:43 +10:00
Paul d2590b05c5 Remove PC -> pasture icon hover if there's no room to add more pokemon 2023-07-03 11:50:35 +10:00
Hiroku 8557096359 Merge branch 'implement_pokemon' into 'main'
Implemented and Updated MANY models.

See merge request cable-mc/cobblemon!522
2023-07-02 23:52:40 +00:00
TyzillionandHiroku 66592af8ef Implemented and Updated MANY models. 2023-07-02 23:52:40 +00:00
Paul 8c5fe15835 Fixed diameter vs radius issue in anticluster pasture code 2023-07-02 19:51:17 +10:00
Paul 30dbaa0585 Changelog for pastures [skip-ci] 2023-07-02 19:03:31 +10:00
Paul 480a3894f8 Added pasture block to blocks creative tab 2023-07-02 19:02:15 +10:00
Paul d3ffbd654b Merge remote-tracking branch 'origin/main' into tethers
# Conflicts:
#	common/src/main/kotlin/com/cobblemon/mod/common/CobblemonItems.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/CobblemonNetwork.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/client/CobblemonClient.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/client/render/VaryingRenderableResolver.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/command/TestCommand.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/config/CobblemonConfig.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/pokemon/Pokemon.kt
2023-07-02 18:56:34 +10:00
Paul 43fcdf3f1b Finalized pasture block pass 1 2023-07-02 18:53:14 +10:00
Village 75f36825af 🌱 2023-07-01 14:21:06 -04:00
Hiroku 182f5ce1f9 Merge branch 'pokeball-despawn' into 'main'
poke-balls now despawn after 30 seconds to prevent potential lag machines

See merge request cable-mc/cobblemon!521
2023-07-01 02:00:38 +00:00
LilyandHiroku a05bc8887e poke-balls now despawn after 30 seconds to prevent potential lag machines 2023-07-01 02:00:36 +00:00
Veraxiel 76640c40ae Fixed 0601_klinklang.json 2023-06-29 21:50:55 +00:00
Hiroku 3404065bf0 Merge branch 'background-fixup' into 'main'
it works!!

See merge request cable-mc/cobblemon!519
2023-06-28 10:16:44 +00:00
dhi_holoandHiroku ba6eec0fad it works!! 2023-06-28 10:16:44 +00:00
Hiroku ff81bee266 Merge branch '314-shedinjarecoverissue' into 'main'
Resolve "Shedinja cannot recover naturally."

Closes #314

See merge request cable-mc/cobblemon!520
2023-06-28 10:16:21 +00:00
IslanaandHiroku 6926ae1be1 Resolve "Shedinja cannot recover naturally." 2023-06-28 10:16:21 +00:00
Hiroku 5ce290e792 Merge branch 'animation-refreactor' into 'main'
Animation refractor

See merge request cable-mc/cobblemon!480
2023-06-28 09:54:17 +00:00
WaterpickerandHiroku 5a7391ff69 Animation refractor 2023-06-28 09:54:17 +00:00
Islana f63970163a Merge remote-tracking branch 'origin/main' 2023-06-28 00:08:07 -04:00
Islana b34adc6b57 Shedinja revive Fix 2023-06-28 00:07:13 -04:00
Hiroku 0cd33621b2 Merge branch 'forge-maven-deployment-fix' into 'main'
Fixes forge maven deployments being hit with a missing access widener error

See merge request cable-mc/cobblemon!518
2023-06-27 08:28:10 +00:00
Nick 765421fc5f Fixes forge maven deployments being hit with a missing access widener error 2023-06-26 23:03:49 -07:00
Hiroku 4b6cef26bd Merge branch 'ys/pokeedit-command-2.0' into 'main'
Add support for editing IVs and EVs in pokeedit

Closes #306

See merge request cable-mc/cobblemon!501
2023-06-25 22:59:51 +00:00
YaseenandHiroku ccbae294f4 Add support for editing IVs and EVs in pokeedit 2023-06-25 22:59:51 +00:00
Hiroku 82f1ce8931 Merge branch 'creative-categories' into 'main'
Creative categories

See merge request cable-mc/cobblemon!514
2023-06-25 21:49:10 +00:00
LilyandHiroku 474491ebff Creative categories 2023-06-25 21:49:10 +00:00
Hiroku 60b36a03d4 Merge branch 'text_changes_and_fixes' into 'main'
small text changes:

See merge request cable-mc/cobblemon!515
2023-06-25 21:47:44 +00:00
LilyandHiroku 25bb99b68d small text changes: 2023-06-25 21:47:44 +00:00
Hiroku c644f610da Merge branch 'main-patch-15d5' into 'main'
changed healing machine messages to action bar

See merge request cable-mc/cobblemon!512
2023-06-25 03:36:35 +00:00
Hiroku 88c38f59b0 Merge branch 'mimikyu-shoulder' into 'main'
mimikyu shoulder mount!!!

See merge request cable-mc/cobblemon!513
2023-06-25 03:36:12 +00:00
LilyandHiroku 36f9062f45 mimikyu shoulder mount!!! 2023-06-25 03:36:11 +00:00
Lily 26a49c8327 changed healing machine messages to action bar 2023-06-25 01:19:16 +00:00
Hiroku d8b66e01df Merge branch 'battle-crash-logs' into 'main'
Handle battle crashes and log them

See merge request cable-mc/cobblemon!509
2023-06-25 00:18:51 +00:00
DeltricandHiroku af14c7d505 Handle battle crashes and log them 2023-06-25 00:18:51 +00:00
Hiroku 4148773881 Merge branch 'fixes-and-api' into 'main'
Various fixes and API enhancements

See merge request cable-mc/cobblemon!508
2023-06-24 06:11:40 +00:00
DeltricandHiroku 6ffdd5c3c7 Various fixes and API enhancements 2023-06-24 06:11:40 +00:00
Hiroku 7d253c505a Merge branch 'whatsy-main-patch-45454' into 'main'
Update CHANGELOG.md

See merge request cable-mc/cobblemon!507
2023-06-23 23:56:17 +00:00
Lily 827ea20bd7 Update CHANGELOG.md 2023-06-23 23:41:04 +00:00
Nick 63689e14a0 Merge branch 'fix-battle-messages' into 'main'
Fix battle messages

See merge request cable-mc/cobblemon!506
2023-06-23 21:44:33 +00:00
LilyandNick b82c40feb2 Fix battle messages 2023-06-23 21:44:33 +00:00
Paul ed85324b3a Removed a bunch of angry recipes and advancements that I already deleted once already 2023-06-23 22:15:06 +10:00
Paul 0ab9b19c4b Merge remote-tracking branch 'origin/main' into revival-herbs
# Conflicts:
#	CHANGELOG.md
#	common/src/main/kotlin/com/cobblemon/mod/common/CobblemonItems.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/CobblemonMechanics.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/block/BigRootBlock.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/block/EnergyRootBlock.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/item/interactive/RemedyItem.kt
#	common/src/main/resources/data/cobblemon/loot_tables/blocks/medicinal_leek_crop.json
2023-06-23 22:06:33 +10:00
Paul 50a33598e8 Resolved startup errors by removing advancements and recipes that aren't in yet 2023-06-23 22:03:56 +10:00
Hiroku ef81050be9 Merge branch 'fix-pc-command' into 'main'
fix no opening sound when using /pc

See merge request cable-mc/cobblemon!505
2023-06-23 02:06:39 +00:00
LilyandHiroku cb95aa2466 fix no opening sound when using /pc 2023-06-23 02:06:39 +00:00
Nick a4fb1e1e6e Merge branch 'revival-herbs' into 'main'
Many crops

See merge request cable-mc/cobblemon!503
2023-06-23 00:48:00 +00:00
HirokuandNick 1c4b146500 Many crops 2023-06-23 00:47:59 +00:00
Hiroku 6fbe1774f8 Update README.md [skip-ci] 2023-06-22 23:26:26 +00:00
Hiroku 85960ff726 Update README.md 2023-06-22 23:26:01 +00:00
Nick 254b4bee80 Merge branch 'species-form-visibility-changes' into 'main'
Species/FormData property visibility changes.

See merge request cable-mc/cobblemon!502
2023-06-21 16:40:15 +00:00
LiciousandNick 489357ee91 Species/FormData property visibility changes. 2023-06-21 16:40:14 +00:00
Paul 600669e1c5 Added a bunch of items, improved PokemonInteractiveItem, remedy datapack logic 2023-06-19 07:53:12 +10:00
Hiroku d3ff4984fe Update CHANGELOG.md [skip-ci] 2023-06-18 00:29:47 +00:00
Paul f61a30ab26 Merge remote-tracking branch 'origin/xvitarecipes' into revival-herbs
# Conflicts:
#	common/src/main/resources/data/cobblemon/loot_tables/blocks/revival_herb.json
2023-06-18 09:10:31 +10:00
Paul aa77473288 Make mints more rare for realsies 2023-06-18 08:36:04 +10:00
Paul 2f837b34fc Fixed energy and big roots not dropping anything 2023-06-17 21:27:06 +10:00
Paul d7ca55597e Made mints rarer 2023-06-17 21:25:45 +10:00
Paul 331278d1b3 Finalized brewing mechanism, added incorrectly-textured medicinal brew w/ recipe 2023-06-17 20:13:35 +10:00
Paul 669a119bf5 Merge remote-tracking branch 'origin/custom-brewing-basis-1.19.3' into revival-herbs
# Conflicts:
#	fabric/src/main/kotlin/com/cobblemon/mod/fabric/CobblemonFabric.kt
#	forge/src/main/kotlin/com/cobblemon/mod/forge/CobblemonForge.kt
2023-06-17 12:24:34 +10:00
Paul 3813cdec4b Big Root / Energy Root polish and API 2023-06-17 12:07:23 +10:00
Paul f6380a72e3 Merge remote-tracking branch 'origin/main' into revival-herbs 2023-06-17 11:58:57 +10:00
Hiroku 6fe48faff8 we are snapshotting (gradle.properties) 2023-06-17 01:37:46 +00:00
Hiroku 68b9f09697 Prevent subsequent stages from running CI if skipped first 2023-06-17 01:21:36 +00:00
Hiroku 2080f2f109 Update CI not to run for forks 2023-06-17 01:18:23 +00:00
Paul 933ba72d04 Merge remote-tracking branch 'origin/main' into revival-herbs 2023-06-16 22:53:22 +10:00
Paul 7f19026c71 Update Big Root / Energy Root behaviours 2023-06-16 22:51:14 +10:00
Paul 64e5e9aeb0 Removed gloom textures that should not have been there 2023-06-16 18:07:39 +10:00
Paul f6635b5575 Merge remote-tracking branch 'origin/main' into new-commands 2023-06-16 17:30:13 +10:00
Paul 77fa5f5787 Improved clear party command 2023-06-16 17:29:58 +10:00
dhi_holo 12ad46935c im sorry
some day i may not forget
2023-06-16 17:19:16 +10:00
dhi_holo c3b54fc55b Merge branch 'main' into xvitarecipes 2023-06-16 17:16:51 +10:00
Hiroku 46101206f7 Merge branch 'chromatemp' into 'main'
Small Changelog fix

See merge request cable-mc/cobblemon!500
2023-06-16 07:14:18 +00:00
HexeChromaandHiroku 81150c5ef6 Small Changelog fix 2023-06-16 07:14:18 +00:00
Paul 10e8d702c2 Merge remote-tracking branch 'origin/main'
# Conflicts:
#	common/src/main/kotlin/com/cobblemon/mod/common/client/CobblemonClient.kt
2023-06-16 15:54:16 +10:00
Paul f5ba14ae65 Hoes for apricorn tree leaves and fixed those leaves looking bad on fast graphics 2023-06-16 15:54:04 +10:00
Hiroku 5ef6c587a8 Merge branch 'HexeChroma-main-patch-93627' into 'main'
Update CobblemonClient.kt

See merge request cable-mc/cobblemon!498
2023-06-16 03:19:52 +00:00
HexeChromaandHiroku 2ba484024c Update CobblemonClient.kt 2023-06-16 03:19:51 +00:00
Paul 687a4aa935 Undo some changes that were not intended for this branch 2023-06-16 12:07:43 +10:00
Paul 5cc297c4af Merge conflict resolution 2023-06-16 11:31:24 +10:00
Hiroku ccd4a5237d Merge branch 'new-commands' into 'new-commands'
New command to adjust pokemon walk speed.

See merge request cable-mc/cobblemon!487
2023-06-16 01:04:11 +00:00
DaBatandHiroku 6ad02118a9 New command to adjust pokemon walk speed. 2023-06-16 01:04:10 +00:00
Paul 89bb983925 Restore changelog work overwritten by last merge 2023-06-16 11:02:15 +10:00
Hiroku de2dc38778 Merge branch 'added-sounds' into 'main'
Added cries for Gen 5-7 starters

See merge request cable-mc/cobblemon!491
2023-06-16 01:00:56 +00:00
SterrezoandHiroku fbcaa7353f Added cries for Gen 5-7 starters 2023-06-16 01:00:56 +00:00
Hiroku abf4f97f00 Merge branch 'interpreter_refactory' into 'main'
Battle window improvements and interpreter refactory

See merge request cable-mc/cobblemon!492
2023-06-16 00:56:37 +00:00
Hiroku a0736e550d Merge branch 'ys/waterlog-pc' into 'main'
implement waterloggable pc

See merge request cable-mc/cobblemon!496
2023-06-15 22:16:26 +00:00
YaseenandHiroku ea46a2973f implement waterloggable pc 2023-06-15 22:16:26 +00:00
Hiroku 26a9d8d07f Merge branch 'ys/draw-triangles-fix' into 'main'
Fix for stats hexagon

See merge request cable-mc/cobblemon!497
2023-06-15 22:09:08 +00:00
YaseenandHiroku 71bba4296b Fix for stats hexagon 2023-06-15 22:09:08 +00:00
Licious eb26ffa7ca Fixed being locked out of healing machines if it goes boom during use. 2023-06-15 22:45:21 +01:00
Hiroku 0038f7428b Merge branch 'ys/waterlogging-tethers' into 'tethers'
Making the tether/pasture block waterloggable

See merge request cable-mc/cobblemon!495
2023-06-15 21:20:15 +00:00
YaseenandHiroku 1fd1cf32a2 Making the tether/pasture block waterloggable 2023-06-15 21:20:15 +00:00
Hiroku 57a7dccd37 Merge branch 'tooltip-changes' into 'main'
Tooltip changes

See merge request cable-mc/cobblemon!494
2023-06-15 21:19:22 +00:00
LiciousandHiroku 5fa56177fc Tooltip changes 2023-06-15 21:19:22 +00:00
Hiroku d68d630175 Merge branch 'french-toast-is-better' into 'main'
Implement toast API

Closes #288

See merge request cable-mc/cobblemon!489
2023-06-15 10:06:04 +00:00
LiciousandHiroku 662ae77944 Implement toast API 2023-06-15 10:06:04 +00:00
dhi_holo b219999945 Update superb_remedy.json 2023-06-15 13:05:56 +10:00
dhi_holo 467ae236b5 Merge branch 'main' into xvitarecipes 2023-06-15 12:55:29 +10:00
dhi_holo 4d2c298c00 Moistch
all 18 mulch recipes+unlock advancements, still not certain on the IDs but just felt like writing them today
2023-06-15 12:55:24 +10:00
Nick 469fb8dd52 Merge branch 'loot-table-appending' into 'main'
Implemented LootTable injection

Closes #217

See merge request cable-mc/cobblemon!490
2023-06-13 17:21:40 +00:00
LiciousandNick 371f2ac08a Implemented LootTable injection 2023-06-13 17:21:39 +00:00
Segfault Guy 3d20d7635b Add color to important langs. Refactor lang construction for -item, -enditem, and more. Broadcast ability activations. 2023-06-13 12:20:17 -04:00
Segfault Guy f67f8007fb Condense battle lang construction and fix lang inconsistencies 2023-06-13 10:34:00 -04:00
Segfault Guy a1516ecf10 Tweak dispatch timing to improve battle window flow 2023-06-13 10:30:31 -04:00
Segfault Guy 6c2ae912d1 Refactor all interpreter handlers to use BattleMessage system 2023-06-13 10:30:31 -04:00
Paul 78711ea675 Fixed revival herb blockstate, I promise I'm a good dev 2023-06-11 11:45:46 +10:00
dhi_holo 0867de8257 Update revival_herb.json
fixed minor oversight
2023-06-11 10:55:51 +10:00
Paul 62720b8d15 Revival herb age should probably start at zero rather than one 2023-06-11 10:53:02 +10:00
Paul 00f7a859f4 Revival herb render and generation 'finished' - needs optimising 2023-06-10 21:56:26 +10:00
dhi_holo 280d144dcf Potentially Functional New Loot table?
I'll be honest, I don't really understand, but I fell down this hill- wait this is a commit and I'm braindying

This loot table should, in theory, work how it's outlined in the document. Hopefully.
I'll probably come back to it in future to investigate fortune mechanics, but we'll come back to that if this file doesn't break everything first
2023-06-10 17:51:56 +10:00
dhi_holo f2daba8ae8 Merge branch 'main' into xvitarecipes 2023-06-10 17:50:01 +10:00
Paul 8076287376 Merge remote-tracking branch 'origin/energy-roots' into revival-herbs
# Conflicts:
#	common/src/main/kotlin/com/cobblemon/mod/common/CobblemonBlocks.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/CobblemonItems.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/world/feature/CobblemonPlacedFeatures.kt
2023-06-10 12:44:54 +10:00
Paul d54c4ced74 Added revival herbs mostly and pep up flowers 2023-06-10 12:43:35 +10:00
Paul 4aeedb1751 Merge remote-tracking branch 'origin/main' into revival-herbs 2023-06-09 16:47:45 +10:00
Hiroku 54c591b51f Merge branch 'maven-deployment' into 'main'
Add new maven deployment job

See merge request cable-mc/cobblemon!488
2023-06-07 07:57:55 +00:00
Paul 620ef585ce Changelog for trading completed. Closes #92 2023-06-07 17:56:07 +10:00
Paul 9601cf49ce Merge remote-tracking branch 'origin/main' into trading 2023-06-07 17:55:13 +10:00
Paul 56088e3a40 Make Nick happy 2023-06-07 17:52:56 +10:00
Nick 5b8149ce82 Add new maven deployment job 2023-06-06 21:02:46 -07:00
dhi_holo 2f5b2bc2df Remedying
Remedy/Superb Remedy have the Big and Energy Roots flipped around
Feathers now cost one less mint
Revives redone
Leek and Potato Stew now cooked
2023-06-07 10:47:25 +10:00
dhi_holo 19a3244102 Merge branch 'main' into xvitarecipes 2023-06-07 10:37:06 +10:00
Paul 49987de803 Lang tooltip for energy root 2023-06-05 12:07:25 +10:00
Hiroku 332981a198 Update CHANGELOG.md [skip-ci] 2023-06-04 22:49:31 +00:00
Hiroku 5c026d7494 Merge branch 'add-persistent-data-to-pokemon' into 'main'
add Pokemon Persistent Data

See merge request cable-mc/cobblemon!484
2023-06-04 22:47:59 +00:00
Hiroku bb7342cd2d Merge branch 'added-sounds' into 'main'
Added cries for Braixen, Chatot, Chespin, Conkeldurr, Darmanitan, Darumaka,...

See merge request cable-mc/cobblemon!486
2023-06-04 22:42:40 +00:00
SterrezoandHiroku 90d1797cb4 Added cries for Braixen, Chatot, Chespin, Conkeldurr, Darmanitan, Darumaka,... 2023-06-04 22:42:40 +00:00
Paul 5dab0f060e Energy root fixes 2023-06-04 20:44:39 +10:00
Paul 03b17b050a Added energy root w/ world generation sans testing 2023-06-04 11:35:16 +10:00
Paul 2cc44d32fb Added BeneathHeightmapPlacementModifier 2023-06-04 11:35:09 +10:00
Paul 4be66e4993 Merge remote-tracking branch 'origin/main' into energy-roots 2023-06-03 18:29:02 +10:00
Paul 04cb83b13e Tint the trade and battle challenge icons if a request exists 2023-06-03 11:04:43 +10:00
Paul d8a5ffa567 Fixed langs being broken in many cases (anything with 'pokemon' in the key 2023-06-03 11:04:17 +10:00
Village be2cc7e445 license 2023-06-02 15:19:40 -04:00
Paul 07cfd61ebe Removed debug sound 2023-06-02 14:02:25 +10:00
Paul a7fe48ec20 Show EVs on trade GUI, fixed models display glitching on resize 2023-06-02 14:00:26 +10:00
Oliver Whitehead 1c1cb3e91f add Pokemon Persistent Data 2023-06-02 01:27:22 +01:00
Paul bfb14ff828 Allow multiple trades per active trade 2023-06-02 10:02:52 +10:00
jmmcp 36fcb12add Added potion recipes to access widener and an example recipe for it 2023-05-31 18:04:37 -04:00
Paul c7ff0c7e39 More fixes and implementations of lang for trading 2023-05-31 23:07:45 +10:00
dhi_holo 4a1bbd1e6a Herbal
Braised Vivichoke, Vivichoke Dip, Remedy, Fine Remedy, Superb Remedy, Revive, Max Revive, Heal Powder, recipes and unlock advancements, and typo fix for Roasted Leek
2023-05-31 22:24:25 +10:00
dhi_holo a859ea205b Merge branch 'main' into xvitarecipes 2023-05-31 21:25:39 +10:00
dhi_holo 6b41168626 Leeks!
Leek and Potato Stew, Roasted Leek, and Medicinal Leek to Magenta Dye recipes and advancements
2023-05-31 21:25:24 +10:00
dhi_holo cb4479a7a1 EV Recipes
Updates PP Up and PP Max to new recipes, adds recipes for the six Effort Feathers, adds recipe for the Pasture block, adds a "berries" tag and Berry Juice recipe. All also have an unlock advancement for the recipe book
2023-05-31 20:28:32 +10:00
Paul 3f4d2c7f8c Implement opposite party data in trade GUI 2023-05-30 19:53:48 +10:00
Village aa31776bf3 prevent modification of display name MutableText, nudge gender icon to prevent overlap 2023-05-29 21:22:53 -04:00
dhi_holo 6dbe92e093 Updates, people, updates
Added finalized recipes for the 8 Vitamins, plus unlock recipes for them.
Removed the X-Item recipes for now, they're not needed, was only in the initial branch for critiquing and repos keep copies of that so we good.

Reorganised the Recipe Advancements folders to match the new creative tab layout, that's the majority of the changes, but it's really not anything noteworthy, just keeping it clean for future additions.

Need to look into the advancement tab background stuff, something funky's going on, but I couldn't figure it out tonight
2023-05-29 19:14:15 +10:00
Paul f75c0aeab4 Merge remote-tracking branch 'origin/main' into trading
# Conflicts:
#	common/src/main/kotlin/com/cobblemon/mod/common/Cobblemon.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/CobblemonNetwork.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/battles/BattleRegistry.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/client/keybind/keybinds/PartySendBinding.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/client/render/item/PokemonItemRenderer.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/command/TestCommand.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/item/PokemonItem.kt
#	common/src/main/resources/assets/cobblemon/lang/en_us.json
2023-05-29 18:35:11 +10:00
Village 952ad6e0d2 trade 2023-05-29 03:36:41 -04:00
Paul 0f0e6b0142 Pasture GUI work 2023-05-29 15:13:37 +10:00
Village 2a41f431bb trade 2023-05-28 23:38:27 -04:00
Paul 63a779cb1e Fixed custom brewing recipes on Forge I think 2023-05-28 23:15:46 +10:00
dhi_holo 27bcdadac6 damn file didn't save properly 2023-05-28 15:26:12 +10:00
dhi_holo 18e1caff39 WIP Recipes
Adds recipes for the battle and vitamin items (using some items yet to be implemented), as well as two tags for protein/zinc crafting

PP Up/Max needs going over, and Dire Hit needs approving in general, and all recipes still need advancements, but I wanted to make sure it was in team space, not my laptop exclusively, so it was easier to read over
2023-05-28 14:47:57 +10:00
jmmcp d9af350ab6 Merge remote-tracking branch 'origin/main' into custom-brewing-basis-1.19.3
# Conflicts:
#	common/src/main/kotlin/com/cobblemon/mod/common/Cobblemon.kt
#	common/src/main/resources/cobblemon-common.accesswidener
2023-05-28 00:29:30 -04:00
jmmcp ca6461499f Placed/Configured Feature tweaks 2023-05-28 00:06:28 -04:00
Paul 71bee3edd2 Fixed metal coat not being in the creative tabs 2023-05-28 11:06:55 +10:00
Paul 2c50d5f523 Merge remote-tracking branch 'origin/main' into tethers 2023-05-28 11:04:54 +10:00
Paul 721823117a Added trader party to trade GUI initializer 2023-05-28 07:00:28 +10:00
jmmcp e87d6eabab Placed/Configured Feature beginnings 2023-05-27 00:07:19 -04:00
Hiroku 2387639cea See above 2023-05-23 21:59:12 +00:00
Hiroku 83fdcceaa7 You saw nothing 2023-05-23 21:57:48 +00:00
Hiroku 8db77bcaea Say stats instead of nature with mints 2023-05-23 21:53:15 +00:00
jmmcp 6f9b80c3b0 Merge remote-tracking branch 'origin/main' into medicinal_leeks
# Conflicts:
#	common/src/main/kotlin/com/cobblemon/mod/common/CobblemonBlocks.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/CobblemonItems.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/client/CobblemonClient.kt
2023-05-23 17:08:34 -04:00
Paul 85f4345f5c Made apricorn tree placed feature less dumb, improve pasture block collider 2023-05-20 23:17:20 +10:00
Paul 71d0e56c20 Merge corrections, pasture block fixes 2023-05-19 22:57:08 +10:00
Paul 5b78ba6329 Merge remote-tracking branch 'origin/main' into tethers
# Conflicts:
#	common/src/main/kotlin/com/cobblemon/mod/common/CobblemonBlocks.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/entity/pokemon/PokemonEntity.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/net/messages/client/pokemon/update/NatureUpdatePacket.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/net/messages/client/spawn/SpawnPokemonPacket.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/pokemon/Pokemon.kt
2023-05-19 13:04:52 +10:00
Paul 1dbe2cc993 Added new pasture model 2023-05-19 13:03:53 +10:00
Paul 1c942ce83c Move version number up to 1.4.0 2023-05-17 20:44:06 +10:00
Paul 2d3ff73530 Merge remote-tracking branch 'origin/main' 2023-05-17 20:40:09 +10:00
Paul 4d5bc93702 Fixed Forge runs 2023-05-17 20:39:22 +10:00
Deltric b4dc4f4a05 Setup Pasture Block w/ backend logic + packets 2023-05-17 04:04:17 -05:00
Hiroku cdf41a5b13 Merge branch '1.19.3-particle-camera-modes' into 'main'
1.19.3 particle camera modes

See merge request cable-mc/cobblemon!479
2023-05-15 20:57:09 +00:00
Hiroku 9651025bef 1.19.3 particle camera modes 2023-05-15 20:57:08 +00:00
Paul 54a9412a5c Moved spawn frequency to config option. Closes #260 2023-05-15 18:32:08 +10:00
Paul 4bfeda2031 Substantially reduced default frequency of Pokémon cries (default is now once in 54 seconds). Closes #265 2023-05-15 18:25:18 +10:00
Paul ed136ecabb Fixed invalid action choices from AI causing crashes. Closes #284 2023-05-15 18:05:46 +10:00
Paul 2f0eb7c246 Fixed logging spam when loading shoulder mounted Pokémon on the client. Closes #289 2023-05-15 18:01:46 +10:00
Hiroku ea0c16bf01 Merge branch '#279-heal-wild-pokemon' into 'main'
HealWildOnDefeatOrRun

See merge request cable-mc/cobblemon!476
2023-05-14 00:04:30 +00:00
IslanaandHiroku 18d6917e9f HealWildOnDefeatOrRun 2023-05-14 00:04:30 +00:00
Paul 039c5993f5 Sprite/block texture updates, fix deepslate water stone ore looking like deepslate fire stone ore 2023-05-14 09:09:56 +10:00
Hiroku 8394d9f0f0 Merge branch 'bad-world-squeezewithinbounds' into 'main'
Fixed World.squeezeWithinBounds squeezing z coordinates using border's x coordinates

See merge request cable-mc/cobblemon!478
2023-05-13 11:46:17 +00:00
David Sadler 1b791abbe0 Fixed World.squeezeWithinBounds squeezing z coordinates using border's x coordinates 2023-05-13 12:37:00 +01:00
Hiroku ed07a915dc Merge branch '273-pokemon-spawn-outside-world-border' into 'main'
Fixed pokemon spawning outside world border

Closes #273

See merge request cable-mc/cobblemon!477
2023-05-13 10:28:27 +00:00
selfdotandHiroku 513221a7dd Fixed pokemon spawning outside world border 2023-05-13 10:28:26 +00:00
Paul cd5556f2e3 Added debug components in TestCommand.kt and TradeParticipant.kt for trading GUI testing 2023-05-12 16:13:53 +10:00
Paul db99c7f4b0 Lowered chance of white mints dropping random-colour additional seeds 2023-05-12 15:03:03 +10:00
Paul 581c9b5844 Fixed Pokéball item rendering in inventory (lighting) and player model (everything) 2023-05-11 22:00:17 +10:00
Paul 6403ea5a18 Made mints rarer, fixed calm mint recipe 2023-05-11 21:21:52 +10:00
Paul 36772de3e0 Changelog for mints [skip-ci] 2023-05-11 20:10:37 +10:00
Hiroku 3ccdb48939 Merge branch 'mints' into 'main'
Add mints

See merge request cable-mc/cobblemon!475
2023-05-11 10:07:11 +00:00
LandonandHiroku 058ac88f19 Add mints 2023-05-11 10:07:11 +00:00
jmmcp 23a9399284 Updated licenses 2023-05-10 11:31:37 -04:00
jmmcp f67c35541d Added the basis for Medicinal Leeks and its crop block. This push includes implementation of the item and crop block itself as well as the logic behind them. 2023-05-10 00:15:08 -04:00
Paul 71224066a8 Added structure identifier / tag spawn conditions 2023-05-06 10:34:28 +10:00
Paul 950c5b2c82 Fixed labels and lighting issues with Pokémon item frames 2023-04-29 22:34:04 +10:00
Paul 107252b1dd Added scale animation support, and jump keyframes 2023-04-29 22:32:52 +10:00
Paul 72da390ad4 Fixed faints not working right in add-ons 2023-04-27 22:52:17 +10:00
Hiroku 603336f740 Merge branch 'ys/battle-lang-implementations' into 'main'
Battle lang implementations

See merge request cable-mc/cobblemon!471
2023-04-27 10:35:32 +00:00
YaseenandHiroku 83ab81fd37 Battle lang implementations 2023-04-27 10:35:32 +00:00
Hiroku a0ef28effd Merge branch 'ys/recoil-flee-issue-fix' into 'main'
Dont flee while theres some battle messages left to process

Closes #277

See merge request cable-mc/cobblemon!472
2023-04-27 09:11:47 +00:00
YaseenandHiroku ea20dc7c60 Dont flee while theres some battle messages left to process 2023-04-27 09:11:47 +00:00
Hiroku da473c9951 Merge branch 'main' into 'main'
Add missing shoulderMountable key to Eiscue & Tatsugiri's species files

See merge request cable-mc/cobblemon!470
2023-04-26 22:07:51 +00:00
Xander ForrestandHiroku ae33cf7b5c Add missing shoulderMountable key to Eiscue & Tatsugiri's species files 2023-04-26 22:07:51 +00:00
Hiroku d2626b9a0e Merge branch 'battle_context' into 'main'
Add BattleContext and ContextManager to track battle state. Add BattleFaintedEvent. Refactor ShowdownInterpreter handlers.

See merge request cable-mc/cobblemon!454
2023-04-26 09:38:03 +00:00
Segfault Guy d2f6987ce5 Context for boosts. Finished Minor/Major action history. ContextManager expansion and fixes. 2023-04-26 00:28:38 -04:00
Segfault Guy af142abd90 Fix bug where contexts can't be created from conditions caused by -activate and -ability instructions 2023-04-26 00:28:38 -04:00
Segfault Guy c072b6525c Add BattleContext, ContextManager, and BattleFaintedEvent. 2023-04-26 00:28:18 -04:00
Segfault Guy 73777a3873 resolved conflict 2023-04-26 00:19:46 -04:00
Hiroku ae2ed8e1e6 Merge branch '236-pokeball-animation-issue' into 'main'
Issue Fix 236

Closes #236

See merge request cable-mc/cobblemon!468
2023-04-25 21:25:07 +00:00
Cameron PierceandHiroku 7718bac2e5 Issue Fix 236 2023-04-25 21:25:06 +00:00
Hiroku 1dc6f06b94 Merge branch 'nosepass-points-at-spawn' into 'main'
Made Nosepass point towards spawn while idle

Closes #238

See merge request cable-mc/cobblemon!465
2023-04-25 10:13:29 +00:00
selfdotandHiroku 8bb16b8d00 Made Nosepass point towards spawn while idle 2023-04-25 10:13:29 +00:00
Hiroku 8f8fa7efb7 Merge branch 'fix_leech_seed_messages' into 'main'
Implement Leech Seed messages

See merge request cable-mc/cobblemon!467
2023-04-25 10:09:48 +00:00
paperandHiroku 6d58b69be6 Implement Leech Seed messages 2023-04-25 10:09:48 +00:00
Hiroku 99e501ae3c Merge branch 'main' into 'main'
Properly set the velocity of spawned entities

Closes #223

See merge request cable-mc/cobblemon!466
2023-04-25 10:06:20 +00:00
Justin L. Wells ea41803ccb Properly set the velocity of spawned entities 2023-04-24 20:27:12 -05:00
Paul e1c29b7423 Merged 1.19.3 into main 2023-04-24 22:34:42 +10:00
Paul a1df69c67a Merge remote-tracking branch 'origin/1.19.3'
# Conflicts:
#	common/build.gradle.kts
#	common/src/main/kotlin/com/cobblemon/mod/common/CobblemonNetwork.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/CobblemonSounds.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/api/events/CobblemonEvents.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/battles/ShowdownInterpreter.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/client/net/ClientPacketRegistrar.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/entity/pokemon/PokemonEntity.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/entity/pokemon/ai/goals/WildRestGoal.kt
#	common/src/main/resources/assets/cobblemon/lang/en_us.json
2023-04-24 21:43:41 +10:00
Hiroku 2b91acd6ad Merge branch 'ys/fix-test-commands' into '1.19.3'
Fix test commands

See merge request cable-mc/cobblemon!464
2023-04-24 11:15:41 +00:00
Paul 96a6f2adeb Licenses 2023-04-24 18:02:32 +10:00
Hiroku 509e473e4f Merge branch 'battle_music' into 'main'
Battle music system for Pokémon battles

See merge request cable-mc/cobblemon!463
2023-04-24 06:22:07 +00:00
Hiroku ae825f5e29 Merge branch 'main' into 'battle_music'
# Conflicts:
#   common/src/main/kotlin/com/cobblemon/mod/common/CobblemonNetwork.kt
#   common/src/main/kotlin/com/cobblemon/mod/common/battles/ShowdownInterpreter.kt
#   common/src/main/kotlin/com/cobblemon/mod/common/client/net/ClientPacketRegistrar.kt
2023-04-24 06:20:24 +00:00
Paul 36de85ccb0 Syntactical cleaning 2023-04-24 14:14:11 +10:00
Paul b47892892d Fixed battles not starting properly 2023-04-24 11:09:41 +10:00
Yaseen 9bde52c73e Fix test commands 2023-04-23 23:12:26 +01:00
Paul 469a350497 Compilation error fix 2023-04-22 23:36:45 +10:00
Hiroku 5abc147442 Merge branch 'storage-fixes' into '1.19.3'
Miscellaneous Storage fixes

See merge request cable-mc/cobblemon!452
2023-04-22 12:54:39 +00:00
DeltricandHiroku 390d3b5518 Miscellaneous Storage fixes 2023-04-22 12:54:39 +00:00
Hiroku ead25288a0 Merge branch 'ys/fix-sleep' into 'main'
Sleep fix

See merge request cable-mc/cobblemon!456
2023-04-22 12:51:19 +00:00
YaseenandHiroku 030ba82109 Sleep fix 2023-04-22 12:51:19 +00:00
Hiroku 396aaecdb6 Merge branch 'ys/fix-ability-traps' into 'main'
Fix abilities that should trap pokemon

See merge request cable-mc/cobblemon!457
2023-04-22 12:49:36 +00:00
YaseenandHiroku b7e752da64 Fix abilities that should trap pokemon 2023-04-22 12:49:36 +00:00
Hiroku c014362025 Merge branch 'ys/new-commands' into '1.19.3'
Added testpcslot and testpartyslot commands

See merge request cable-mc/cobblemon!461
2023-04-22 12:47:58 +00:00
YaseenandHiroku 1f86abd8db Added testpcslot and testpartyslot commands 2023-04-22 12:47:58 +00:00
Paul b9cf702042 Nicknaming fixing 2023-04-22 22:24:54 +10:00
Hiroku b07b20ef3c Merge branch 'nicknames-1.19.3' into '1.19.3'
Implemented nicknames on 1.19.3 branch

See merge request cable-mc/cobblemon!415
2023-04-22 09:26:20 +00:00
selfdotandHiroku 24692f57f6 Implemented nicknames on 1.19.3 branch 2023-04-22 09:26:20 +00:00
Segfault Guy 8e08782cd1 Fire BattleMusicPacket and BattleMusicHandler on battle start and end 2023-04-22 00:42:54 -04:00
Paul dc4ad24004 changelog [skip-ci] 2023-04-22 12:13:17 +10:00
Hiroku 22171add23 Merge branch 'pokespawn-event' into 'main'
Pokespawn event

See merge request cable-mc/cobblemon!439
2023-04-22 02:12:08 +00:00
amoandHiroku 073901ae7a Pokespawn event 2023-04-22 02:12:08 +00:00
Hiroku 5c092661de Merge branch 'ys/mineable-block-tags' into 'main'
Making blocks mineable using tools

Closes #272 and #263

See merge request cable-mc/cobblemon!458
2023-04-22 01:47:35 +00:00
YaseenandHiroku 4eb130e9fd Making blocks mineable using tools 2023-04-22 01:47:35 +00:00
Hiroku 33fb5a3ab9 Merge branch 'moon-phases' into '1.19.3'
Fixes moon phase spawn condition being checked in reverse

See merge request cable-mc/cobblemon!462
2023-04-22 01:46:23 +00:00
selfdotandHiroku 7bbbddc580 Fixes moon phase spawn condition being checked in reverse 2023-04-22 01:46:23 +00:00
Paul 60fb7231c7 Added isBattle, isTouchingWater to pose JSON, added isVisible to transformed part JSON 2023-04-21 19:37:14 +10:00
Paul 5d84ee5ac6 Merge remote-tracking branch 'origin/tethers' into tethers 2023-04-20 22:15:24 +10:00
Paul 048dcf785d More packets and fixes for pasture blocks 2023-04-20 22:14:09 +10:00
Hiroku a244c56c4c Merge branch 'ys/fix-spawning-prospector' into 'main'
Spawning Prospector fix

Closes #270

See merge request cable-mc/cobblemon!460
2023-04-20 10:20:42 +00:00
YaseenandHiroku 5f793be70d Spawning Prospector fix 2023-04-20 10:20:42 +00:00
Hiroku a5e46e900f Merge branch 'ys/pokemon-item-fix' into 'main'
Fix getSpeciesAndAspects

See merge request cable-mc/cobblemon!455
2023-04-20 09:26:04 +00:00
YaseenandHiroku bb9f4b6a9a Fix getSpeciesAndAspects 2023-04-20 09:26:04 +00:00
Village 03f6b79f0b slot overlay 2023-04-16 20:55:44 -04:00
Hiroku 642fa11cb2 Merge branch '1.19.4' into '1.19.3'
What seems backwards is actually forwards

See merge request cable-mc/cobblemon!453
2023-04-16 14:02:05 +00:00
DeltricandHiroku 22ce696423 What seems backwards is actually forwards 2023-04-16 14:02:04 +00:00
Paul e88cbc1618 Gen 9 french translations 2023-04-12 21:24:54 +10:00
Paul 2f7084ae15 Networking and PC integration for pasture block 2023-04-12 21:17:02 +10:00
Hiroku a392a087dc Merge branch 'misc-battle-interpretations' into '1.19.3'
Disable, Lock On, and Protosynthesis

See merge request cable-mc/cobblemon!451
2023-04-09 11:28:56 +00:00
DeltricandHiroku 0081e60cd5 Disable, Lock On, and Protosynthesis 2023-04-09 11:28:56 +00:00
dhi_holo 3d94cf2c11 Minor Advancement Visual Update
Improved quality of Cobblemon logos, and switched the Shiny achievement icon from Charizard to Gyarados
2023-04-09 17:16:16 +10:00
Hiroku 50588cf372 Merge branch 'misc_fixes' into 'main'
Misc small Fixes

See merge request cable-mc/cobblemon!450
2023-04-09 04:33:39 +00:00
TyzillionandHiroku dd8e4ee0a3 Misc small Fixes 2023-04-09 04:33:38 +00:00
Paul 594d188de7 Pasture block supports limited wandering, save and load logic 2023-04-08 18:20:23 +10:00
Hiroku dd8ff8ef36 Merge branch 'learnset-query-command' into '1.19.3'
Learnset query command for command block/mcfunction use

See merge request cable-mc/cobblemon!449
2023-04-07 18:30:07 +00:00
LiciousandHiroku 7cf46baa98 Learnset query command for command block/mcfunction use 2023-04-07 18:30:07 +00:00
Licious17 6c5efcd69b Fix shouldered Pokémon not gaining passive friendship as if they were sent out. 2023-04-07 10:13:13 +01:00
Hiroku 9d109a9584 Merge branch 'struggle-messages' into 'main'
Implemented messages for struggling

See merge request cable-mc/cobblemon!440
2023-04-07 02:17:28 +00:00
DeltricandHiroku fdef9d9837 Implemented messages for struggling 2023-04-07 02:17:28 +00:00
Hiroku d9cc185052 Merge branch 'main' into 'main'
Update move,ability and pokedex for zh_cn.json

See merge request cable-mc/cobblemon!444
2023-04-07 01:48:29 +00:00
Yyi yunandHiroku 1fdf2b53ff Update move,ability and pokedex for zh_cn.json 2023-04-07 01:48:28 +00:00
Licious17 5c60f2634d Fix starter options in starter screen facing Narnia, closes #243 2023-04-06 14:47:58 +01:00
Paul b082c3e04d Compile error fix and @JvmField on PokemonPropertyExtractors 2023-04-06 22:07:20 +10:00
dhi_holo 424b4dd401 Advancement Tab GUI Background
Another bitching at Mojang's new Atlas system, Closes issue #245
2023-04-06 22:06:12 +10:00
Paul 1437dbebcf Changelog and licenses 2023-04-06 21:14:38 +10:00
dhi_holo cfb49e7f6c Cobblemon Logos Moved
Mojang made atlas stuff which sucks to deal with in 1.19.3+, so I've moved the textures for the Cobblemon icons from GUI into Items, because Mojang loves ruining stuff that worked for years
2023-04-06 20:50:46 +10:00
Hiroku 107baf4d9a Merge branch 'interpreter_instruction_additions' into 'main'
Add handlers for |-sidestart|, |-sideend|, and |-fieldactivate| instructions to ShowdownInterpreter

See merge request cable-mc/cobblemon!442
2023-04-06 10:23:24 +00:00
Hiroku e739be029a Merge branch 'additional_pokemon_events' into 'main'
Added BattleFled, BattleStarted, PokemonRecalled, and PokemonSent events

See merge request cable-mc/cobblemon!404
2023-04-06 10:10:07 +00:00
Licious bfca02c78f Merge branch 'ut_animation_validation' into 'main'
Validate animations are registered via model AND configuration

See merge request cable-mc/cobblemon!436
2023-04-06 10:01:34 +00:00
NickandLicious 007bc4b212 Validate animations are registered via model AND configuration 2023-04-06 10:01:34 +00:00
Paul bfe1d8bb75 Bunch of work on the pasture block 2023-04-06 19:28:05 +10:00
Hiroku d6fc53d42c Merge branch 'pokemon-store-query-command' into '1.19.3'
Add Pokémon store query command for command block/mcfunction use

See merge request cable-mc/cobblemon!446
2023-04-06 09:23:26 +00:00
LiciousandHiroku 787ce28318 Add Pokémon store query command for command block/mcfunction use 2023-04-06 09:23:26 +00:00
Hiroku b5c10ea372 Merge branch 'species-data-fixes' into '1.19.3'
Species data fixes

See merge request cable-mc/cobblemon!445
2023-04-06 09:21:50 +00:00
LiciousandHiroku 7bc0547c66 Species data fixes 2023-04-06 09:21:50 +00:00
Licious17 9c0babf267 Fix Forge client lifecycle stuff, runs work again 2023-04-06 10:16:06 +01:00
Segfault Guy 0b1915946a Specify status cured on shed skin activation 2023-04-05 01:38:16 -04:00
Segfault Guy fc78d64f62 Add handlers for |-sidestart|, |-sideend|, and |-fieldactivate| instructions 2023-04-05 00:45:19 -04:00
jmmcp 2140384e9f Basis for custom brewing recipes (1.19.3 edition) 2023-04-04 15:55:31 -04:00
Hiroku 3785313dd2 Update PlatformEvents.kt to use @jvmField like it was intended oops 2023-04-03 11:20:04 +00:00
Licious f091c08dd3 Merge branch 'ys/handle-cure-status-fix-and-general-status-fix' into 'main'
Status fixes

See merge request cable-mc/cobblemon!434
2023-04-03 07:41:57 +00:00
Deltric 6e5438040e Updated link cable path 2023-04-03 00:43:19 -05:00
Segfault Guy c35213cb3b Fixed BattleVictoryEvent. Spun BattleFledEvent and InterpretFaint to their own branch. 2023-04-02 23:10:49 -04:00
Segfault Guy 7b2e287b89 Added losers to BattleVictoryEvent 2023-04-02 23:10:49 -04:00
Segfault Guy 5b1f32cc57 Added BattleStartedEvent. Included Pokemon that caused faint in BattleFaintedEvent. Added temporary action history to PokemonBattle. 2023-04-02 23:10:49 -04:00
Segfault Guy faa8f5aae6 Included fleeing player in BattleFledEvent. Fixed misc mistakes. 2023-04-02 23:10:49 -04:00
Segfault Guy 7c3ddf6d03 Fixed BattleFaintedEvent to include killer. Tweaked events. 2023-04-02 23:10:49 -04:00
Segfault Guy 80a6a10293 Added BattleFainted, BattleFled, PokemonRecalled, and PokemonSent events 2023-04-02 23:10:49 -04:00
Paul 65ac3319f3 Updated from main 2023-04-01 18:48:22 +10:00
Paul 045b9fbc9a Merge remote-tracking branch 'origin/main' into 1.19.3
# Conflicts:
#	common/src/main/kotlin/com/cobblemon/mod/common/Cobblemon.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/CobblemonItems.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/CobblemonNetwork.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/api/storage/party/PartyStore.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/client/gui/pc/PCGUI.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/client/net/ClientPacketRegistrar.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/client/net/effect/SpawnSnowstormParticleHandler.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/client/render/MatrixWrapper.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/client/render/models/blockbench/PoseableEntityModel.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/data/CobblemonDataProvider.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/entity/pokeball/EmptyPokeBallEntity.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/entity/pokemon/PokemonEntity.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/entity/pokemon/ai/goals/PokemonInBattleMovementGoal.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/net/serverhandling/storage/party/ReleasePCPokemonHandler.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/net/serverhandling/storage/pc/ReleasePartyPokemonHandler.kt
#	common/src/main/resources/assets/cobblemon/models/item/link_cable.json
#	common/src/main/resources/cobblemon-common.accesswidener
2023-04-01 17:54:36 +10:00
Yaseen b97f447169 Status fixes 2023-04-01 06:27:33 +01:00
Hiroku 21e505e7ad Merge branch 'whoopsies' into 'main'
Fixes my mistake

See merge request cable-mc/cobblemon!433
2023-04-01 04:39:49 +00:00
dhi_holoandHiroku 6f30fc3ee3 Fixes my mistake 2023-04-01 04:39:48 +00:00
Hiroku c52822ef3d Merge branch 'last_minute_changes' into 'main'
Fixed Klink line crash

See merge request cable-mc/cobblemon!432
2023-04-01 03:50:09 +00:00
TyzillionandHiroku 5c349f54d5 Fixed Klink line crash 2023-04-01 03:50:06 +00:00
Paul 64b869f365 Fixed crash when faint animations aren't found isn't found 2023-04-01 13:14:51 +10:00
Hiroku 7c5e9c43f2 Merge branch 'interaction-wheel-ui' into 'trading'
Refactor interaction wheel GUIs

See merge request cable-mc/cobblemon!396
2023-03-26 06:27:56 +00:00
landonjw b10c09b740 Refactor interaction wheel GUIs 2023-03-26 02:07:43 -04:00
Licious17 113e423af1 Merge remote-tracking branch 'origin/1.19.3' into 1.19.3 2023-03-25 21:59:47 +00:00
Licious17 f9cdd9d002 Several fixes & tweaks, Forge currently broken 2023-03-25 21:59:34 +00:00
Paul d2284a8b3b Merge remote-tracking branch 'origin/main' into 1.19.3
# Conflicts:
#	common/src/main/kotlin/com/cobblemon/mod/common/entity/pokemon/PokemonEntity.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/util/PlayerExtensions.kt
2023-03-23 19:24:45 +10:00
Licious17 671c96856f Doc ServerPlayerEvent.RightClickEntity 2023-03-18 22:49:57 +00:00
Licious17 ec625ebc60 Fix bad merge imports 2023-03-18 21:39:09 +00:00
Licious17 ece0347973 Merge branch 'main' into 1.19.3
# Conflicts:
#	common/src/main/kotlin/com/cobblemon/mod/common/Cobblemon.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/client/gui/battle/widgets/BattleMessagePane.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/entity/pokemon/PokemonEntity.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/net/messages/client/pokemon/update/NatureUpdatePacket.kt
#	fabric/src/main/resources/fabric.mod.json
#	forge/src/main/resources/META-INF/mods.toml
#	gradle/libs.versions.yml
2023-03-18 21:18:47 +00:00
Paul 4cc78ba4c6 Many corrections from merge but why are pokeballs doing that thing when thrown 2023-03-16 21:54:30 +10:00
Paul 9b29c800b2 Merge remote-tracking branch 'origin/main' into 1.19.3 2023-03-13 22:00:25 +10:00
Paul 2aa85c4254 Compile errors and general patching for 1.3 -> 1.4 2023-03-13 21:48:59 +10:00
Paul d576022219 Merge conflict stuff 2023-03-13 16:19:15 +10:00
Paul 749c12f1ae Licenses 2023-03-13 14:42:09 +10:00
Paul 1e4258811c Remaining backend trade logic 2023-03-13 13:20:19 +10:00
Paul 7cc5bd6dc8 Fixed pokemon item renderer spamming errors in console 2023-03-12 21:31:15 +10:00
Paul ac8ffc2ca1 More logic for handling requests for battle challenges and trade offer on server and client 2023-03-12 10:10:08 +10:00
Paul 2df57c3166 Client packet handlers for trading 2023-03-10 11:26:21 +10:00
Paul 36f70fffb2 Created S2C packets for trading 2023-03-05 18:26:43 +10:00
Paul 7170537dcf Merge remote-tracking branch 'origin/trading' into trading 2023-03-05 17:49:04 +10:00
Village 49c578d999 interact icons 2023-03-05 02:36:09 -05:00
Paul ce94877c8b Licenses 2023-03-05 12:59:22 +10:00
Paul baa81cef03 Some trade logic, storing trade state and requests 2023-03-05 12:10:19 +10:00
Xylopia c0f998eb82 Added the ClearParty Command, not tested yet due to spawn file messes 2023-03-01 23:23:05 -05:00
Xylopia 69a3ad59cd Merge remote-tracking branch 'origin/spawn-event' into new-commands
# Conflicts:
#	CHANGELOG.md
#	common/src/main/kotlin/com/cobblemon/mod/common/api/spawning/detail/PokemonSpawnAction.kt
2023-03-01 23:14:16 -05:00
Xylopia ebe9c7243d Merge remote-tracking branch 'origin/spawn_fixes' into new-commands
# Conflicts:
#	common/src/main/resources/data/cobblemon/spawn_pool_world/0399_bidoof.json
2023-03-01 23:13:25 -05:00
Veraxiel 3e28bac830 Updated spawn files. Updated Evo-Stone ore files. 2023-02-28 21:36:01 -05:00
Veraxiel df320ab978 Added presets for derelict, treetop, and wilderness. Updated presets foliage and urban. 2023-02-28 14:01:13 -05:00
tyzillion 1d145f78eb Fixed Pokemon Spawns. 2023-02-28 12:45:04 -05:00
Paul e8b23fd0be Fixed spawn packets esp on Forge, fixed various other packets, fixed party overlay again 2023-02-23 23:56:19 +10:00
Licious17 a9e261da03 Fix SpawnExtraDataEntityPacket spawning the entity before applying our data. 2023-02-23 00:17:14 +00:00
Paul 348dd14fc5 Added icon_shiny and move_select that were deleted, fixed math util 2023-02-23 10:04:19 +10:00
Paul 426962aa6b Fixed access widener number 2.0 2023-02-22 21:20:37 +10:00
Paul 40f377f78e Fixed access widener 2023-02-22 20:33:31 +10:00
Paul 39dcae9cb1 Licenses update for 2022 -> 2023 2023-02-22 20:21:59 +10:00
Paul fd8bdf51f2 Licenses 2023-02-22 20:04:30 +10:00
Paul 5eba2230ea Many many corrections from merging main into bye-architectury 2023-02-22 19:35:43 +10:00
Paul 080a7f76bc Merge remote-tracking branch 'origin/main' into bye-architectury
# Conflicts:
#	common/src/main/java/com/cobblemon/mod/common/mixin/ArgumentTypesMixin.java
#	common/src/main/kotlin/com/cobblemon/mod/common/Cobblemon.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/CobblemonBlocks.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/CobblemonClientImplementation.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/CobblemonConfiguredFeatures.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/CobblemonEntities.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/CobblemonFeatures.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/CobblemonImplementation.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/CobblemonNetwork.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/CobblemonPlacements.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/CobblemonSounds.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/api/battles/model/PokemonBattle.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/api/events/entity/EntityAttributeEvent.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/api/events/net/MessageBuiltEvent.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/api/tags/CobblemonItemTags.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/battles/ShowdownInterpreter.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/block/PCBlock.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/client/CobblemonClient.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/client/gui/summary/Summary.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/client/net/ClientPacketHandler.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/client/net/ClientPacketRegistrar.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/client/net/pokemon/update/EvolutionUpdatePacketHandler.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/client/net/pokemon/update/SingleUpdatePacketHandler.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/client/render/pokemon/PokemonRenderer.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/client/render/pokemon/SpeciesAssetResolver.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/entity/pokeball/EmptyPokeBallEntity.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/entity/pokemon/PokemonEntity.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/entity/pokemon/ai/goals/PokemonInBattleMovementGoal.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/item/CobblemonItemGroups.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/net/PacketHandler.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/net/SidedPacketRegistrar.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/net/messages/client/battle/BattleHealthChangePacket.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/net/messages/client/battle/BattleSwitchPokemonPacket.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/net/messages/client/pokemon/update/StringUpdatePacket.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/net/messages/client/pokemon/update/evolution/EvolutionUpdatePacket.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/net/messages/client/storage/EvolutionLikeUpdatePacket.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/net/messages/client/storage/SetPokemonPacket.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/net/messages/server/pokemon/update/evolution/EvolutionDisplayUpdatePacket.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/net/serverhandling/ServerPacketHandler.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/net/serverhandling/ServerPacketRegistrar.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/net/serverhandling/evolution/EvolutionDisplayUpdatePacketHandler.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/pokemon/Pokemon.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/registry/CompletableRegistry.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/util/EventExtensions.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/util/math/geometry/TransformationMatrix.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/world/feature/CobblemonOreConfiguredFeatures.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/world/feature/CobblemonOrePlacedFeatures.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/world/placement/BiomeTagModifier.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/world/placement/CobblemonPlacementTypes.kt
#	common/src/main/resources/assets/cobblemon/textures/gui/interact/move_select.png
#	common/src/main/resources/assets/cobblemon/textures/gui/summary/icon_shiny.png
#	common/src/main/resources/cobblemon-common.accesswidener
#	fabric/src/main/kotlin/com/cobblemon/mod/fabric/CobblemonFabric.kt
#	fabric/src/main/kotlin/com/cobblemon/mod/fabric/client/CobblemonFabricClient.kt
#	fabric/src/main/kotlin/com/cobblemon/mod/fabric/net/CobblemonNetworkFabric.kt
#	forge/src/main/kotlin/com/cobblemon/mod/forge/CobblemonForge.kt
#	forge/src/main/kotlin/com/cobblemon/mod/forge/client/CobblemonForgeClient.kt
#	forge/src/main/kotlin/com/cobblemon/mod/forge/net/CobblemonNetworkForge.kt
#	gradle/libs.versions.yml
2023-02-22 11:37:37 +10:00
Paul 9a2cfe040c Kdoc correction 2023-02-20 13:00:55 +10:00
Paul 47194659fa Various 1.19.3 fixes and packet errors 2023-02-20 12:57:38 +10:00
Nick 1cdc5aa3c7 Pull in correct fabric loader, fixes fabric 1.19.3 debug launch 2023-02-19 17:59:40 -08:00
Paul 413dafd681 Fix Forge decoding of packets not knowing the actual packet identifier 2023-02-20 10:49:13 +10:00
Licious17 1759249a89 Fix processResources task on forge 2023-02-15 17:10:13 +00:00
Licious17 6e83f9f7be Licenses 2023-02-15 13:37:39 +00:00
Licious17 50ac79281a Finished Forge implementation. 2023-02-15 13:37:15 +00:00
Licious17 4b9071d183 Finished all platform abstract stuff, finished Fabric implementation. 2023-02-15 11:54:16 +00:00
Licious17 76a04a0df9 Remove ArgumentTypesMixin and implement platform specific registration 2023-02-12 22:32:56 +00:00
Licious17 e2506f95a6 Implement worldgen feature registration 2023-02-12 21:03:53 +00:00
Licious17 f3ad759c25 Implement worldgen feature registration 2023-02-12 15:43:39 +00:00
Licious17 0785ce1c71 Implement sound event registration, add stripped block functionality to apricorn logs 2023-02-12 15:25:14 +00:00
Licious17 805fe12600 Implement block entity registration 2023-02-12 13:29:37 +00:00
Licious17 26182bdf10 Remove leftover code 2023-02-12 13:07:46 +00:00
Licious17 14d71200ec Implemented Entity types registration. 2023-02-12 13:07:18 +00:00
Licious17 150e6685ef Implemented item and block registration, fixed Forge mods.toml requiring 1.19.2 instead of 1.19.3 2023-02-11 23:31:02 +00:00
Paul 4faf75a763 Merge remote-tracking branch 'origin/main' into spawn-event 2023-02-07 23:35:13 +10:00
Paul ada2cb77c3 I really do always forget the license 2023-02-07 22:46:24 +10:00
Paul 50acc65b64 Added spawn event and check spawn condition for Pokemon, allowing Magnum Torch (fabric) to work 2023-02-07 22:05:06 +10:00
Paul 59efce5e55 License update 2023-02-05 22:23:14 +10:00
Paul 0ec23d65b3 Fixed blits being all black because of the wrong shader program being used 2023-02-05 22:08:03 +10:00
Paul 849ab32c5d Fixed party overlay not rendering 2023-02-05 21:55:59 +10:00
Licious17 f710c5ceb5 Fixed cobblemon:apricorn_trees placed feature JSON 2023-02-02 19:55:13 +00:00
Licious17 fe81edca50 Fixed cobblemon:apricorn_trees configured feature JSON 2023-02-02 19:32:07 +00:00
Licious17 650303de58 Port Quaternion#fromEulerXyzDegrees functionality 2023-02-02 19:03:22 +00:00
Licious17 c76c577b91 Update Pokemon label rendering 2023-02-02 16:46:18 +00:00
Licious17 eb95595af0 Fix implementations trying to access changed texture directories 2023-02-02 16:36:31 +00:00
Licious17 137d082e1a Update UI assets to match Minecraft standards 2023-02-02 16:30:03 +00:00
Licious17 ceb9fd0cf6 Fix item and block texture rendering 2023-02-02 16:15:23 +00:00
Licious17 fce087979a Added all features, game boots 2023-02-02 15:57:22 +00:00
Licious17 939ce328b9 Update item creative tabs 2023-02-01 23:41:31 +00:00
Licious17 d86366a04a Add in evolution ore feature JSON, update internal access 2023-02-01 23:22:06 +00:00
Licious17 7234dc0788 Merge branch 'main' into 1.19.3
# Conflicts:
#	common/src/main/kotlin/com/cobblemon/mod/common/CobblemonBlocks.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/world/feature/ApricornTreeFeature.kt
2023-02-01 22:21:40 +00:00
Paul 9a4ed01c7a Started the 1.19.3 port, TODO: itemgroups, placed features 2023-01-16 18:09:16 +10:00
4249 changed files with 188815 additions and 28201 deletions
+27 -6
View File
@@ -7,12 +7,14 @@ stages:
#TODO add client reference test process, search for import com.cobblemon.mod.common.client
build-job:
build:
stage: build
only:
- branches@cable-mc/cobblemon
script:
- export GRADLE_OPTS="-Xmx4G -Xms4G"
- chmod +x ./gradlew
- ./gradlew build
- export GRADLE_OPTS="-Xmx4G -Xms4G"
- chmod +x ./gradlew
- ./gradlew build
cache:
key: "$CI_COMMIT_REF_NAME"
policy: push
@@ -20,9 +22,28 @@ build-job:
- forge/build/libs
- fabric/build/libs
# Separate step to deploy the artifacts, save Norry the headache of keeping even more shit around
deploy-job:
publish:
stage: deploy
dependencies:
- build
cache:
key: "CI_COMMIT_REF_NAME"
policy: pull
paths:
- forge/build/libs/*.jar
- fabric/build/libs/*.jar
rules:
- if: '$CI_COMMIT_BRANCH == "main"'
script:
- export GRADLE_OPTS="-Xmx4G -Xms4G"
- chmod +x ./gradlew
- ./gradlew publish
# Separate step to deploy the artifacts, save Norry the headache of keeping even more shit around
deploy:
stage: deploy
dependencies:
- build
when: manual
cache:
key: "$CI_COMMIT_REF_NAME"
+258 -5
View File
@@ -1,4 +1,253 @@
# Changelog
## [1.4.0](#1-4-0)
### Additions
- Added nicknaming.
- Added mints, found on mountains.
- Added revival herbs, with pep-up flowers if fully grown, growing in lush caves.
- Added medicinal leeks, growing on the surface of rivers and ponds. It is a potion ingredient!
- Added big roots, generating from cave ceiling dirt and sometimes spreading into energy roots.
- Added trading between players. Press R while looking at another player, you'll figure it out.
- Added pasture blocks, used to let your PC Pokémon roam around your base.
- Added support for scale in animations.
- Added support for jump keyframes (i.e. pre and post keyframes)
- Made Nosepass point towards world spawn while idle.
- Added structure spawn conditions
- Added Pokémon cry system for battles and sending out.
- Added cries for Gen 1-9 starters and their evolutions.
- Added cries for Chatot, Darmanitan, Darumaka, Lucario, Mimikyu, Quagsire, Riolu, Wooper, Caterpie, Metapod, Butterfree, Weedle, Kakuna, Beedrill, Pidgey, Pidgeotto, Pidgeot, Rattata, Raticate, Cleffa, Clefairy, Clefable, Tauros, Miltank, Buneary, Lopunny, Wooloo, Dubwool.
- Added recipes for Berry Juice, Heal Powder, Remedy, Fine Remedy, Superb Remedy, Revive, Max Revive, HP Up, Protein, Iron, Calcium, Zinc, Carbos, PP Up, PP Max, Pasture, Medicinal Leek to Magenta Dye, Roasted Leek, Leek and Potato Stew, Braised Vivichoke, Vivichoke Dip, Mulch Base, Growth Mulch, Surprise Mulch, Coarse Mulch, Humid Mulch, Rich Mulch, Loamy Mulch, Peat Mulch, Sandy Mulch, Health Feather, Muscle Feather, Resist Feather, Genius Feather, Clever Feather, Genius Feather
- Added a shoulder mount for Mimikyu
- Added Advancement trigger for defeating Pokémon and collecting varieties of Pokémon.
- Added sleep animations to Arcanine, Jigglypuff, Wigglytuff, Vulpix and Ninetales.
- Added flying placeholder animations to Pidgey, Pidgeotto, Pidgeot, Golbat, Crobat, Scyther, Scizor, Zapdos, Moltres, Articuno, Dragonite, Rowlet, Dartrix, and Decidueye.
- Added loot to various vanilla chest loot tables (Link Cable in Ancient Cities, Woodland Mansions, End Cities, and Igloos, Vivichoke Seeds in Jungle Temples, Dungeons, and Plains, Savanna, Snowy, and Taiga Villages, and all 7 Apricorn Sprouts in Desert, Plains, Savanna, Snowy, and Taiga Villages, as well as the Bonus Chest)
- Added the `/teststore <player> <store> <properties>` command allowing command block/mcfunction users to query a party, PC or both for Pokémon matching specific properties and returning the match count, this will be a cheat command in the Minecraft permission system or use the permission `cobblemon.command.teststore` if a permission mod is present.
- Added the `/querylearnset <player> <slot> <move>` command allowing command block/mcfunction users to query a party slot and check if the Pokémon can learn a specific move returning a 1 if yes otherwise 0, this will be a cheat command in the Minecraft permission system or use the permission `cobblemon.command.querylearnset` if a permission mod is present.
- Added the `/testpcslot <player> <slot> <properties>` command allowing command block/mcfunction users to query a pc slot and check if the Pokémon matches specific properties returning a 1 if yes otherwise 0, this will be a cheat command in the Minecraft permission system or use the permission `cobblemon.command.testpcslot` if a permission mod is present.
- Added the `/testpartyslot <player> <slot> <properties>` command allowing command block/mcfunction users to query a party slot and check if the Pokémon matches a specific properties returning a 1 if yes otherwise 0, this will be a cheat command in the Minecraft permission system or use the permission `cobblemon.command.testpartyslot` if a permission mod is present.
- Added the `/clearparty <player>` command for emptying a player's party.
- Added the `/pokemonrestart <reset_starters>` and the `/pokemonrestartother <player> <reset_starters>` command allowing command block/mcfunction users to reset a players Pokémon data.
- Added support for "isBattle" and "isTouchingWater" properties on resource pack Pokémon poses. This allows your custom Pokémon to be posed differently when in battle.
- Added support for "isVisible" on a transformed part on resource pack Pokémon poses. This allows your custom Pokémon to have bones disappear in specific poses, such as hiding Greninja's throwing star when not in a battle pose.
- Added the `doPokemonLoot` gamerule to toggle Pokémon dropping items/exp on death.
### Pokémon Added
#### Gen 2
- Spinarak
- Ariados
- Shuckle
- Chinchou
- Lanturn
- Aipom
- Gligar
- Hoothoot
- Noctowl
- Mareep
- Flaaffy
- Ampharos
- Sudowoodo
#### Gen 3
- Taillow
- Swellow
- Relicanth
- Duskull
- Dusclops
- Shroomish
- Breloom
- Cacnea
- Cacturne
- Poochyena
- Mightyenna
- Wingull
- Pelipper
- Numel
- Camerupt
- Clamperl
- Huntail
- Gorebyss
- Surskit
- Masquerain
- Chimecho
- Barboach
- Whiscash
#### Gen 4
- Cherubi (Planned)
- Cherrim (Planned)
- Carnivine
- Shinx
- Luxio
- Luxray
- Ambipom
- Gliscor
- Dusknoir
- Chingling
- Bonsly
- Chatot
- Combee
- Vespiquen
#### Gen 5
- Bouffolant
- Roggenrola
- Boldore
- Gigalith
- Venepede
- Whirlpede
- Scolipede
- Yamask (Planned)
- Cofagrigus (Planned)
- Patrat (Planned)
- Watchog (Planned)
- Lillipup
- Herdier
- Stoutland
#### Gen 6
- Scatterbug
- Spewpa
- Vivillion
- Skrelp (Planned)
- Dragalge (Planned)
- Bunnelby (Planned)
- Diggersby (Planned)
#### Gen 7
- Wishiwashi (Planned)
- Cutiefly
- Ribombee
- Stufful
- Bewear
- Comfey
- Alolan Exeggutor
#### Gen 8
- Arrokuda (Planned)
- Barraskewda (Planned)
- Nickit
- Thievul
- Falinks
- Galarian Farfetch'd
- Sirfetch'd
- Rookidee
- Corvisquire
- Corviknight
#### Gen 9
- Sprigatitto
- Floragato
- Meowscarada
- Flittle
- Espathra
- Garganacl
- Fidough
- Dachsbun
- Armarouge
- Ceruledge
- Cetoddle
- Cetitan
- Shroodle (Planned)
- Grafaiai (Planned)
- Tandemaus
- Maushold
- Varoom
- Revavroom
- Squawkabilly (Planned)
- Glimmet
- Glimmora
### Changes
- Updated model and textures of Arcanine, Magnemite, Magneton, Magnezone, Exeggcute, Exeggutor, Farfetchd, Elekid, Electabuzz, Electivire, Pichu, Pikachu, Raichu, Gengar, Wooper Drowzee, Hypno, Aerodactyl, Spearow, Fearow, Lickitung, Pidgeotto, Pidgeot, Scyther, Scizor, Kleavor, Popplio, Brionne, Primarina, Torchic, Combusken, Blaziken, Aerodacyl, Scyther, Scizor, Kleavor, Lickitung, Lickilicky, Happiny, Chansey, Pidgey, Pidgeotto, Pidgeot, Spearow, Fearow, Drowzee, Hypno, Arcanine, Magnemite, Magneton, Magnezone, Exeggcute, Exeggutor, Farfetchd, Elekid, Electabuzz, Electivire, Pichu, Pikachu, Raichu, and Gengar.
- Updated models of Sceptile and Shuckle.
- Updated sprites for EV medicines, the rare candy, and the apricorn door item.
- Updated textures for apricorn doors and all the evolution stone ores.
- Updated Apricorn Leaves color.
- Wild Pokémon now heal if you are defeated by them or flee from them.
- Doubled the default time between ambient Pokémon cries (they have cries if you're using a resource pack to add them)
- Moved spawn attempts per tick to a config option (ticksBetweenSpawnAttempts)
- PCs can now be waterlogged
- Starter selection prompt now appears as a tutorial-esque toast instead of plain text
- Cobblemon items can now all have their own tooltips via resourcepacks, to add a tooltip simply add a lang entry like "item.cobblemon.{item_id}.tooltip", if you want to add multiple tooltip lines you can do so with "item.cobblemon.{item_id}.tooltip_1" and upwards.
- Updated texture of Weedle.
- Updated shiny texture of Dwebble and Crustle.
- Updated Animations for Piplup, Prinplup, Empoleon, Drowzee, Hypno, Farfetch'd, Exeggcute, Exeggutor, Bidoof, Chimecho, Lickytung, Lickilicky, Popplio, Brionne, Luvdisc, Chimchar, Monferno, Infernape, Sobble, Drizzile, Inteleon, Greninja, Heatmor, Aerodactyl, Ditto, Lotad, Lombre, Ludicolo, Pumpkaboo, Gourgeist.
- Reorganised the advancements recipes folder
- Pokeedit command now supports IVs and EVs.
- Reorganised creative categories
- Pokemon can now wander into non-solid blocks such as foliage
- Pokeballs now despawn after 30 seconds
- Dive Balls will now have the same motion speed underwater as if they were thrown in the air.
- Hardcoded potion shoulder effects have been removed, you can now use any potion vanilla or otherwise with the parameters you'd like, for more information see the [Datapack & Resourcepack Creators](#datapack-&-resourcepack-creators) section.
- Clicking categories of the Stat sub-section or the party reorder button in the Summary screen will now produce a click sound.
- Updated PC Recipe.
- Improved Pokémon AI and movement.
- Friendship will slowly increase when Pokémon are shoulder-mounted.
### Fixes
- Fixed spawning moon phase dependent Pokémon only when the moon phase is wrong
- Fixed large Pokémon spawning partially inside walls where they suffocate.
- Fixed messages for entry hazards, screens, Tailwind, Perish Song, Destiny Bond, Shed Skin, Uproar, Forewarn, Disguise, Arena Trap, Yawn, Curse, Clamp, Whirlpool, Liquid Ooze, Miracle Eye and Safeguard.
- Fixed Porygon not evolving with an Upgrade.
- Fixed super sized Pumpkaboo not having any moves.
- Fixed Infernape look animation.
- Fixed Garchomp t-posing while swimming.
- Fixed a bug that caused sleeping Pokémon to stay asleep.
- Fixed a bug that would freeze a battle when a Pokémon gets trapped due to an ability.
- Fixed the Poké Ball close animation canceling whenever colliding with a block.
- Fixed faint animations not working properly in add-ons.
- Fixed lighting and Pokémon label issues when a Pokémon item frame is nearby.
- Fixed Pokémon being able to spawn outside the world border as a tease.
- Fixed deepslate water stone ore items looking like deepslate fire stone ores.
- Fixed a bunch of client-side logging errors when Pokémon are shoulder mounted.
- Fixed a crash when wild Pokémon have to struggle under specific circumstances.
- Fixed uncolored pixels on Yanma's shiny texture.
- Fixed apricorn tree leaves looking gross on Fast graphics mode.
- Fixed hoes not breaking apricorn tree leaves any faster.
- Fixed Shiftry's PC model position.
- Fixed the /pc command not playing the opening sound.
- Fixed Shedinja not being able to recover naturally.
- Fixed different forms of Pokémon not being able to appear as different sizes.
- Fixed the Healing Machine soft locking you from using others when removed by non-players.
- Fixed animations being sped up when using the Replay Mod.
- Fixed particle animations not running when a Pokémon is off-screen.
- Fixed Pokémon variants and layers not rendering correctly when shouldered and playing on a dedicated server, existing shoulders affected will need to be retrieved and shouldered again.
- Shoulder effects will now stay applied through situations that remove potion effects such as drinking milk.
- Fixed Shedninja evolving to use the consumed Pokeball and removed the held item.
- Fixed non-existent species in spawn pool file causing random species to spawn.
- Fixed shearing Pokémon dropping 0-2 wool instead of 1-3.
- Fixed some alignment issues in the stat hexagon of the summary menu.
### Developer
- Added SpawnEvent
- Added persistent NBT property inside Pokemon to store quick and simple data.
- Species and FormData have had their evolutions, pre-evolution and labels properties exposed. It is still recommended to work using a Pokémon instance when possible.
- Added capture check to BattleVictoryEvent
- Added ThownPokeballHitEvent
- The various hardcoded potion shoulder effects have been removed, make use of PotionBaseEffect.
### Datapack & Resourcepack Creators
- All potion related shoulder effects have had their IDs changed, they now all share the same type being `potion_effect` and use the vanilla Potion data [parameters](https://minecraft.fandom.com/wiki/Potion#Item_data), take for example the default Pidgey asset:
- ```json
{
"type": "potion_effect",
"effect": "minecraft:slow_falling",
"amplifier": 0,
"ambient": true,
"showParticles": false,
"showIcon": false
}
```
## [1.3.1 (March 31st, 2023)](#1-3-1)
### Additions
@@ -33,6 +282,8 @@
- Made Weavile a little bigger.
- Changed the recipes for Mystic Water, Miracle Seed, and Charcoal Stick to utilise the evolution stones, as well as Never-Melt Ice having an alternate recipe using the Ice Stone.
- Replaced the `Failed to handle` battle messages to `Missing interpretation` to make it more clear that mechanics do work just still pending dedicated messages.
- Healing Machine and PC are now mine-able with pickaxes and Apricorn leaves are mine-able using hoes.
- Updated Pokéball, UI and evolution sounds.
### Fixes
- Fixed killing a Dodrio killing your game. Dodrio will never look the same to us.
@@ -47,7 +298,7 @@
- Fixed console spam when rendering Pokémon model items.
- Fixed battle messages for 50+ moves and abilities and items.
- Fixed the possible duplicate when capturing Pokémon (probably, this one's hard to reproduce to confirm it's fixed).
- Previously duplicated Pokémon are cleaned from PCs and parties on restart.
- Previously duplicated Pokémon are cleaned from PCs and parties on restart.
- Fixed an issue with some particle effects applying after a Pokémon has died or on top of the wrong Pokémon when using specific mods.
- Fixed Pokémon not looking at each other in battle.
- Fixed Experience Candy and Experience Share attempting to bring Pokémon above level cap causing crashes.
@@ -83,6 +334,8 @@
- Fixed instantly fleeing from Pokémon set to be unfleeable.
- Fixed Pumpkaboo line forms not working. (Currently sizes aren't visual but check base stats to see which size you have.)
- Fixed a bug that caused already interpreted messages for moves to be mistaken as uninterpreted.
- Fixed a Pokémon spawner bug that caused Pokémon to not spawn due to dropped item entities.
- Fixed a bug that causes Pokémon model items to be invisible.
### Developer
- Add events that are fired just before and after a Pokémon is released (ReleasePokemonEvent.Pre and .Post)
@@ -151,7 +404,7 @@
- ``generation_9`` Sets the calculator to the generation 9 implementation.
- ``cobblemon`` Sets the calculator to the custom Cobblemon implementation. This is the default value.
- ``debug`` Sets the calculator to the debug/cheat implementation, every attempt will be a successful critical capture.
### Changes
- Pokémon now save to the world by default, meaning the same Pokémon will remain in the world and not disappear after you log out and log back in. They still despawn over time though.
- Significantly sped up the Poké Ball shake animation so it takes less time to try to catch Pokémon.
@@ -228,7 +481,7 @@
- Fixed ambient sound file path for Porygon2.
- Fixed forms not being able to unset the secondary type of a Pokémon in the stat JSON.
- Fixed moves that haven't carried over from generation 8 onwards having the description they did in the generation 8 games instead of their last valid one.
- Fixed shoulder mounted pokemon not returning to party on healer use and on evolution
- Fixed shoulder mounted pokemon not returning to party on healer use and on evolution
### Developer
- Reworked CatchRateModifier, as such, existing implementations need to be updated.
@@ -240,7 +493,7 @@
### Localization
- Added complete translations for French, German, Simplified Mandarin, Brazilian Portuguese, and Pirate English.
- Added partial translations for Traditional Mandarin, Italian, and Spanish. We'd love more help with this!
- Thank you to all of the fantastic volunteer translators for taking the time to help with this!
- Thank you to all of the fantastic volunteer translators for taking the time to help with this!
## [1.2.0 - The Customization Update (January 1st, 2023)](#1-2-0)
### Additions
@@ -278,7 +531,7 @@
- Fixed stat calculations for everything except HP. HP was fine though :).
- Fixed a randomized Pokémon spawning in mountains that corrupted the data of whatever party or PC it got into. Yikes.
- Fixed a rare crash involving literally random number generation. A random crash involving random numbers.
- Fixed all regular Mewtwo having the stats and types of Mega Mewtwo X - same deal with many other Pokémon.
- Fixed all regular Mewtwo having the stats and types of Mega Mewtwo X - same deal with many other Pokémon.
- Fixed the framing of many Pokémon in GUIs.
- Fixed texture glitches with Rattata and Nidoqueen (again!).
- Fixed dropped item forms of all Pokéballs and the Healing Machine, and slightly adjusted all other display settings
+9 -8
View File
@@ -4,14 +4,15 @@ An open-source Pokémon mod for Minecraft Java Edition, written in Kotlin for Fa
## Getting started
To set up the development workspace, first clone the project and open the build.gradle with Intellij. There will be
errors until you go to File -> Settings -> Build, Execution, Deployment -> Build Tools -> Gradle and change the Gradle JVM
to 17. After changing this, click the icon for reloading the project. This will automatically
put together all the dependencies and project setup.
To set up the development workspace, first clone the project and open the build.gradle with Intellij. Make sure that you clone it to a folder that has no spaces in its path (for example, C:/Development/Cobblemon Stuff/cobblemon/ is bad) since Architectury Plugin seems to dislike it.
Run `./gradlew genEclipseRuns`, and then in Intellij go to your run configurations, and change whichever you plan on
running to use a Java 17 JRE. runClient is as if you booted up in singleplayer, runServer is a server without a client,
and runData is for summoning the Eldritch gods or something, idk.
After it takes ages to load, you should hopefully have runnable configurations of the project in the top right, such as Minecraft Client (:fabric). If not, try running `./gradlew genEclipseRuns`.
Troubleshooting:
- Try running `./gradlew --refresh-dependencies`
- Try File -> Invalidate Caches.
- Try deleting the `.idea` folder in the project root (make sure IntelliJ is closed when you try it).
- Try completely reclone the thing lmao.
## Contributing
@@ -19,4 +20,4 @@ If you're interested in contributing to the project, you can simply fork the rep
[here](https://gitlab.com/cable-mc/cobblemon/-/issues?scope=all&state=opened&label_name[]=accepted&assignee_id=None).
If you want a more involved role in the project, involving branches on the main repository instead of forking and involvement
in design discussions, add and message Hiroku#4373 on our Discord here: https://discord.gg/AsNpJSST7G.
in design discussions, you can either apply in the `application-box` forum of our Discord or add and message Hiroku (`hiroku_dev`) on our Discord here: https://discord.gg/cobblemon.
@@ -3,6 +3,7 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
val accessWidenerFile = "src/main/resources/cobblemon-common.accesswidener"
plugins {
java
`java-library`
id("org.cadixdev.licenser")
id("dev.architectury.loom")
@@ -38,7 +39,7 @@ loom {
dependencies {
minecraft("net.minecraft:minecraft:${rootProject.property("mc_version")}")
mappings("net.fabricmc:yarn:${rootProject.property("yarn_version")}")
mappings("net.fabricmc:yarn:${rootProject.property("yarn_version")}:v2")
}
tasks {
@@ -15,8 +15,8 @@ publishing {
maven("https://maven.impactdev.net/repository/development/") {
name = "ImpactDev-Public"
credentials {
username = System.getenv("NEXUS_USER")
password = System.getenv("NEXUS_PW")
username = System.getenv("COBBLEMON_MAVEN_USER")
password = System.getenv("COBBLEMON_MAVEN_PASSWORD")
}
}
}
+6 -4
View File
@@ -4,7 +4,7 @@ plugins {
}
architectury {
common()
common("forge", "fabric")
}
repositories {
@@ -17,7 +17,6 @@ dependencies {
implementation(libs.reflect)
modImplementation(libs.fabricLoader)
modApi(libs.architectury)
modApi(libs.molang)
// For Showdown
@@ -31,10 +30,13 @@ dependencies {
testImplementation(libs.junitParams)
testImplementation(libs.mockito)
testImplementation(libs.mockk)
compileOnly("net.luckperms:api:${rootProject.property("luckperms_version")}")
testImplementation(libs.classgraph)
}
tasks.withType<Test> {
useJUnitPlatform()
testLogging {
setEvents(listOf("failed"))
setExceptionFormat("full")
}
}
@@ -0,0 +1,15 @@
/*
* 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.access;
import net.minecraft.sound.SoundCategory;
public interface SoundManagerDuck {
void toggleCategories(SoundCategory... categories);
}
@@ -0,0 +1,71 @@
/*
* 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.models.blockbench.pose;
import net.minecraft.client.render.VertexConsumer;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.entity.Entity;
import org.jetbrains.annotations.Nullable;
import java.util.Map;
/**
* A bone represents a particular joint of a model. Bones are capable of containing child bones identifiable
* by a String ideally representing the name of a particular bone.
*
* This interface is meant to allow projects and sidemods to implement their own rendering logic in reference
* to the bones.
*
* @author Waterpicker
* @since 1.4.0
*/
public interface Bone {
/**
* A map of identifiable names to child bones
*
* @since 1.4.0
*/
Map<String, Bone> getChildren();
/**
* Renders a particular bone in relation to a particular entity.
*
* @param entity The entity this bone is being drawn for. This parameter need not be available and can be null
* @param stack The current [MatrixStack] for the renderer
* @param buffer The vertex consumer deployed by the renderer
* @param packedLight The light level to be applied to the bone
* @param packedOverlay The overlay value to be applied to the bone
* @param r A value representing the amount of red coloring that should be applied on the RGB scale
* @param g A value representing the amount of green coloring that should be applied on the RGB scale
* @param b A value representing the amount of blue coloring that should be applied on the RGB scale
* @param a The alpha value to apply to the model based on the RGB scale
*
* @since 1.4.0
*/
<T extends Entity> void render(
@Nullable T entity,
MatrixStack stack,
VertexConsumer buffer,
int packedLight,
int packedOverlay,
float r,
float g,
float b,
float a
);
/**
* Allows for direct transformation of a bone via a given matrix stack
*
* @since 1.4.0
*/
void transform(MatrixStack matrixStack);
}
@@ -1,40 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.mixin;
import com.cobblemon.mod.common.command.argument.*;
import com.mojang.brigadier.arguments.ArgumentType;
import net.minecraft.command.argument.ArgumentTypes;
import net.minecraft.command.argument.serialize.ArgumentSerializer;
import net.minecraft.command.argument.serialize.ConstantArgumentSerializer;
import net.minecraft.util.registry.Registry;
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.CallbackInfoReturnable;
@Mixin(ArgumentTypes.class)
public class ArgumentTypesMixin {
@Shadow
private static <A extends ArgumentType<?>, T extends ArgumentSerializer.ArgumentTypeProperties<A>> ArgumentSerializer<A, T> register(Registry<ArgumentSerializer<?, ?>> registry, String string, Class<? extends A> clazz, ArgumentSerializer<A, T> argumentSerializer) {
throw new AssertionError("Should not be executed.");
}
@Inject(method = "register(Lnet/minecraft/util/registry/Registry;)Lnet/minecraft/command/argument/serialize/ArgumentSerializer;", at = @At("RETURN"))
private static void register(Registry<ArgumentSerializer<?, ?>> registry, CallbackInfoReturnable<ArgumentSerializer<?, ?>> ci) {
register(registry, "cobblemon:pokemon", PokemonArgumentType.class, ConstantArgumentSerializer.of(PokemonArgumentType.Companion::pokemon));
register(registry, "cobblemon:pokemonproperties", PokemonPropertiesArgumentType.class, ConstantArgumentSerializer.of(PokemonPropertiesArgumentType.Companion::properties));
register(registry, "cobblemon:spawnbucket", SpawnBucketArgumentType.class, ConstantArgumentSerializer.of(SpawnBucketArgumentType.Companion::spawnBucket));
register(registry, "cobblemon:move", MoveArgumentType.class, ConstantArgumentSerializer.of(MoveArgumentType.Companion::move));
register(registry, "cobblemon:partyslot", PartySlotArgumentType.class, ConstantArgumentSerializer.of(PartySlotArgumentType.Companion::partySlot));
}
}
@@ -13,6 +13,7 @@ import com.cobblemon.mod.common.client.render.item.CobblemonBuiltinItemRendererR
import net.minecraft.client.render.VertexConsumerProvider;
import net.minecraft.client.render.item.BuiltinModelItemRenderer;
import net.minecraft.client.render.model.json.ModelTransformation;
import net.minecraft.client.render.model.json.ModelTransformationMode;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.item.ItemStack;
import org.spongepowered.asm.mixin.Mixin;
@@ -24,7 +25,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
public class BuiltinModelItemRendererMixin {
@Inject(method = "render", at = @At("HEAD"), cancellable = true)
private void cobblemon$useDynamicItemRenderer(ItemStack stack, ModelTransformation.Mode mode, MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light, int overlay, CallbackInfo ci) {
private void cobblemon$useDynamicItemRenderer(ItemStack stack, ModelTransformationMode mode, MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light, int overlay, CallbackInfo ci) {
CobblemonBuiltinItemRenderer renderer = CobblemonBuiltinItemRendererRegistry.INSTANCE.rendererOf(stack.getItem());
if (renderer != null) {
renderer.render(stack, mode, matrices, vertexConsumers, light, overlay);
@@ -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.mixin;
import com.cobblemon.mod.common.CobblemonBlocks;
import com.cobblemon.mod.common.block.PastureBlock;
import net.minecraft.block.BlockState;
import net.minecraft.block.FenceBlock;
import net.minecraft.block.HorizontalFacingBlock;
import net.minecraft.util.math.Direction;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
@Mixin(value = FenceBlock.class)
public abstract class FenceBlockMixin {
// This could be done with a modify variable but it just doesn't seem to want to work, very crude unfinished explanation I had on Fabric discord was
// "boolean is a primitive, it isnt passed by reference but by value and you have your own object references anyway so assigning a new object to non-primitive references (variables) wont modify it after your mixin returns
//(you cant modify a random argument that mixin passes you that way, target the boolean not the FenceBlock)"
// However the issue is the only way to get all the params which we need is by passing in the entire method reference which enforces the return type.
@Redirect(method = "getStateForNeighborUpdate", at = @At(value = "INVOKE", target = "Lnet/minecraft/block/FenceBlock;canConnect(Lnet/minecraft/block/BlockState;ZLnet/minecraft/util/math/Direction;)Z"))
private boolean cobblemon$getStateForNeighborUpdate(FenceBlock instance, BlockState state, boolean neighborIsFullSquare, Direction dir) {
return instance.canConnect(state, neighborIsFullSquare, dir) || this.cobblemon$canConnect(state, dir);
}
@Redirect(method = "getPlacementState", at = @At(value = "INVOKE", target = "Lnet/minecraft/block/FenceBlock;canConnect(Lnet/minecraft/block/BlockState;ZLnet/minecraft/util/math/Direction;)Z"))
private boolean cobblemon$getPlacementState(FenceBlock instance, BlockState state, boolean neighborIsFullSquare, Direction dir) {
return instance.canConnect(state, neighborIsFullSquare, dir) || this.cobblemon$canConnect(state, dir);
}
private boolean cobblemon$canConnect(BlockState state, Direction dir) {
if (state.isOf(CobblemonBlocks.PASTURE) && state.get(PastureBlock.Companion.getPART()) == PastureBlock.PasturePart.BOTTOM) {
final Direction pastureFacing = state.get(HorizontalFacingBlock.FACING);
return dir == pastureFacing.rotateYClockwise() || dir == pastureFacing.rotateYCounterclockwise();
}
return false;
}
}
@@ -0,0 +1,31 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.mixin;
import com.cobblemon.mod.common.api.pokemon.effect.ShoulderEffectRegistry;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.effect.StatusEffectInstance;
import net.minecraft.server.network.ServerPlayerEntity;
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(LivingEntity.class)
public abstract class LivingEntityMixin {
@Inject(method = "onStatusEffectRemoved", at = @At(value = "TAIL"))
private void cobblemon$onStatusEffectRemoved(StatusEffectInstance effect, CallbackInfo ci) {
final LivingEntity entity = (LivingEntity) (Object) this;
if (entity instanceof ServerPlayerEntity) {
ShoulderEffectRegistry.INSTANCE.onEffectEnd((ServerPlayerEntity) entity);
}
}
}
@@ -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.mixin;
import com.cobblemon.mod.common.client.render.models.blockbench.pose.Bone;
import net.minecraft.client.model.ModelPart;
import net.minecraft.client.render.VertexConsumer;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.entity.Entity;
import org.jetbrains.annotations.NotNull;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import java.util.Map;
@Mixin(ModelPart.class)
public abstract class ModelPartMixin implements Bone {
@Shadow public abstract void render(MatrixStack matrices, VertexConsumer vertices, int light, int overlay, float red, float green, float blue, float alpha);
@Shadow public abstract void rotate(MatrixStack matrixStack);
@Shadow @Final
public Map<String, ModelPart> children;
@NotNull
@Override
public Map<String, Bone> getChildren() {
return (Map<String, Bone>) (Object) children;
}
@Override
public <T extends Entity> void render(T entity, MatrixStack stack, VertexConsumer buffer, int packedLight, int packedOverlay, float r, float g, float b, float a) {
this.render(stack, buffer, packedLight, packedOverlay, r, g, b, a);
}
@Override
public void transform(MatrixStack matrixStack) {
this.rotate(matrixStack);
}
}
@@ -145,7 +145,7 @@ public abstract class PlayerMixin extends LivingEntity {
public void onEatFood(World world, ItemStack stack, CallbackInfoReturnable<ItemStack> cir) {
if (!getWorld().isClient) {
if (stack.getItem() == Items.APPLE && getWorld().random.nextDouble() < Cobblemon.config.getAppleLeftoversChance()) {
ItemStack leftovers = new ItemStack(CobblemonItems.LEFTOVERS.get());
ItemStack leftovers = new ItemStack(CobblemonItems.LEFTOVERS);
ServerPlayerEntity player = Objects.requireNonNull(getServer()).getPlayerManager().getPlayer(uuid);
assert player != null;
CobblemonEvents.LEFTOVERS_CREATED.postThen(
@@ -0,0 +1,31 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.mixin;
import com.cobblemon.mod.common.brewing.BrewingRecipes;
import net.minecraft.item.ItemStack;
import net.minecraft.screen.BrewingStandScreenHandler;
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(BrewingStandScreenHandler.PotionSlot.class)
public class PotionSlotMixin {
@Inject(
method = "matches",
at = @At(value = "HEAD"),
cancellable = true
)
private static void matchesBrewable(ItemStack stack, CallbackInfoReturnable<Boolean> cir) {
if (BrewingRecipes.brewableItems.contains(stack.getItem())) {
cir.setReturnValue(true);
}
}
}
@@ -18,7 +18,6 @@ import net.minecraft.world.chunk.ChunkManager;
import net.minecraft.world.chunk.ChunkStatus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
@@ -8,14 +8,12 @@
package com.cobblemon.mod.common.mixin;
import com.cobblemon.mod.common.block.ApricornBlock;
import com.cobblemon.mod.common.block.ShearableBlock;
import kotlin.Unit;
import net.minecraft.block.BlockState;
import net.minecraft.block.dispenser.ShearsDispenserBehavior;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.sound.SoundCategory;
import net.minecraft.sound.SoundEvents;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.event.GameEvent;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
@@ -24,15 +22,12 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(ShearsDispenserBehavior.class)
public abstract class ShearsDispenserBehaviorMixin {
// This exists so we can execute our custom interaction only if no one redirected shears interactions to overwrite the vanilla ones.
// This exists, so we can execute our custom interaction only if no one redirected shears interactions to overwrite the vanilla ones.
@Inject(method = "tryShearBlock", at = @At("HEAD"), cancellable = true)
private static void cobblemon$tryApricornHarvest(ServerWorld world, BlockPos pos, CallbackInfoReturnable<Boolean> cir) {
final BlockState state = world.getBlockState(pos);
if (state.getBlock() instanceof ApricornBlock apricornBlock && state.get(ApricornBlock.Companion.getAGE()) == ApricornBlock.MAX_AGE) {
world.playSound(null, pos, SoundEvents.ENTITY_SHEEP_SHEAR, SoundCategory.BLOCKS, 1F, 1F);
apricornBlock.harvest(world, state, pos);
world.emitGameEvent(null, GameEvent.SHEAR, pos);
cir.setReturnValue(true);
if (state.getBlock() instanceof ShearableBlock shearableBlock) {
cir.setReturnValue(shearableBlock.attemptShear(world, state, pos, () -> Unit.INSTANCE));
}
}
@@ -0,0 +1,43 @@
/*
* 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.access.SoundManagerDuck;
import net.minecraft.client.sound.SoundInstance;
import net.minecraft.client.sound.SoundManager;
import net.minecraft.sound.SoundCategory;
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(SoundManager.class)
public class SoundManagerMixin implements SoundManagerDuck {
private boolean[] blockedCategories = new boolean[SoundCategory.values().length];
@Override
public void toggleCategories(SoundCategory... categories) {
for (SoundCategory category : categories) {
int index = category.ordinal();
boolean blocked = blockedCategories[index];
blockedCategories[index] = !blocked;
}
}
@Inject(method = "play(Lnet/minecraft/client/sound/SoundInstance;)V", at = @At("HEAD"), cancellable = true)
public void play(SoundInstance sound, CallbackInfo cb) {
if (blockedCategories[sound.getCategory().ordinal()]) cb.cancel();
}
@Inject(method = "play(Lnet/minecraft/client/sound/SoundInstance;I)V", at = @At("HEAD"), cancellable = true)
public void play(SoundInstance sound, int delay, CallbackInfo cb) {
if (blockedCategories[sound.getCategory().ordinal()]) cb.cancel();
}
}
@@ -0,0 +1,39 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.mixin;
import com.google.common.collect.Multimap;
import net.minecraft.client.sound.SoundInstance;
import net.minecraft.client.sound.SoundSystem;
import net.minecraft.sound.SoundCategory;
import net.minecraft.util.Identifier;
import org.jetbrains.annotations.Nullable;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(SoundSystem.class)
public abstract class SoundSystemMixin {
@Shadow
private Multimap<SoundCategory, SoundInstance> sounds;
@Shadow
protected abstract void stop(SoundInstance sound);
@Inject(method = "stopSounds(Lnet/minecraft/util/Identifier;Lnet/minecraft/sound/SoundCategory;)V", at = @At("HEAD"), cancellable = true)
public void stopSounds(@Nullable Identifier id, @Nullable SoundCategory category, CallbackInfo cb) {
if (id == null && category != null) {
sounds.get(category).forEach(this::stop);
cb.cancel();
}
}
}
@@ -0,0 +1,22 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.mixin.accessor;
import net.minecraft.client.sound.MusicTracker;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
@Mixin(MusicTracker.class)
public interface MusicTrackerAccessor {
@Accessor("timeUntilNextSong")
int timeUntilNextSong();
@Accessor("timeUntilNextSong")
void setTimeUntilNextSong(int timeUntilNextSong);
}
@@ -0,0 +1,26 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.mixin.accessor;
import net.minecraft.entity.effect.StatusEffectInstance;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
@Mixin(StatusEffectInstance.class)
public interface StatusEffectInstanceAccessor {
@Accessor
void setAmplifier(int amplifier);
@Accessor
void setShowParticles(boolean showParticles);
@Accessor
void setShowIcon(boolean showIcon);
}
@@ -0,0 +1,41 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.mixin.invoker;
import net.minecraft.block.*;
import net.minecraft.resource.featuretoggle.FeatureFlag;
import net.minecraft.sound.BlockSoundGroup;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Invoker;
@SuppressWarnings("unused")
@Mixin(Blocks.class)
public interface BlocksInvoker {
@Invoker("createLogBlock")
static PillarBlock createLogBlock(MapColor topMapColor, MapColor sideMapColor) {
throw new UnsupportedOperationException();
}
@Invoker("createLeavesBlock")
static LeavesBlock createLeavesBlock(BlockSoundGroup soundGroup) {
throw new UnsupportedOperationException();
}
@Invoker("createWoodenButtonBlock")
static ButtonBlock createWoodenButtonBlock(BlockSetType blockSetType, FeatureFlag... requiredFeatures) {
throw new UnsupportedOperationException();
}
@Invoker("createFlowerPotBlock")
static FlowerPotBlock createFlowerPotBlock(Block flower, FeatureFlag... requiredFeatures) {
throw new UnsupportedOperationException();
}
}
@@ -0,0 +1,21 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.mixin.invoker;
import net.minecraft.world.GameRules;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Invoker;
@Mixin(GameRules.BooleanRule.class)
public interface BooleanRuleInvoker {
@Invoker("create")
static GameRules.Type<GameRules.BooleanRule> cobblemon$create(boolean initialValue) {
throw new UnsupportedOperationException();
}
}
@@ -0,0 +1,20 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.mixin.invoker;
import net.minecraft.client.network.ClientPlayNetworkHandler;
import net.minecraft.entity.Entity;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Invoker;
@Mixin(ClientPlayNetworkHandler.class)
public interface ClientPlayNetworkHandlerInvoker {
@Invoker
void callPlaySpawnSound(Entity entity);
}
@@ -0,0 +1,24 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.mixin.invoker;
import net.minecraft.block.AbstractBlock;
import net.minecraft.block.BlockSetType;
import net.minecraft.block.DoorBlock;
import net.minecraft.sound.SoundEvent;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Invoker;
@Mixin(DoorBlock.class)
public interface DoorBlockInvoker {
@Invoker("<init>")
static DoorBlock cobblemon$create(AbstractBlock.Settings settings, BlockSetType blockSetType) {
throw new UnsupportedOperationException();
}
}
@@ -0,0 +1,24 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.mixin.invoker;
import net.minecraft.block.AbstractBlock;
import net.minecraft.block.BlockSetType;
import net.minecraft.block.PressurePlateBlock;
import net.minecraft.sound.SoundEvent;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Invoker;
@Mixin(PressurePlateBlock.class)
public interface PressurePlateBlockInvoker {
@Invoker("<init>")
static PressurePlateBlock cobblemon$create(PressurePlateBlock.ActivationRule type, AbstractBlock.Settings settings, BlockSetType blockSetType) {
throw new UnsupportedOperationException();
}
}
@@ -0,0 +1,23 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.mixin.invoker;
import net.minecraft.block.AbstractBlock;
import net.minecraft.block.BlockState;
import net.minecraft.block.StairsBlock;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Invoker;
@Mixin(StairsBlock.class)
public interface StairsBlockInvoker {
@Invoker("<init>")
static StairsBlock cobblemon$create(BlockState baseBlockState, AbstractBlock.Settings settings) {
throw new UnsupportedOperationException();
}
}
@@ -0,0 +1,24 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.mixin.invoker;
import net.minecraft.block.AbstractBlock;
import net.minecraft.block.BlockSetType;
import net.minecraft.block.TrapdoorBlock;
import net.minecraft.sound.SoundEvent;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Invoker;
@Mixin(TrapdoorBlock.class)
public interface TrapdoorBlockInvoker {
@Invoker("<init>")
static TrapdoorBlock cobblemon$create(AbstractBlock.Settings settings, BlockSetType blockSetType) {
throw new UnsupportedOperationException();
}
}
@@ -14,6 +14,7 @@ import net.minecraft.client.render.item.ItemModels;
import net.minecraft.client.render.item.ItemRenderer;
import net.minecraft.client.render.model.BakedModel;
import net.minecraft.client.render.model.json.ModelTransformation;
import net.minecraft.client.render.model.json.ModelTransformationMode;
import net.minecraft.client.util.ModelIdentifier;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.client.world.ClientWorld;
@@ -33,13 +34,12 @@ public abstract class ItemRendererMixin {
@Shadow @Final private ItemModels models;
@Shadow public abstract void renderItem(ItemStack stack, ModelTransformation.Mode renderMode, boolean leftHanded, MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light, int overlay, BakedModel model);
@Shadow public abstract void renderItem(ItemStack stack, ModelTransformationMode renderMode, boolean leftHanded, MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light, int overlay, BakedModel model);
@Inject(method = "getModel", at = @At("HEAD"), cancellable = true)
private void cobblemon$bakePokeballModel(ItemStack stack, World world, LivingEntity entity, int seed, CallbackInfoReturnable<BakedModel> cir) {
if (stack.getItem() instanceof PokeBallItem pokeBallItem) {
ModelIdentifier modelIdentifier = new ModelIdentifier(pokeBallItem.getPokeBall().getModel3d());
BakedModel model = this.models.getModelManager().getModel(modelIdentifier);
BakedModel model = this.models.getModelManager().getModel(new ModelIdentifier(pokeBallItem.getPokeBall().getModel3d(), "inventory"));
ClientWorld clientWorld = world instanceof ClientWorld ? (ClientWorld) world : null;
BakedModel overriddenModel = model.getOverrides().apply(model, stack, clientWorld, entity, seed);
cir.setReturnValue(overriddenModel == null ? this.models.getModelManager().getMissingModel() : overriddenModel);
@@ -47,15 +47,14 @@ public abstract class ItemRendererMixin {
}
@Inject(
method = "renderItem(Lnet/minecraft/item/ItemStack;Lnet/minecraft/client/render/model/json/ModelTransformation$Mode;ZLnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumerProvider;IILnet/minecraft/client/render/model/BakedModel;)V",
method = "renderItem(Lnet/minecraft/item/ItemStack;Lnet/minecraft/client/render/model/json/ModelTransformationMode;ZLnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumerProvider;IILnet/minecraft/client/render/model/BakedModel;)V",
at = @At("HEAD"),
cancellable = true
)
private void cobblemon$determinePokeballModel(ItemStack stack, ModelTransformation.Mode renderMode, boolean leftHanded, MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light, int overlay, BakedModel model, CallbackInfo ci) {
boolean shouldBe2d = renderMode == ModelTransformation.Mode.GUI || renderMode == ModelTransformation.Mode.FIXED;
private void cobblemon$determinePokeballModel(ItemStack stack, ModelTransformationMode renderMode, boolean leftHanded, MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light, int overlay, BakedModel model, CallbackInfo ci) {
boolean shouldBe2d = renderMode == ModelTransformationMode.GUI || renderMode == ModelTransformationMode.FIXED;
if (shouldBe2d && stack.getItem() instanceof PokeBallItem pokeBallItem) {
ModelIdentifier modelIdentifier = new ModelIdentifier(pokeBallItem.getPokeBall().getModel2d());
BakedModel replacementModel = this.models.getModelManager().getModel(modelIdentifier);
BakedModel replacementModel = this.models.getModelManager().getModel(new ModelIdentifier(pokeBallItem.getPokeBall().getModel2d(), "inventory"));
if (!model.equals(replacementModel)) {
ci.cancel();
renderItem(stack, renderMode, leftHanded, matrices, vertexConsumers, light, overlay, replacementModel);
@@ -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.mixin.pokeball;
import com.cobblemon.mod.common.entity.pokeball.WaterDragModifier;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.projectile.thrown.ThrownEntity;
import net.minecraft.world.World;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.ModifyVariable;
@Mixin(ThrownEntity.class)
public abstract class ThrownEntityMixin extends Entity {
public ThrownEntityMixin(EntityType<?> type, World world) {
super(type, world);
}
@ModifyVariable(method = "tick", at = @At("STORE"), ordinal = 0)
private float cobblemon$waterDragModifier(float value) {
if (this.isTouchingWater() && this instanceof WaterDragModifier) {
return ((WaterDragModifier) this).waterDrag();
}
return value;
}
}
@@ -18,12 +18,7 @@ import com.cobblemon.mod.common.api.drop.ItemDropEntry
import com.cobblemon.mod.common.api.events.CobblemonEvents.BATTLE_VICTORY
import com.cobblemon.mod.common.api.events.CobblemonEvents.DATA_SYNCHRONIZED
import com.cobblemon.mod.common.api.events.CobblemonEvents.EVOLUTION_COMPLETE
import com.cobblemon.mod.common.api.events.CobblemonEvents.LIVING_DEATH
import com.cobblemon.mod.common.api.events.CobblemonEvents.PLAYER_QUIT
import com.cobblemon.mod.common.api.events.CobblemonEvents.POKEMON_CAPTURED
import com.cobblemon.mod.common.api.events.CobblemonEvents.SERVER_STARTED
import com.cobblemon.mod.common.api.events.CobblemonEvents.SERVER_STOPPED
import com.cobblemon.mod.common.api.events.CobblemonEvents.TICK_POST
import com.cobblemon.mod.common.api.net.serializers.PoseTypeDataSerializer
import com.cobblemon.mod.common.api.net.serializers.StringSetDataSerializer
import com.cobblemon.mod.common.api.net.serializers.Vec3DataSerializer
@@ -43,8 +38,6 @@ import com.cobblemon.mod.common.api.pokemon.stats.EvCalculator
import com.cobblemon.mod.common.api.pokemon.stats.Generation8EvCalculator
import com.cobblemon.mod.common.api.pokemon.stats.StatProvider
import com.cobblemon.mod.common.api.properties.CustomPokemonProperty
import com.cobblemon.mod.common.api.reactive.Observable.Companion.filter
import com.cobblemon.mod.common.api.reactive.Observable.Companion.map
import com.cobblemon.mod.common.api.scheduling.ScheduledTaskTracker
import com.cobblemon.mod.common.api.spawning.BestSpawner
import com.cobblemon.mod.common.api.spawning.CobblemonSpawningProspector
@@ -61,13 +54,19 @@ import com.cobblemon.mod.common.api.storage.pc.PCStore
import com.cobblemon.mod.common.api.storage.pc.link.PCLinkManager
import com.cobblemon.mod.common.api.storage.player.PlayerDataStoreManager
import com.cobblemon.mod.common.api.tags.CobblemonEntityTypeTags
import com.cobblemon.mod.common.battles.BagItems
import com.cobblemon.mod.common.battles.BattleFormat
import com.cobblemon.mod.common.battles.BattleRegistry
import com.cobblemon.mod.common.battles.BattleSide
import com.cobblemon.mod.common.battles.ShowdownThread
import com.cobblemon.mod.common.battles.actor.PokemonBattleActor
import com.cobblemon.mod.common.battles.pokemon.BattlePokemon
import com.cobblemon.mod.common.battles.runner.ShowdownService
import com.cobblemon.mod.common.command.argument.MoveArgumentType
import com.cobblemon.mod.common.command.argument.PartySlotArgumentType
import com.cobblemon.mod.common.command.argument.PokemonArgumentType
import com.cobblemon.mod.common.command.argument.PokemonPropertiesArgumentType
import com.cobblemon.mod.common.command.argument.PokemonStoreArgumentType
import com.cobblemon.mod.common.command.argument.SpawnBucketArgumentType
import com.cobblemon.mod.common.config.CobblemonConfig
import com.cobblemon.mod.common.config.LastChangedVersion
import com.cobblemon.mod.common.config.constraint.IntConstraint
@@ -77,37 +76,31 @@ import com.cobblemon.mod.common.events.AdvancementHandler
import com.cobblemon.mod.common.events.ServerTickHandler
import com.cobblemon.mod.common.item.PokeBallItem
import com.cobblemon.mod.common.net.messages.client.settings.ServerSettingsPacket
import com.cobblemon.mod.common.net.serverhandling.ServerPacketRegistrar
import com.cobblemon.mod.common.particle.CobblemonParticles
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.GENDER_ASPECT
import com.cobblemon.mod.common.pokemon.aspects.SHINY_ASPECT
import com.cobblemon.mod.common.pokemon.evolution.variants.BlockClickEvolution
import com.cobblemon.mod.common.pokemon.feature.*
import com.cobblemon.mod.common.pokemon.feature.TagSeasonResolver
import com.cobblemon.mod.common.pokemon.helditem.CobblemonHeldItemManager
import com.cobblemon.mod.common.pokemon.properties.HiddenAbilityPropertyType
import com.cobblemon.mod.common.pokemon.properties.UncatchableProperty
import com.cobblemon.mod.common.pokemon.properties.UntradeableProperty
import com.cobblemon.mod.common.pokemon.properties.tags.PokemonFlagProperty
import com.cobblemon.mod.common.pokemon.stat.CobblemonStatProvider
import com.cobblemon.mod.common.registry.CompletableRegistry
import com.cobblemon.mod.common.starter.CobblemonStarterHandler
import com.cobblemon.mod.common.trade.TradeManager
import com.cobblemon.mod.common.util.DataKeys
import com.cobblemon.mod.common.util.cobblemonResource
import com.cobblemon.mod.common.util.getServer
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.removeAmountIf
import com.cobblemon.mod.common.util.server
import com.cobblemon.mod.common.world.feature.CobblemonPlacedFeatures
import com.cobblemon.mod.common.world.feature.ore.CobblemonOrePlacedFeatures
import com.cobblemon.mod.common.world.gamerules.CobblemonGameRules
import com.cobblemon.mod.common.world.feature.CobblemonOrePlacedFeatures
import com.cobblemon.mod.common.world.placement.CobblemonPlacementTypes
import dev.architectury.event.EventResult
import dev.architectury.event.events.common.CommandRegistrationEvent
import dev.architectury.event.events.common.InteractionEvent
import dev.architectury.event.events.common.PlayerEvent
import dev.architectury.hooks.item.tool.AxeItemHooks
import java.io.File
import java.io.FileReader
import java.io.FileWriter
@@ -118,17 +111,18 @@ import kotlin.reflect.full.memberProperties
import kotlin.reflect.jvm.isAccessible
import kotlin.reflect.jvm.javaField
import net.minecraft.client.MinecraftClient
import net.minecraft.command.argument.serialize.ConstantArgumentSerializer
import net.minecraft.entity.data.TrackedDataHandlerRegistry
import net.minecraft.item.Items
import net.minecraft.item.NameTagItem
import net.minecraft.server.network.ServerPlayerEntity
import net.minecraft.registry.RegistryKey
import net.minecraft.util.WorldSavePath
import net.minecraft.util.registry.RegistryKey
import net.minecraft.world.World
import org.apache.logging.log4j.LogManager
object Cobblemon {
const val MODID = "cobblemon"
const val VERSION = "1.3.1"
const val VERSION = "1.4.0"
const val CONFIG_PATH = "config/$MODID/main.json"
val LOGGER = LogManager.getLogger()
@@ -158,6 +152,17 @@ object Cobblemon {
var seasonResolver: SeasonResolver = TagSeasonResolver
fun preInitialize(implementation: CobblemonImplementation) {
this.implementation = implementation
implementation.registerPermissionValidator()
implementation.registerSoundEvents()
implementation.registerBlocks()
implementation.registerItems()
implementation.registerEntityTypes()
implementation.registerEntityAttributes()
implementation.registerBlockEntityTypes()
implementation.registerWorldGenFeatures()
implementation.registerParticles()
DropEntry.register("command", CommandDropEntry::class.java)
DropEntry.register("item", ItemDropEntry::class.java, isDefault = true)
@@ -165,18 +170,13 @@ object Cobblemon {
CaptureCalculators.registerDefaults()
this.loadConfig()
this.implementation = implementation
// CobblemonBlockPredicates.touch()
CobblemonOrePlacedFeatures.register()
CobblemonPlacedFeatures.register()
this.registerArgumentTypes()
CobblemonCriteria // Init the fields and register the criteria
CobblemonEntities.register()
CobblemonBlocks.register()
CobblemonBlockEntities.register()
CobblemonItems.register()
ServerPacketRegistrar.registerHandlers()
CobblemonSounds.register()
CobblemonFeatures.register()
CobblemonGameRules.register()
CobblemonParticles.register()
CobblemonGameRules // Init fields and register
ShoulderEffectRegistry.register()
@@ -184,26 +184,28 @@ object Cobblemon {
storage.onPlayerDataSync(it)
playerData.get(it).sendToPlayer(it)
starterHandler.handleJoin(it)
ServerSettingsPacket().sendToPlayer(it)
ServerSettingsPacket(this.config.preventCompletePartyDeposit, this.config.displayEntityLevelLabel).sendToPlayer(it)
}
PLAYER_QUIT.subscribe {
PCLinkManager.removeLink(it.uuid)
BattleRegistry.getBattleByParticipatingPlayer(it)?.stop()
PlatformEvents.SERVER_PLAYER_LOGOUT.subscribe {
PCLinkManager.removeLink(it.player.uuid)
BattleRegistry.getBattleByParticipatingPlayer(it.player)?.stop()
storage.onPlayerDisconnect(it.player)
playerData.onPlayerDisconnect(it.player)
TradeManager.onLogoff(it.player)
}
LIVING_DEATH.pipe(filter { it is ServerPlayerEntity }, map { it as ServerPlayerEntity }).subscribe {
PCLinkManager.removeLink(it.uuid)
battleRegistry.getBattleByParticipatingPlayer(it)?.stop()
PlatformEvents.PLAYER_DEATH.subscribe {
PCLinkManager.removeLink(it.player.uuid)
battleRegistry.getBattleByParticipatingPlayer(it.player)?.stop()
}
InteractionEvent.INTERACT_ENTITY.register(InteractionEvent.InteractEntity { player, entity, hand ->
if (player.getStackInHand(hand).item is NameTagItem && entity.type.isIn(CobblemonEntityTypeTags.CANNOT_HAVE_NAME_TAG))
EventResult.interruptTrue()
else
EventResult.pass()
})
InteractionEvent.RIGHT_CLICK_BLOCK.register(InteractionEvent.RightClickBlock { pl, _, pos, _ ->
val player = pl as? ServerPlayerEntity ?: return@RightClickBlock EventResult.pass()
val block = player.world.getBlockState(pos).block
PlatformEvents.RIGHT_CLICK_ENTITY.subscribe { event ->
if (event.player.getStackInHand(event.hand).item is NameTagItem && event.entity.type.isIn(CobblemonEntityTypeTags.CANNOT_HAVE_NAME_TAG)) {
event.cancel()
}
}
PlatformEvents.RIGHT_CLICK_BLOCK.subscribe { event ->
val player = event.player
val block = player.world.getBlockState(event.pos).block
player.party().forEach { pokemon ->
pokemon.evolutions
.filterIsInstance<BlockClickEvolution>()
@@ -211,12 +213,11 @@ object Cobblemon {
evolution.attemptEvolution(pokemon, BlockClickEvolution.BlockInteractionContext(block, player.world))
}
}
return@RightClickBlock EventResult.pass()
})
}
PlayerEvent.CHANGE_DIMENSION.register(PlayerEvent.ChangeDimension{ player, _, _ ->
player.party().forEach { pokemon -> pokemon.entity?.recallWithAnimation() }
})
PlatformEvents.CHANGE_DIMENSION.subscribe {
it.player.party().forEach { pokemon -> pokemon.entity?.recallWithAnimation() }
}
TrackedDataHandlerRegistry.register(Vec3DataSerializer)
TrackedDataHandlerRegistry.register(StringSetDataSerializer)
@@ -228,13 +229,6 @@ object Cobblemon {
fun initialize() {
showdownThread.launch()
CompletableRegistry.allRegistriesCompleted.thenAccept {
LOGGER.info("All registries loaded.")
}
CobblemonPlacementTypes.register()
CobblemonOrePlacedFeatures.register()
// Start up the data provider.
CobblemonDataProvider.registerDefaults()
@@ -256,23 +250,15 @@ object Cobblemon {
CustomPokemonProperty.register(PokemonFlagProperty)
CustomPokemonProperty.register(HiddenAbilityPropertyType)
CommandRegistrationEvent.EVENT.register(CobblemonCommands::register)
ifDedicatedServer {
isDedicatedServer = true
TICK_POST.subscribe { ScheduledTaskTracker.update() }
CobblemonNetwork.clientHandlersRegistered.complete(Unit)
PlatformEvents.SERVER_TICK_POST.subscribe { ScheduledTaskTracker.update() }
}
CobblemonBlocks.completed.thenAccept {
AxeItemHooks.addStrippable(CobblemonBlocks.APRICORN_LOG.get(), CobblemonBlocks.STRIPPED_APRICORN_LOG.get())
AxeItemHooks.addStrippable(CobblemonBlocks.APRICORN_WOOD.get(), CobblemonBlocks.STRIPPED_APRICORN_WOOD.get())
}
SERVER_STARTED.subscribe { server ->
PlatformEvents.SERVER_STARTING.subscribe { event ->
val server = event.server
playerData = PlayerDataStoreManager().also { it.setup(server) }
val pokemonStoreRoot = server.getSavePath(WorldSavePath.ROOT).resolve("pokemon").toFile()
storage.registerFactory(
priority = Priority.LOWEST,
factory = FileBackedPokemonStoreFactory(
@@ -287,15 +273,15 @@ object Cobblemon {
)
}
SERVER_STOPPED.subscribe {
PlatformEvents.SERVER_STOPPED.subscribe {
storage.unregisterAll()
playerData.saveAll()
}
SERVER_STARTED.subscribe {
PlatformEvents.SERVER_STARTED.subscribe {
bestSpawner.onServerStarted()
battleRegistry.onServerStarted()
}
TICK_POST.subscribe { ServerTickHandler.onTick(it) }
PlatformEvents.SERVER_TICK_POST.subscribe { ServerTickHandler.onTick(it.server) }
POKEMON_CAPTURED.subscribe { AdvancementHandler.onCapture(it) }
// EGG_HATCH.subscribe { AdvancementHandler.onHatch(it) }
BATTLE_VICTORY.subscribe { AdvancementHandler.onWinBattle(it) }
@@ -307,17 +293,27 @@ object Cobblemon {
if (this.config.ninjaskCreatesShedinja && pokemon.species.resourceIdentifier == ninjaskIdentifier && PokemonSpecies.getByIdentifier(Pokemon.SHEDINJA) != null) {
val player = pokemon.getOwnerPlayer() ?: return@subscribe
if (player.inventory.containsAny { it.item is PokeBallItem }) {
var pokeball = Items.AIR
player.inventory.combinedInventory.forEach {
it.forEach {
itemStack -> if (itemStack.item is PokeBallItem && pokeball == Items.AIR) {
pokeball = itemStack.item as PokeBallItem
}
}
}
player.inventory.removeAmountIf(1) { it.item is PokeBallItem }
val properties = event.evolution.result.copy()
properties.species = Pokemon.SHEDINJA.toString()
val product = pokemon.clone()
product.removeHeldItem()
properties.apply(product)
product.caughtBall = (pokeball as PokeBallItem).pokeBall
pokemon.storeCoordinates.get()?.store?.add(product)
}
}
}
PokemonSpecies.observable.subscribe {
BagItems.observable.subscribe {
LOGGER.info("Starting dummy Showdown battle to force it to pre-load data.")
battleRegistry.startBattle(
BattleFormat.GEN_9_SINGLES,
@@ -329,7 +325,7 @@ object Cobblemon {
fun getLevel(dimension: RegistryKey<World>): World? {
return if (isDedicatedServer) {
getServer()?.getWorld(dimension)
server()?.getWorld(dimension)
} else {
val mc = MinecraftClient.getInstance()
return mc.server?.getWorld(dimension) ?: mc.world
@@ -420,4 +416,14 @@ object Cobblemon {
exception.printStackTrace()
}
}
private fun registerArgumentTypes() {
this.implementation.registerCommandArgument(cobblemonResource("pokemon"), PokemonArgumentType::class, ConstantArgumentSerializer.of(PokemonArgumentType::pokemon))
this.implementation.registerCommandArgument(cobblemonResource("pokemon_properties"), PokemonPropertiesArgumentType::class, ConstantArgumentSerializer.of(PokemonPropertiesArgumentType::properties))
this.implementation.registerCommandArgument(cobblemonResource("spawn_bucket"), SpawnBucketArgumentType::class, ConstantArgumentSerializer.of(SpawnBucketArgumentType::spawnBucket))
this.implementation.registerCommandArgument(cobblemonResource("move"), MoveArgumentType::class, ConstantArgumentSerializer.of(MoveArgumentType::move))
this.implementation.registerCommandArgument(cobblemonResource("party_slot"), PartySlotArgumentType::class, ConstantArgumentSerializer.of(PartySlotArgumentType::partySlot))
this.implementation.registerCommandArgument(cobblemonResource("pokemon_store"), PokemonStoreArgumentType::class, ConstantArgumentSerializer.of(PokemonStoreArgumentType::pokemonStore))
}
}
@@ -8,31 +8,26 @@
package com.cobblemon.mod.common
import com.cobblemon.mod.common.registry.CompletableRegistry
import com.cobblemon.mod.common.block.entity.HealingMachineBlockEntity
import com.cobblemon.mod.common.block.entity.PCBlockEntity
import dev.architectury.registry.registries.RegistrySupplier
import java.util.function.Supplier
import com.cobblemon.mod.common.block.entity.PokemonPastureBlockEntity
import com.cobblemon.mod.common.platform.PlatformRegistry
import net.minecraft.block.entity.BlockEntityType
import net.minecraft.util.registry.Registry
import net.minecraft.registry.Registries
import net.minecraft.registry.Registry
import net.minecraft.registry.RegistryKey
import net.minecraft.registry.RegistryKeys
object CobblemonBlockEntities : CompletableRegistry<BlockEntityType<*>>(Registry.BLOCK_ENTITY_TYPE_KEY) {
private fun <T : BlockEntityType<*>> register(name: String, blockEntityType: Supplier<T>) : RegistrySupplier<T> {
return queue(name, blockEntityType)
}
object CobblemonBlockEntities : PlatformRegistry<Registry<BlockEntityType<*>>, RegistryKey<Registry<BlockEntityType<*>>>, BlockEntityType<*>>() {
override val registry: Registry<BlockEntityType<*>> = Registries.BLOCK_ENTITY_TYPE
override val registryKey: RegistryKey<Registry<BlockEntityType<*>>> = RegistryKeys.BLOCK_ENTITY_TYPE
@JvmField
val HEALING_MACHINE = com.cobblemon.mod.common.CobblemonBlockEntities.register("healing_machine") {
BlockEntityType.Builder.create(
::HealingMachineBlockEntity,
CobblemonBlocks.HEALING_MACHINE.get()
).build(null)
}
val HEALING_MACHINE: BlockEntityType<HealingMachineBlockEntity> = this.create("healing_machine", BlockEntityType.Builder.create(::HealingMachineBlockEntity, CobblemonBlocks.HEALING_MACHINE).build(null))
@JvmField
val PC = com.cobblemon.mod.common.CobblemonBlockEntities.register("pc") {
BlockEntityType.Builder.create(
::PCBlockEntity,
CobblemonBlocks.PC.get()
).build(null)
}
val PC: BlockEntityType<PCBlockEntity> = this.create("pc", BlockEntityType.Builder.create(::PCBlockEntity, CobblemonBlocks.PC).build(null))
@JvmField
val PASTURE: BlockEntityType<PokemonPastureBlockEntity> = this.create("pasture", BlockEntityType.Builder.create(::PokemonPastureBlockEntity, CobblemonBlocks.PASTURE).build(null))
}
@@ -9,50 +9,56 @@
package com.cobblemon.mod.common
import com.cobblemon.mod.common.api.apricorn.Apricorn
import com.cobblemon.mod.common.registry.CompletableRegistry
import com.cobblemon.mod.common.block.ApricornBlock
import com.cobblemon.mod.common.block.ApricornSaplingBlock
import com.cobblemon.mod.common.block.HealingMachineBlock
import com.cobblemon.mod.common.block.PCBlock
import dev.architectury.registry.registries.RegistrySupplier
import com.cobblemon.mod.common.block.*
import com.cobblemon.mod.common.block.MintBlock.MintType
import com.cobblemon.mod.common.mixin.invoker.DoorBlockInvoker
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.mixin.invoker.*
import com.cobblemon.mod.common.platform.PlatformRegistry
import net.minecraft.block.*
import net.minecraft.entity.EntityType
import net.minecraft.block.piston.PistonBehavior
import net.minecraft.entity.effect.StatusEffects
import net.minecraft.registry.Registries
import net.minecraft.registry.Registry
import net.minecraft.registry.RegistryKey
import net.minecraft.registry.RegistryKeys
import net.minecraft.sound.BlockSoundGroup
import net.minecraft.util.math.Direction
import net.minecraft.util.math.intprovider.UniformIntProvider
import net.minecraft.util.registry.Registry
import java.util.function.ToIntFunction
object CobblemonBlocks : CompletableRegistry<Block>(Registry.BLOCK_KEY) {
/**
* Evolution Ores
*/
@JvmField
val DAWN_STONE_ORE = this.evolutionStoneOre("dawn_stone_ore")
@JvmField
val DUSK_STONE_ORE = this.evolutionStoneOre("dusk_stone_ore")
@JvmField
val FIRE_STONE_ORE = this.evolutionStoneOre("fire_stone_ore")
@JvmField
val ICE_STONE_ORE = this.evolutionStoneOre("ice_stone_ore")
@JvmField
val LEAF_STONE_ORE = this.evolutionStoneOre("leaf_stone_ore")
@JvmField
val MOON_STONE_ORE = this.evolutionStoneOre("moon_stone_ore")
@JvmField
val DRIPSTONE_MOON_STONE_ORE = this.evolutionStoneOre("dripstone_moon_stone_ore")
@JvmField
val SHINY_STONE_ORE = this.evolutionStoneOre("shiny_stone_ore")
@JvmField
val SUN_STONE_ORE = this.evolutionStoneOre("sun_stone_ore")
@JvmField
val THUNDER_STONE_ORE = this.evolutionStoneOre("thunder_stone_ore")
@JvmField
val WATER_STONE_ORE = this.evolutionStoneOre("water_stone_ore")
@Suppress("SameParameterValue", "HasPlatformType", "MemberVisibilityCanBePrivate", "unused")
object CobblemonBlocks : PlatformRegistry<Registry<Block>, RegistryKey<Registry<Block>>, Block>() {
/**
* Deepslate separator
*/
override val registry: Registry<Block> = Registries.BLOCK
override val registryKey: RegistryKey<Registry<Block>> = RegistryKeys.BLOCK
val APRICORN_BLOCK_SET_TYPE = BlockSetType("apricorn")
val APRICORN_WOOD_TYPE = WoodType.register(WoodType("apricorn", APRICORN_BLOCK_SET_TYPE))
// Evolution Ores
@JvmField
val DAWN_STONE_ORE = evolutionStoneOre("dawn_stone_ore")
@JvmField
val DUSK_STONE_ORE = evolutionStoneOre("dusk_stone_ore")
@JvmField
val FIRE_STONE_ORE = evolutionStoneOre("fire_stone_ore")
@JvmField
val ICE_STONE_ORE = evolutionStoneOre("ice_stone_ore")
@JvmField
val LEAF_STONE_ORE = evolutionStoneOre("leaf_stone_ore")
@JvmField
val MOON_STONE_ORE = evolutionStoneOre("moon_stone_ore")
@JvmField
val DRIPSTONE_MOON_STONE_ORE = evolutionStoneOre("dripstone_moon_stone_ore")
@JvmField
val SHINY_STONE_ORE = evolutionStoneOre("shiny_stone_ore")
@JvmField
val SUN_STONE_ORE = evolutionStoneOre("sun_stone_ore")
@JvmField
val THUNDER_STONE_ORE = evolutionStoneOre("thunder_stone_ore")
@JvmField
val WATER_STONE_ORE = evolutionStoneOre("water_stone_ore")
@JvmField
val DEEPSLATE_DAWN_STONE_ORE = this.deepslateEvolutionStoneOre("deepslate_dawn_stone_ore")
@@ -75,130 +81,171 @@ object CobblemonBlocks : CompletableRegistry<Block>(Registry.BLOCK_KEY) {
@JvmField
val DEEPSLATE_WATER_STONE_ORE = this.deepslateEvolutionStoneOre("deepslate_water_stone_ore")
/**
* Apricorns
*/
// Apricorns
@JvmField
val APRICORN_LOG = queue("apricorn_log") {
log(
MapColor.DIRT_BROWN,
MapColor.BROWN
)
}
val APRICORN_LOG = log("apricorn_log", arg2 = MapColor.BROWN)
@JvmField
val STRIPPED_APRICORN_LOG = queue("stripped_apricorn_log") {
log(
MapColor.DIRT_BROWN,
MapColor.DIRT_BROWN
)
}
val STRIPPED_APRICORN_LOG = log("stripped_apricorn_log")
@JvmField
val APRICORN_WOOD = queue("apricorn_wood") {
log(
MapColor.DIRT_BROWN,
MapColor.DIRT_BROWN
)
}
val APRICORN_WOOD = log("apricorn_wood")
@JvmField
val STRIPPED_APRICORN_WOOD = queue("stripped_apricorn_wood") {
log(
MapColor.DIRT_BROWN,
MapColor.DIRT_BROWN
)
}
val STRIPPED_APRICORN_WOOD = log("stripped_apricorn_wood")
@JvmField
val APRICORN_PLANKS = queue("apricorn_planks") { Block(AbstractBlock.Settings.of(Material.WOOD, MapColor.DIRT_BROWN).strength(2.0f, 3.0f).sounds(BlockSoundGroup.WOOD)) }
val APRICORN_PLANKS = this.create("apricorn_planks", Block(AbstractBlock.Settings.create().mapColor(MapColor.DIRT_BROWN).strength(2.0f, 3.0f).sounds(BlockSoundGroup.WOOD)))
@JvmField
val APRICORN_LEAVES = queue("apricorn_leaves") { com.cobblemon.mod.common.CobblemonBlocks.leaves(BlockSoundGroup.GRASS) }
val APRICORN_LEAVES = leaves("apricorn_leaves")
@JvmField
val APRICORN_FENCE = queue("apricorn_fence") { FenceBlock(AbstractBlock.Settings.of(Material.WOOD, APRICORN_PLANKS.get().defaultMapColor).strength(2.0f, 3.0f).sounds(BlockSoundGroup.WOOD)) }
val APRICORN_FENCE = this.create("apricorn_fence", FenceBlock(AbstractBlock.Settings.create().mapColor(APRICORN_PLANKS.defaultMapColor).strength(2.0f, 3.0f).sounds(BlockSoundGroup.WOOD)))
@JvmField
val APRICORN_FENCE_GATE = queue("apricorn_fence_gate") { FenceGateBlock(AbstractBlock.Settings.of(Material.WOOD, APRICORN_PLANKS.get().defaultMapColor).strength(2.0f, 3.0f).sounds(BlockSoundGroup.WOOD)) }
val APRICORN_FENCE_GATE = this.create("apricorn_fence_gate", FenceGateBlock(AbstractBlock.Settings.create().mapColor(APRICORN_PLANKS.defaultMapColor).strength(2.0f, 3.0f).sounds(BlockSoundGroup.WOOD), APRICORN_WOOD_TYPE))
@JvmField // Note At the time of 1.20.0 we don't need our own BlockSetType for Apricorn wood
val APRICORN_BUTTON = this.create("apricorn_button", BlocksInvoker.createWoodenButtonBlock(BlockSetType.OAK))
@JvmField
val APRICORN_BUTTON = queue("apricorn_button") { WoodenButtonBlock(AbstractBlock.Settings.of(Material.DECORATION).noCollision().strength(0.5f).sounds(BlockSoundGroup.WOOD)) }
@JvmField
val APRICORN_PRESSURE_PLATE = queue("apricorn_pressure_plate") { PressurePlateBlock(PressurePlateBlock.ActivationRule.EVERYTHING, AbstractBlock.Settings.of(Material.WOOD, APRICORN_PLANKS.get().defaultMapColor).noCollision().strength(0.5f).sounds(BlockSoundGroup.WOOD)) }
val APRICORN_PRESSURE_PLATE = this.create("apricorn_pressure_plate", PressurePlateBlockInvoker.`cobblemon$create`(PressurePlateBlock.ActivationRule.EVERYTHING, AbstractBlock.Settings.create().mapColor(APRICORN_PLANKS.defaultMapColor).noCollision().strength(0.5f).sounds(BlockSoundGroup.WOOD), APRICORN_BLOCK_SET_TYPE))
// Tag was removed be sure to add it back when implemented
// @JvmField
// val APRICORN_SIGN = queue("apricorn_sign") { StandingSignBlock(AbstractBlock.Settings.of(Material.WOOD).noCollission().strength(1.0f).sounds(BlockSoundGroup.WOOD), APRICORN_WOOD_TYPE) }
//@JvmField
// val APRICORN_WALL_SIGN = queue("apricorn_wall_sign") { WallSignBlock(AbstractBlock.Settings.of(Material.WOOD).noCollission().strength(1.0f).sounds(BlockSoundGroup.WOOD).dropsLike(APRICORN_SIGN), APRICORN_WOOD_TYPE) }
//val APRICORN_SIGN = queue("apricorn_sign") { StandingSignBlock(AbstractBlock.Settings.of(Material.WOOD).noCollission().strength(1.0f).sounds(BlockSoundGroup.WOOD), APRICORN_WOOD_TYPE) }
//val APRICORN_WALL_SIGN = queue("apricorn_wall_sign") { WallSignBlock(AbstractBlock.Settings.of(Material.WOOD).noCollission().strength(1.0f).sounds(BlockSoundGroup.WOOD).dropsLike(APRICORN_SIGN), APRICORN_WOOD_TYPE) }
@JvmField
val APRICORN_SLAB = queue("apricorn_slab") { SlabBlock(AbstractBlock.Settings.of(Material.WOOD, MapColor.OAK_TAN).strength(2.0f, 3.0f).sounds(BlockSoundGroup.WOOD)) }
val APRICORN_SLAB = this.create("apricorn_slab", SlabBlock(AbstractBlock.Settings.create().mapColor(MapColor.OAK_TAN).strength(2.0f, 3.0f).sounds(BlockSoundGroup.WOOD)))
@JvmField
val APRICORN_STAIRS = queue("apricorn_stairs") { StairsBlock(
APRICORN_PLANKS.get().defaultState, AbstractBlock.Settings.copy(
APRICORN_PLANKS.get())) }
val APRICORN_STAIRS = this.create("apricorn_stairs", StairsBlockInvoker.`cobblemon$create`(APRICORN_PLANKS.defaultState, AbstractBlock.Settings.copy(APRICORN_PLANKS)))
@JvmField
val APRICORN_DOOR = queue("apricorn_door") { DoorBlock(AbstractBlock.Settings.of(Material.WOOD, APRICORN_PLANKS.get().defaultMapColor).strength(3.0F).sounds(BlockSoundGroup.WOOD).nonOpaque()) }
val APRICORN_DOOR = this.create("apricorn_door", DoorBlockInvoker.`cobblemon$create`(AbstractBlock.Settings.create().mapColor(APRICORN_PLANKS.defaultMapColor).strength(3.0F).sounds(BlockSoundGroup.WOOD).nonOpaque(), APRICORN_BLOCK_SET_TYPE))
@JvmField
val APRICORN_TRAPDOOR = queue("apricorn_trapdoor") { TrapdoorBlock(AbstractBlock.Settings.of(Material.WOOD, MapColor.OAK_TAN).strength(3.0F).sounds(BlockSoundGroup.WOOD).nonOpaque().allowsSpawning { _, _, _, _ -> false }) }
val APRICORN_TRAPDOOR = this.create("apricorn_trapdoor", TrapdoorBlockInvoker.`cobblemon$create`(AbstractBlock.Settings.create().mapColor(MapColor.OAK_TAN).strength(3.0F).sounds(BlockSoundGroup.WOOD).nonOpaque().allowsSpawning { _, _, _, _ -> false }, APRICORN_BLOCK_SET_TYPE))
private val PLANT_PROPERTIES = AbstractBlock.Settings.of(Material.PLANT).noCollision().ticksRandomly().breakInstantly().sounds(BlockSoundGroup.GRASS)
private val PLANT_PROPERTIES = AbstractBlock.Settings.create().mapColor(MapColor.DARK_GREEN).noCollision().ticksRandomly().breakInstantly().sounds(BlockSoundGroup.GRASS).pistonBehavior(PistonBehavior.DESTROY)
@JvmField
val BLACK_APRICORN_SAPLING = queue("black_apricorn_sapling") { ApricornSaplingBlock(PLANT_PROPERTIES, Apricorn.BLACK) }
val BLACK_APRICORN_SAPLING = this.create("black_apricorn_sapling", ApricornSaplingBlock(PLANT_PROPERTIES, Apricorn.BLACK))
@JvmField
val BLUE_APRICORN_SAPLING = queue("blue_apricorn_sapling") { ApricornSaplingBlock(PLANT_PROPERTIES, Apricorn.BLUE) }
val BLUE_APRICORN_SAPLING = this.create("blue_apricorn_sapling", ApricornSaplingBlock(PLANT_PROPERTIES, Apricorn.BLUE))
@JvmField
val GREEN_APRICORN_SAPLING = queue("green_apricorn_sapling") { ApricornSaplingBlock(PLANT_PROPERTIES, Apricorn.GREEN) }
val GREEN_APRICORN_SAPLING = this.create("green_apricorn_sapling", ApricornSaplingBlock(PLANT_PROPERTIES, Apricorn.GREEN))
@JvmField
val PINK_APRICORN_SAPLING = queue("pink_apricorn_sapling") { ApricornSaplingBlock(PLANT_PROPERTIES, Apricorn.PINK) }
val PINK_APRICORN_SAPLING = this.create("pink_apricorn_sapling", ApricornSaplingBlock(PLANT_PROPERTIES, Apricorn.PINK))
@JvmField
val RED_APRICORN_SAPLING = queue("red_apricorn_sapling") { ApricornSaplingBlock(PLANT_PROPERTIES, Apricorn.RED) }
val RED_APRICORN_SAPLING = this.create("red_apricorn_sapling", ApricornSaplingBlock(PLANT_PROPERTIES, Apricorn.RED))
@JvmField
val WHITE_APRICORN_SAPLING = queue("white_apricorn_sapling") { ApricornSaplingBlock(PLANT_PROPERTIES, Apricorn.WHITE) }
val WHITE_APRICORN_SAPLING = this.create("white_apricorn_sapling", ApricornSaplingBlock(PLANT_PROPERTIES, Apricorn.WHITE))
@JvmField
val YELLOW_APRICORN_SAPLING = queue("yellow_apricorn_sapling") { ApricornSaplingBlock(PLANT_PROPERTIES, Apricorn.YELLOW) }
val YELLOW_APRICORN_SAPLING = this.create("yellow_apricorn_sapling", ApricornSaplingBlock(PLANT_PROPERTIES, Apricorn.YELLOW))
@JvmField
val BLACK_APRICORN = registerApricornBlock("black_apricorn", Apricorn.BLACK)
val MEDICINAL_LEEK = this.create("medicinal_leek", MedicinalLeekBlock(AbstractBlock.Settings.create().pistonBehavior(PistonBehavior.DESTROY).burnable().mapColor(MapColor.DULL_RED).noCollision().ticksRandomly().breakInstantly().sounds(BlockSoundGroup.CROP)))
@JvmField
val BLUE_APRICORN = registerApricornBlock("blue_apricorn", Apricorn.BLUE)
val ENERGY_ROOT = this.create("energy_root", EnergyRootBlock(AbstractBlock.Settings.create().pistonBehavior(PistonBehavior.DESTROY).burnable().mapColor(MapColor.DIRT_BROWN).noCollision().ticksRandomly().breakInstantly().sounds(BlockSoundGroup.ROOTS)))
@JvmField
val GREEN_APRICORN = registerApricornBlock("green_apricorn", Apricorn.GREEN)
val BIG_ROOT = this.create("big_root", BigRootBlock(AbstractBlock.Settings.create().pistonBehavior(PistonBehavior.DESTROY).burnable().mapColor(MapColor.DARK_GREEN).noCollision().ticksRandomly().breakInstantly().sounds(BlockSoundGroup.ROOTS)))
@JvmField
val PINK_APRICORN = registerApricornBlock("pink_apricorn", Apricorn.PINK)
@JvmField
val RED_APRICORN = registerApricornBlock("red_apricorn", Apricorn.RED)
@JvmField
val WHITE_APRICORN = registerApricornBlock("white_apricorn", Apricorn.WHITE)
@JvmField
val YELLOW_APRICORN = registerApricornBlock("yellow_apricorn", Apricorn.YELLOW)
val REVIVAL_HERB = this.create("revival_herb", RevivalHerbBlock(AbstractBlock.Settings.create().pistonBehavior(PistonBehavior.DESTROY).mapColor(MapColor.DARK_GREEN).burnable().noCollision().breakInstantly().sounds(BlockSoundGroup.CROP)))
@JvmField
val HEALING_MACHINE = queue("healing_machine") { HealingMachineBlock(AbstractBlock.Settings.of(Material.METAL, MapColor.IRON_GRAY).sounds(BlockSoundGroup.METAL).strength(2f).nonOpaque().luminance(ToIntFunction { state: BlockState -> if (state.get(HealingMachineBlock.CHARGE_LEVEL) >= HealingMachineBlock.MAX_CHARGE_LEVEL) 7 else 2 })) }
val BLACK_APRICORN = apricornBlock("black_apricorn", Apricorn.BLACK)
@JvmField
val PC = queue("pc") { PCBlock(AbstractBlock.Settings.of(Material.METAL, MapColor.IRON_GRAY).sounds(BlockSoundGroup.METAL).strength(2F).nonOpaque().luminance(ToIntFunction { state: BlockState -> if ((state.get(
PCBlock.ON) as Boolean) && (state.get(PCBlock.PART) == PCBlock.PCPart.TOP)) 10 else 0 })) }
val BLUE_APRICORN = apricornBlock("blue_apricorn", Apricorn.BLUE)
@JvmField
val GREEN_APRICORN = apricornBlock("green_apricorn", Apricorn.GREEN)
@JvmField
val PINK_APRICORN = apricornBlock("pink_apricorn", Apricorn.PINK)
@JvmField
val RED_APRICORN = apricornBlock("red_apricorn", Apricorn.RED)
@JvmField
val WHITE_APRICORN = apricornBlock("white_apricorn", Apricorn.WHITE)
@JvmField
val YELLOW_APRICORN = apricornBlock("yellow_apricorn", Apricorn.YELLOW)
private fun registerApricornBlock(id: String, apricorn: Apricorn): RegistrySupplier<ApricornBlock> {
return queue(id) { ApricornBlock(AbstractBlock.Settings.of(Material.PLANT, apricorn.mapColor()).ticksRandomly().strength(Blocks.OAK_LOG.hardness, Blocks.OAK_LOG.blastResistance).sounds(BlockSoundGroup.WOOD).nonOpaque(), apricorn) }
}
@JvmField
val HEALING_MACHINE = create(
"healing_machine",
HealingMachineBlock(
AbstractBlock.Settings.create()
.mapColor(MapColor.IRON_GRAY)
.sounds(BlockSoundGroup.METAL)
.pistonBehavior(PistonBehavior.BLOCK)
.strength(2f)
.nonOpaque()
.luminance { if (it.get(HealingMachineBlock.CHARGE_LEVEL) >= HealingMachineBlock.MAX_CHARGE_LEVEL) 7 else 2 }
)
)
@JvmField
val PC = create(
"pc",
PCBlock(
AbstractBlock.Settings.create()
.mapColor(MapColor.IRON_GRAY)
.sounds(BlockSoundGroup.METAL)
.pistonBehavior(PistonBehavior.BLOCK)
.strength(2F)
.nonOpaque()
.luminance { if ((it.get(PCBlock.ON) as Boolean) && (it.get(PCBlock.PART) == PCBlock.PCPart.TOP)) 10 else 0 }
)
)
@JvmField
val RED_MINT = create("red_mint", MintBlock(MintType.RED, AbstractBlock.Settings.create().mapColor(MapColor.RED).noCollision().ticksRandomly().breakInstantly().sounds(BlockSoundGroup.CROP)))
@JvmField
val BLUE_MINT = create("blue_mint", MintBlock(MintType.BLUE, AbstractBlock.Settings.create().mapColor(MapColor.BLUE).noCollision().ticksRandomly().breakInstantly().sounds(BlockSoundGroup.CROP)))
@JvmField
val CYAN_MINT = create("cyan_mint", MintBlock(MintType.CYAN, AbstractBlock.Settings.create().mapColor(MapColor.CYAN).noCollision().ticksRandomly().breakInstantly().sounds(BlockSoundGroup.CROP)))
@JvmField
val PINK_MINT = create("pink_mint", MintBlock(MintType.PINK, AbstractBlock.Settings.create().mapColor(MapColor.PINK).noCollision().ticksRandomly().breakInstantly().sounds(BlockSoundGroup.CROP)))
@JvmField
val GREEN_MINT = create("green_mint", MintBlock(MintType.GREEN, AbstractBlock.Settings.create().mapColor(MapColor.GREEN).noCollision().ticksRandomly().breakInstantly().sounds(BlockSoundGroup.CROP)))
@JvmField
val WHITE_MINT = create("white_mint", MintBlock(MintType.WHITE, AbstractBlock.Settings.create().mapColor(MapColor.WHITE).noCollision().ticksRandomly().breakInstantly().sounds(BlockSoundGroup.CROP)))
@JvmField
val PASTURE = create(
"pasture",
PastureBlock(
AbstractBlock.Settings.create()
.mapColor(MapColor.BROWN)
.sounds(BlockSoundGroup.WOOD)
.strength(2F)
.nonOpaque()
.pistonBehavior(PistonBehavior.BLOCK)
.luminance { if ((it.get(PastureBlock.ON) as Boolean) && (it.get(PastureBlock.PART) == PastureBlock.PasturePart.TOP)) 10 else 0 }
)
)
@JvmField
val VIVICHOKE_SEEDS = this.create("vivichoke_seeds", VivichokeBlock(AbstractBlock.Settings.create().pistonBehavior(PistonBehavior.DESTROY).burnable().mapColor(MapColor.DARK_GREEN).noCollision().ticksRandomly().breakInstantly().sounds(BlockSoundGroup.CROP)))
@JvmField
val PEP_UP_FLOWER = this.create("pep_up_flower", FlowerBlock(StatusEffects.LEVITATION, 10, AbstractBlock.Settings.create().mapColor(MapColor.DARK_GREEN).noCollision().breakInstantly().sounds(BlockSoundGroup.GRASS).offset(AbstractBlock.OffsetType.XZ).pistonBehavior(PistonBehavior.DESTROY)))
@JvmField
val POTTED_PEP_UP_FLOWER = this.create("potted_pep_up_flower", BlocksInvoker.createFlowerPotBlock(PEP_UP_FLOWER))
/**
* Returns a map of all the blocks that can be stripped with an axe in the format of input - output.
*
* @return A map of all the blocks that can be stripped with an axe in the format of input - output.
*/
fun strippedBlocks(): Map<Block, Block> = mapOf(
APRICORN_WOOD to STRIPPED_APRICORN_WOOD,
APRICORN_LOG to STRIPPED_APRICORN_LOG
)
private fun apricornBlock(name: String, apricorn: Apricorn): ApricornBlock = this.create(name, ApricornBlock(AbstractBlock.Settings.create().mapColor(apricorn.mapColor()).ticksRandomly().strength(Blocks.OAK_LOG.hardness, Blocks.OAK_LOG.blastResistance).sounds(BlockSoundGroup.WOOD).nonOpaque(), apricorn))
/**
* Helper method for creating logs
* copied over from Vanilla
*/
private fun log(arg: MapColor, arg2: MapColor): PillarBlock {
return PillarBlock(AbstractBlock.Settings.of(Material.WOOD) { arg3: BlockState ->
if (arg3.get(PillarBlock.AXIS) === Direction.Axis.Y) arg else arg2
}.strength(2.0f).sounds(BlockSoundGroup.WOOD))
private fun log(name: String, arg: MapColor = MapColor.DIRT_BROWN, arg2: MapColor = MapColor.DIRT_BROWN): PillarBlock {
val block = BlocksInvoker.createLogBlock(arg, arg2)
return this.create(name, block)
}
private fun evolutionStoneOre(name: String) = this.queue(name) { OreBlock(AbstractBlock.Settings.copy(Blocks.IRON_ORE), UniformIntProvider.create(1, 2)) }
private fun evolutionStoneOre(name: String) = this.create(name, ExperienceDroppingBlock(AbstractBlock.Settings.copy(Blocks.IRON_ORE), UniformIntProvider.create(1, 2)))
private fun deepslateEvolutionStoneOre(name: String) = this.queue(name) { OreBlock(AbstractBlock.Settings.copy(Blocks.DEEPSLATE_IRON_ORE), UniformIntProvider.create(1, 2)) }
private fun deepslateEvolutionStoneOre(name: String) = this.create(name, ExperienceDroppingBlock(AbstractBlock.Settings.copy(Blocks.DEEPSLATE_IRON_ORE), UniformIntProvider.create(1, 2)))
/**
* Helper method for creating leaves
* copied over from Vanilla
*/
private fun leaves(sound: BlockSoundGroup): LeavesBlock {
return LeavesBlock(
AbstractBlock.Settings.of(Material.LEAVES).strength(0.2f).ticksRandomly().sounds(sound).nonOpaque()
.allowsSpawning { _, _, _, type -> type === EntityType.OCELOT || type === EntityType.PARROT }
.suffocates { _, _, _ -> false }
.blockVision { _, _, _ -> false })
private fun leaves(name: String): LeavesBlock {
val block = BlocksInvoker.createLeavesBlock(BlockSoundGroup.GRASS)
return this.create(name, block)
}
}
@@ -9,12 +9,21 @@
package com.cobblemon.mod.common
import java.util.function.Supplier
import net.minecraft.block.Block
import net.minecraft.block.entity.BlockEntity
import net.minecraft.block.entity.BlockEntityType
import net.minecraft.client.color.block.BlockColorProvider
import net.minecraft.client.color.item.ItemColorProvider
import net.minecraft.client.model.TexturedModelData
import net.minecraft.client.particle.ParticleFactory
import net.minecraft.client.particle.SpriteProvider
import net.minecraft.client.render.RenderLayer
import net.minecraft.client.render.block.entity.BlockEntityRendererFactory
import net.minecraft.client.render.entity.model.EntityModelLayer
import net.minecraft.item.Item
import net.minecraft.particle.ParticleEffect
import net.minecraft.particle.ParticleType
import net.minecraft.resource.SynchronousResourceReloader
interface CobblemonClientImplementation {
fun registerLayer(modelLayer: EntityModelLayer, supplier: Supplier<TexturedModelData>)
@@ -22,4 +31,12 @@ interface CobblemonClientImplementation {
type: ParticleType<T>,
factory: (SpriteProvider) -> ParticleFactory<T>
)
fun registerBlockRenderType(layer: RenderLayer, vararg blocks: Block)
fun registerItemColors(provider: ItemColorProvider, vararg items: Item)
fun registerBlockColors(provider: BlockColorProvider, vararg blocks: Block)
fun <T : BlockEntity> registerBlockEntityRenderer(type: BlockEntityType<T>, factory: BlockEntityRendererFactory<T>)
}
@@ -20,6 +20,7 @@ object CobblemonCommands {
GivePokemon.register(dispatcher)
TakePokemon.register(dispatcher)
ChangeScaleAndSize.register(dispatcher)
ChangeWalkSpeed.register(dispatcher)
TestCommand.register(dispatcher)
ReloadShowdownCommand.register(dispatcher)
ClickTextCommand.register(dispatcher)
@@ -38,5 +39,11 @@ object CobblemonCommands {
PcCommand.register(dispatcher)
SpawnPokemonFromPool.register(dispatcher)
PokeboxCommand.register(dispatcher)
TestStoreCommand.register(dispatcher)
QueryLearnsetCommand.register(dispatcher)
TestPcSlotCommand.register(dispatcher)
TestPartySlotCommand.register(dispatcher)
ClearPartyCommand.register(dispatcher)
PokemonRestartCommand.register(dispatcher)
}
}
@@ -1,41 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common
import net.minecraft.util.registry.RegistryEntry
import net.minecraft.world.gen.feature.ConfiguredFeature
import net.minecraft.world.gen.feature.ConfiguredFeatures
import net.minecraft.world.gen.feature.SingleStateFeatureConfig
object CobblemonConfiguredFeatures {
lateinit var BLACK_APRICORN_TREE: RegistryEntry<ConfiguredFeature<SingleStateFeatureConfig, *>>
lateinit var BLUE_APRICORN_TREE: RegistryEntry<ConfiguredFeature<SingleStateFeatureConfig, *>>
lateinit var GREEN_APRICORN_TREE: RegistryEntry<ConfiguredFeature<SingleStateFeatureConfig, *>>
lateinit var PINK_APRICORN_TREE: RegistryEntry<ConfiguredFeature<SingleStateFeatureConfig, *>>
lateinit var RED_APRICORN_TREE: RegistryEntry<ConfiguredFeature<SingleStateFeatureConfig, *>>
lateinit var WHITE_APRICORN_TREE: RegistryEntry<ConfiguredFeature<SingleStateFeatureConfig, *>>
lateinit var YELLOW_APRICORN_TREE: RegistryEntry<ConfiguredFeature<SingleStateFeatureConfig, *>>
fun register() {
BLACK_APRICORN_TREE = ConfiguredFeatures.register("black_apricorn_tree", CobblemonFeatures.APRICORN_TREE_FEATURE.get(), SingleStateFeatureConfig(
CobblemonBlocks.BLACK_APRICORN.get().defaultState))
BLUE_APRICORN_TREE = ConfiguredFeatures.register("blue_apricorn_tree", CobblemonFeatures.APRICORN_TREE_FEATURE.get(), SingleStateFeatureConfig(
CobblemonBlocks.BLUE_APRICORN.get().defaultState))
GREEN_APRICORN_TREE = ConfiguredFeatures.register("green_apricorn_tree", CobblemonFeatures.APRICORN_TREE_FEATURE.get(), SingleStateFeatureConfig(
CobblemonBlocks.GREEN_APRICORN.get().defaultState))
PINK_APRICORN_TREE = ConfiguredFeatures.register("pink_apricorn_tree", CobblemonFeatures.APRICORN_TREE_FEATURE.get(), SingleStateFeatureConfig(
CobblemonBlocks.PINK_APRICORN.get().defaultState))
RED_APRICORN_TREE = ConfiguredFeatures.register("red_apricorn_tree", CobblemonFeatures.APRICORN_TREE_FEATURE.get(), SingleStateFeatureConfig(
CobblemonBlocks.RED_APRICORN.get().defaultState))
WHITE_APRICORN_TREE = ConfiguredFeatures.register("white_apricorn_tree", CobblemonFeatures.APRICORN_TREE_FEATURE.get(), SingleStateFeatureConfig(
CobblemonBlocks.WHITE_APRICORN.get().defaultState))
YELLOW_APRICORN_TREE = ConfiguredFeatures.register("yellow_apricorn_tree", CobblemonFeatures.APRICORN_TREE_FEATURE.get(), SingleStateFeatureConfig(
CobblemonBlocks.YELLOW_APRICORN.get().defaultState))
}
}
@@ -8,66 +8,45 @@
package com.cobblemon.mod.common
import com.cobblemon.mod.common.api.events.CobblemonEvents
import com.cobblemon.mod.common.api.events.entity.EntityAttributeEvent
import com.cobblemon.mod.common.api.pokeball.PokeBalls
import com.cobblemon.mod.common.entity.data.CobblemonTrackedDataHandlerRegistry
import com.cobblemon.mod.common.entity.pokeball.EmptyPokeBallEntity
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import com.cobblemon.mod.common.registry.CompletableRegistry
import com.cobblemon.mod.common.platform.PlatformRegistry
import com.cobblemon.mod.common.util.cobblemonResource
import dev.architectury.registry.level.entity.EntityAttributeRegistry
import dev.architectury.registry.registries.RegistrySupplier
import net.minecraft.entity.Entity
import net.minecraft.entity.EntityType
import net.minecraft.entity.LivingEntity
import net.minecraft.entity.SpawnGroup
import net.minecraft.entity.attribute.EntityAttributes
import net.minecraft.util.registry.Registry
import net.minecraft.entity.attribute.DefaultAttributeContainer
import net.minecraft.registry.Registries
import net.minecraft.registry.Registry
import net.minecraft.registry.RegistryKey
import net.minecraft.registry.RegistryKeys
object CobblemonEntities : CompletableRegistry<EntityType<*>>(Registry.ENTITY_TYPE_KEY) {
object CobblemonEntities : PlatformRegistry<Registry<EntityType<*>>, RegistryKey<Registry<EntityType<*>>>, EntityType<*>>() {
override fun register() {
super.register()
CobblemonTrackedDataHandlerRegistry.register()
EntityAttributeRegistry.register(
{ POKEMON.get() },
{
LivingEntity.createLivingAttributes()
.add(EntityAttributes.GENERIC_FOLLOW_RANGE)
.also { CobblemonEvents.ENTITY_ATTRIBUTE.post(EntityAttributeEvent(POKEMON.get(), it)) }
}
)
}
private fun <T : Entity> entity(
name: String,
entityTypeBuilder: EntityType.Builder<T>
): RegistrySupplier<EntityType<T>> {
return queue(name) { entityTypeBuilder.build(cobblemonResource(name).toString()) }
}
private fun <T : LivingEntity> livingEntity(
name: String,
entityTypeBuilder: EntityType.Builder<T>
): RegistrySupplier<EntityType<T>> {
return queue(name) { entityTypeBuilder.build(cobblemonResource("pokemon").toString()) }
}
override val registry: Registry<EntityType<*>> = Registries.ENTITY_TYPE
override val registryKey: RegistryKey<Registry<EntityType<*>>> = RegistryKeys.ENTITY_TYPE
@JvmField
val POKEMON = livingEntity(
name = "pokemon",
entityTypeBuilder = EntityType.Builder.create<PokemonEntity>(
{ _, world -> PokemonEntity(world) },
SpawnGroup.CREATURE
)
val POKEMON_KEY = cobblemonResource("pokemon")
@JvmField
val POKEMON: EntityType<PokemonEntity> = this.create(
POKEMON_KEY.path,
EntityType.Builder.create({ _, world -> PokemonEntity(world) }, SpawnGroup.CREATURE)
.build(POKEMON_KEY.toString())
)
@JvmField
val EMPTY_POKEBALL = entity(
name = "empty_pokeball",
entityTypeBuilder = EntityType.Builder.create<EmptyPokeBallEntity>(
{ _, world -> EmptyPokeBallEntity(PokeBalls.POKE_BALL, world) },
SpawnGroup.MISC
)
val EMPTY_POKEBALL_KEY = cobblemonResource("empty_pokeball")
@JvmField
val EMPTY_POKEBALL: EntityType<EmptyPokeBallEntity> = this.create(
EMPTY_POKEBALL_KEY.path,
EntityType.Builder.create({ _, world -> EmptyPokeBallEntity(PokeBalls.POKE_BALL, world) }, SpawnGroup.MISC)
.build(EMPTY_POKEBALL_KEY.toString())
)
fun registerAttributes(consumer: (EntityType<out LivingEntity>, DefaultAttributeContainer.Builder) -> Unit) {
consumer(POKEMON, PokemonEntity.createAttributes())
}
}
@@ -1,26 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common
import com.cobblemon.mod.common.registry.CompletableRegistry
import com.cobblemon.mod.common.world.feature.ApricornTreeFeature
import dev.architectury.registry.registries.RegistrySupplier
import java.util.function.Supplier
import net.minecraft.util.registry.Registry
import net.minecraft.world.gen.feature.Feature
import net.minecraft.world.gen.feature.SingleStateFeatureConfig
object CobblemonFeatures : CompletableRegistry<Feature<*>>(Registry.FEATURE_KEY) {
private fun <T : Feature<*>> register(name: String, feature: Supplier<T>) : RegistrySupplier<T> {
return queue(name, feature)
}
@JvmField
val APRICORN_TREE_FEATURE = register("apricorn_tree_feature") { ApricornTreeFeature(SingleStateFeatureConfig.CODEC) }
}
@@ -8,12 +8,158 @@
package com.cobblemon.mod.common
import com.cobblemon.mod.common.api.net.ClientNetworkPacketHandler
import com.cobblemon.mod.common.api.net.NetworkPacket
import com.cobblemon.mod.common.api.net.ServerNetworkPacketHandler
import com.mojang.brigadier.arguments.ArgumentType
import kotlin.reflect.KClass
import net.minecraft.advancement.criterion.Criterion
import net.minecraft.command.argument.serialize.ArgumentSerializer
import net.minecraft.network.PacketByteBuf
import net.minecraft.network.listener.ClientPlayPacketListener
import net.minecraft.network.packet.Packet
import net.minecraft.registry.RegistryKey
import net.minecraft.registry.tag.TagKey
import net.minecraft.resource.ResourceReloader
import net.minecraft.resource.ResourceType
import net.minecraft.server.MinecraftServer
import net.minecraft.server.network.ServerPlayerEntity
import net.minecraft.util.Identifier
import net.minecraft.world.GameRules
import net.minecraft.world.biome.Biome
import net.minecraft.world.gen.GenerationStep
import net.minecraft.world.gen.feature.PlacedFeature
interface CobblemonImplementation {
val modAPI: ModAPI
/**
*
*/
val networkManager: NetworkManager
/**
* TODO
*
* @return
*/
fun environment(): Environment
/**
* TODO
*
* @param id
* @return
*/
fun isModInstalled(id: String): Boolean
/**
* TODO
*
*/
fun registerPermissionValidator()
/**
* TODO
*
*/
fun registerSoundEvents()
/**
* TODO
*
*/
fun registerItems()
/**
* TODO
*
*/
fun registerBlocks()
/**
* TODO
*
*/
fun registerEntityTypes()
/**
* TODO
*
*/
fun registerEntityAttributes()
/**
* TODO
*
*/
fun registerBlockEntityTypes()
/**
* TODO
*
*/
fun registerWorldGenFeatures()
fun registerParticles()
/**
* Add a feature to the current platform implementation.
*
* @param feature The [PlacedFeature] being added.
* @param step The [GenerationStep.Feature] of this feature.
* @param validTag The [TagKey] required by the [Biome] for this feature to generate in, if null all biomes are valid.
*/
fun addFeatureToWorldGen(feature: RegistryKey<PlacedFeature>, step: GenerationStep.Feature, validTag: TagKey<Biome>?)
/**
* TODO
*
* @param A
* @param T
* @param identifier
* @param argumentClass
* @param serializer
*/
fun <A : ArgumentType<*>, T : ArgumentSerializer.ArgumentTypeProperties<A>> registerCommandArgument(identifier: Identifier, argumentClass: KClass<A>, serializer: ArgumentSerializer<A, T>)
/**
* TODO
*
* @param T
* @param name
* @param category
* @param type
* @return
*/
fun <T : GameRules.Rule<T>> registerGameRule(name: String, category: GameRules.Category, type: GameRules.Type<T>): GameRules.Key<T>
/**
* TODO
*
* @param T
* @param criteria
* @return
*/
fun <T : Criterion<*>> registerCriteria(criteria: T): T
/**
* TODO
*
* @param identifier
* @param reloader
* @param type
* @param dependencies
*/
fun registerResourceReloader(identifier: Identifier, reloader: ResourceReloader, type: ResourceType, dependencies: Collection<Identifier>)
/**
* TODO
*
* @return
*/
fun server(): MinecraftServer?
}
enum class ModAPI {
@@ -21,12 +167,27 @@ enum class ModAPI {
FORGE
}
interface NetworkDelegate {
interface NetworkManager {
fun sendPacketToPlayer(player: ServerPlayerEntity, packet: NetworkPacket)
fun sendPacketToServer(packet: NetworkPacket)
fun <T : NetworkPacket> buildMessage(
packetClass: Class<T>,
toServer: Boolean
): CobblemonNetwork.PreparedMessage<T>
}
fun registerClientBound()
fun registerServerBound()
fun <T: NetworkPacket<T>> createClientBound(identifier: Identifier, kClass: KClass<T>, encoder: (T, PacketByteBuf) -> Unit, decoder: (PacketByteBuf) -> T, handler: ClientNetworkPacketHandler<T>)
fun <T: NetworkPacket<T>> createServerBound(identifier: Identifier, kClass: KClass<T>, encoder: (T, PacketByteBuf) -> Unit, decoder: (PacketByteBuf) -> T, handler: ServerNetworkPacketHandler<T>)
fun sendPacketToPlayer(player: ServerPlayerEntity, packet: NetworkPacket<*>)
fun sendPacketToServer(packet: NetworkPacket<*>)
fun <T : NetworkPacket<*>> asVanillaClientBound(packet: T): Packet<ClientPlayPacketListener>
}
enum class Environment {
CLIENT,
SERVER
}
@@ -8,393 +8,589 @@
package com.cobblemon.mod.common
import com.cobblemon.mod.common.api.mulch.MulchVariant
import com.cobblemon.mod.common.api.pokeball.PokeBalls
import com.cobblemon.mod.common.api.pokemon.helditem.HeldItemProvider
import com.cobblemon.mod.common.api.pokemon.Natures
import com.cobblemon.mod.common.api.pokemon.stats.Stats
import com.cobblemon.mod.common.api.pokemon.status.Statuses
import com.cobblemon.mod.common.block.MintBlock.MintType
import com.cobblemon.mod.common.item.*
import com.cobblemon.mod.common.item.interactive.CandyItem
import com.cobblemon.mod.common.item.interactive.LinkCableItem
import com.cobblemon.mod.common.item.interactive.VitaminItem
import com.cobblemon.mod.common.item.battle.DireHitItem
import com.cobblemon.mod.common.item.battle.GuardSpecItem
import com.cobblemon.mod.common.item.battle.XStatItem
import com.cobblemon.mod.common.item.interactive.*
import com.cobblemon.mod.common.item.interactive.PotionItem
import com.cobblemon.mod.common.platform.PlatformRegistry
import com.cobblemon.mod.common.pokeball.PokeBall
import com.cobblemon.mod.common.pokemon.helditem.CobblemonHeldItemManager
import com.cobblemon.mod.common.registry.CompletableRegistry
import dev.architectury.registry.registries.RegistrySupplier
import net.minecraft.block.Block
import net.minecraft.block.ComposterBlock
import net.minecraft.entity.effect.StatusEffectInstance
import net.minecraft.entity.effect.StatusEffects
import net.minecraft.item.*
import net.minecraft.util.registry.Registry
import net.minecraft.registry.Registries
import net.minecraft.registry.Registry
import net.minecraft.registry.RegistryKey
import net.minecraft.registry.RegistryKeys
object CobblemonItems : CompletableRegistry<Item>(Registry.ITEM_KEY) {
@Suppress("unused")
object CobblemonItems : PlatformRegistry<Registry<Item>, RegistryKey<Registry<Item>>, Item>() {
override val registry: Registry<Item> = Registries.ITEM
override val registryKey: RegistryKey<Registry<Item>> = RegistryKeys.ITEM
init {
this.completed.thenRun {
val compostChance = ComposterBlock.ITEM_TO_LEVEL_INCREASE_CHANCE.getFloat(Items.OAK_LEAVES)
// Should always pass unless Mojang reworks leaves to no longer work in the Composter, in that case we already updated w.o doing anything
if (compostChance != ComposterBlock.ITEM_TO_LEVEL_INCREASE_CHANCE.defaultReturnValue()) {
ComposterBlock.ITEM_TO_LEVEL_INCREASE_CHANCE[APRICORN_LEAVES.get()] = compostChance
}
@JvmField
val pokeBalls = mutableListOf<PokeBallItem>()
@JvmField
val POKE_BALL = pokeBallItem(PokeBalls.POKE_BALL)
@JvmField
val CITRINE_BALL = pokeBallItem(PokeBalls.CITRINE_BALL)
@JvmField
val VERDANT_BALL = pokeBallItem(PokeBalls.VERDANT_BALL)
@JvmField
val AZURE_BALL = pokeBallItem(PokeBalls.AZURE_BALL)
@JvmField
val ROSEATE_BALL = pokeBallItem(PokeBalls.ROSEATE_BALL)
@JvmField
val SLATE_BALL = pokeBallItem(PokeBalls.SLATE_BALL)
@JvmField
val PREMIER_BALL = pokeBallItem(PokeBalls.PREMIER_BALL)
@JvmField
val GREAT_BALL = pokeBallItem(PokeBalls.GREAT_BALL)
@JvmField
val ULTRA_BALL = pokeBallItem(PokeBalls.ULTRA_BALL)
@JvmField
val SAFARI_BALL = pokeBallItem(PokeBalls.SAFARI_BALL)
@JvmField
val FAST_BALL = pokeBallItem(PokeBalls.FAST_BALL)
@JvmField
val LEVEL_BALL = pokeBallItem(PokeBalls.LEVEL_BALL)
@JvmField
val LURE_BALL = pokeBallItem(PokeBalls.LURE_BALL)
@JvmField
val HEAVY_BALL = pokeBallItem(PokeBalls.HEAVY_BALL)
@JvmField
val LOVE_BALL = pokeBallItem(PokeBalls.LOVE_BALL)
@JvmField
val FRIEND_BALL = pokeBallItem(PokeBalls.FRIEND_BALL)
@JvmField
val MOON_BALL = pokeBallItem(PokeBalls.MOON_BALL)
@JvmField
val SPORT_BALL = pokeBallItem(PokeBalls.SPORT_BALL)
@JvmField
val PARK_BALL = pokeBallItem(PokeBalls.PARK_BALL)
@JvmField
val NET_BALL = pokeBallItem(PokeBalls.NET_BALL)
@JvmField
val DIVE_BALL = pokeBallItem(PokeBalls.DIVE_BALL)
@JvmField
val NEST_BALL = pokeBallItem(PokeBalls.NEST_BALL)
@JvmField
val REPEAT_BALL = pokeBallItem(PokeBalls.REPEAT_BALL)
@JvmField
val TIMER_BALL = pokeBallItem(PokeBalls.TIMER_BALL)
@JvmField
val LUXURY_BALL = pokeBallItem(PokeBalls.LUXURY_BALL)
@JvmField
val DUSK_BALL = pokeBallItem(PokeBalls.DUSK_BALL)
@JvmField
val HEAL_BALL = pokeBallItem(PokeBalls.HEAL_BALL)
@JvmField
val QUICK_BALL = pokeBallItem(PokeBalls.QUICK_BALL)
@JvmField
val DREAM_BALL = pokeBallItem(PokeBalls.DREAM_BALL)
@JvmField
val BEAST_BALL = pokeBallItem(PokeBalls.BEAST_BALL)
@JvmField
val MASTER_BALL = pokeBallItem(PokeBalls.MASTER_BALL)
@JvmField
val CHERISH_BALL = pokeBallItem(PokeBalls.CHERISH_BALL)
@JvmField
val VIVICHOKE = create("vivichoke", Item(Item.Settings()))
@JvmField
val VIVICHOKE_SEEDS = create("vivichoke_seeds", VivichokeItem(CobblemonBlocks.VIVICHOKE_SEEDS))
@JvmField
val RED_APRICORN = create("red_apricorn", ApricornItem(CobblemonBlocks.RED_APRICORN))
@JvmField
val YELLOW_APRICORN = create("yellow_apricorn", ApricornItem(CobblemonBlocks.YELLOW_APRICORN))
@JvmField
val GREEN_APRICORN = create("green_apricorn", ApricornItem(CobblemonBlocks.GREEN_APRICORN))
@JvmField
val BLUE_APRICORN = create("blue_apricorn", ApricornItem(CobblemonBlocks.BLUE_APRICORN))
@JvmField
val PINK_APRICORN = create("pink_apricorn", ApricornItem(CobblemonBlocks.PINK_APRICORN))
@JvmField
val BLACK_APRICORN = create("black_apricorn", ApricornItem(CobblemonBlocks.BLACK_APRICORN))
@JvmField
val WHITE_APRICORN = create("white_apricorn", ApricornItem(CobblemonBlocks.WHITE_APRICORN))
@JvmField
val RED_APRICORN_SEED = create("red_apricorn_seed", ApricornSeedItem(CobblemonBlocks.RED_APRICORN_SAPLING))
@JvmField
val YELLOW_APRICORN_SEED = create("yellow_apricorn_seed", ApricornSeedItem(CobblemonBlocks.YELLOW_APRICORN_SAPLING))
@JvmField
val GREEN_APRICORN_SEED = create("green_apricorn_seed", ApricornSeedItem(CobblemonBlocks.GREEN_APRICORN_SAPLING))
@JvmField
val BLUE_APRICORN_SEED = create("blue_apricorn_seed", ApricornSeedItem(CobblemonBlocks.BLUE_APRICORN_SAPLING))
@JvmField
val PINK_APRICORN_SEED = create("pink_apricorn_seed", ApricornSeedItem(CobblemonBlocks.PINK_APRICORN_SAPLING))
@JvmField
val BLACK_APRICORN_SEED = create("black_apricorn_seed", ApricornSeedItem(CobblemonBlocks.BLACK_APRICORN_SAPLING))
@JvmField
val WHITE_APRICORN_SEED = create("white_apricorn_seed", ApricornSeedItem(CobblemonBlocks.WHITE_APRICORN_SAPLING))
@JvmField
val APRICORN_LOG = blockItem("apricorn_log", CobblemonBlocks.APRICORN_LOG)
@JvmField
val STRIPPED_APRICORN_LOG = blockItem("stripped_apricorn_log", CobblemonBlocks.STRIPPED_APRICORN_LOG)
@JvmField
val APRICORN_WOOD = blockItem("apricorn_wood", CobblemonBlocks.APRICORN_WOOD)
@JvmField
val STRIPPED_APRICORN_WOOD = blockItem("stripped_apricorn_wood", CobblemonBlocks.STRIPPED_APRICORN_WOOD)
@JvmField
val APRICORN_PLANKS = blockItem("apricorn_planks", CobblemonBlocks.APRICORN_PLANKS)
@JvmField
val APRICORN_LEAVES = blockItem("apricorn_leaves", CobblemonBlocks.APRICORN_LEAVES).also {
val compostChance = ComposterBlock.ITEM_TO_LEVEL_INCREASE_CHANCE.getFloat(Items.OAK_LEAVES)
// Should always pass unless Mojang reworks leaves to no longer work in the Composter, in that case we already updated w.o doing anything
if (compostChance != ComposterBlock.ITEM_TO_LEVEL_INCREASE_CHANCE.defaultReturnValue()) {
ComposterBlock.ITEM_TO_LEVEL_INCREASE_CHANCE[it] = compostChance
}
}
private val pokeballs = mutableListOf<RegistrySupplier<PokeBallItem>>()
@JvmField
val POKE_BALL = pokeballItem(PokeBalls.POKE_BALL)
val APRICORN_DOOR = blockItem("apricorn_door", CobblemonBlocks.APRICORN_DOOR)
@JvmField
val CITRINE_BALL = pokeballItem(PokeBalls.CITRINE_BALL)
val APRICORN_TRAPDOOR = blockItem("apricorn_trapdoor", CobblemonBlocks.APRICORN_TRAPDOOR)
@JvmField
val VERDANT_BALL = pokeballItem(PokeBalls.VERDANT_BALL)
val APRICORN_FENCE = blockItem("apricorn_fence", CobblemonBlocks.APRICORN_FENCE)
@JvmField
val AZURE_BALL = pokeballItem(PokeBalls.AZURE_BALL)
val APRICORN_FENCE_GATE = blockItem("apricorn_fence_gate", CobblemonBlocks.APRICORN_FENCE_GATE)
@JvmField
val ROSEATE_BALL = pokeballItem(PokeBalls.ROSEATE_BALL)
val APRICORN_BUTTON = blockItem("apricorn_button", CobblemonBlocks.APRICORN_BUTTON)
@JvmField
val SLATE_BALL = pokeballItem(PokeBalls.SLATE_BALL)
@JvmField
val PREMIER_BALL = pokeballItem(PokeBalls.PREMIER_BALL)
@JvmField
val GREAT_BALL = pokeballItem(PokeBalls.GREAT_BALL)
@JvmField
val ULTRA_BALL = pokeballItem(PokeBalls.ULTRA_BALL)
@JvmField
val SAFARI_BALL = pokeballItem(PokeBalls.SAFARI_BALL)
@JvmField
val FAST_BALL = pokeballItem(PokeBalls.FAST_BALL)
@JvmField
val LEVEL_BALL = pokeballItem(PokeBalls.LEVEL_BALL)
@JvmField
val LURE_BALL = pokeballItem(PokeBalls.LURE_BALL)
@JvmField
val HEAVY_BALL = pokeballItem(PokeBalls.HEAVY_BALL)
@JvmField
val LOVE_BALL = pokeballItem(PokeBalls.LOVE_BALL)
@JvmField
val FRIEND_BALL = pokeballItem(PokeBalls.FRIEND_BALL)
@JvmField
val MOON_BALL = pokeballItem(PokeBalls.MOON_BALL)
@JvmField
val SPORT_BALL = pokeballItem(PokeBalls.SPORT_BALL)
@JvmField
val PARK_BALL = pokeballItem(PokeBalls.PARK_BALL)
@JvmField
val NET_BALL = pokeballItem(PokeBalls.NET_BALL)
@JvmField
val DIVE_BALL = pokeballItem(PokeBalls.DIVE_BALL)
@JvmField
val NEST_BALL = pokeballItem(PokeBalls.NEST_BALL)
@JvmField
val REPEAT_BALL = pokeballItem(PokeBalls.REPEAT_BALL)
@JvmField
val TIMER_BALL = pokeballItem(PokeBalls.TIMER_BALL)
@JvmField
val LUXURY_BALL = pokeballItem(PokeBalls.LUXURY_BALL)
@JvmField
val DUSK_BALL = pokeballItem(PokeBalls.DUSK_BALL)
@JvmField
val HEAL_BALL = pokeballItem(PokeBalls.HEAL_BALL)
@JvmField
val QUICK_BALL = pokeballItem(PokeBalls.QUICK_BALL)
@JvmField
val DREAM_BALL = pokeballItem(PokeBalls.DREAM_BALL)
@JvmField
val BEAST_BALL = pokeballItem(PokeBalls.BEAST_BALL)
@JvmField
val MASTER_BALL = pokeballItem(PokeBalls.MASTER_BALL)
@JvmField
val CHERISH_BALL = pokeballItem(PokeBalls.CHERISH_BALL)
@JvmField
val RED_APRICORN = queue("red_apricorn") { ApricornItem(CobblemonBlocks.RED_APRICORN.get()) }
@JvmField
val YELLOW_APRICORN = queue("yellow_apricorn") { ApricornItem(CobblemonBlocks.YELLOW_APRICORN.get()) }
@JvmField
val GREEN_APRICORN = queue("green_apricorn") { ApricornItem(CobblemonBlocks.GREEN_APRICORN.get()) }
@JvmField
val BLUE_APRICORN = queue("blue_apricorn") { ApricornItem(CobblemonBlocks.BLUE_APRICORN.get()) }
@JvmField
val PINK_APRICORN = queue("pink_apricorn") { ApricornItem(CobblemonBlocks.PINK_APRICORN.get()) }
@JvmField
val BLACK_APRICORN = queue("black_apricorn") { ApricornItem(CobblemonBlocks.BLACK_APRICORN.get()) }
@JvmField
val WHITE_APRICORN = queue("white_apricorn") { ApricornItem(CobblemonBlocks.WHITE_APRICORN.get()) }
@JvmField
val RED_APRICORN_SEED = queue("red_apricorn_seed") { ApricornSeedItem(CobblemonBlocks.RED_APRICORN_SAPLING.get(), ItemGroup.MISC) }
@JvmField
val YELLOW_APRICORN_SEED = queue("yellow_apricorn_seed") { ApricornSeedItem(CobblemonBlocks.YELLOW_APRICORN_SAPLING.get(), ItemGroup.MISC) }
@JvmField
val GREEN_APRICORN_SEED = queue("green_apricorn_seed") { ApricornSeedItem(CobblemonBlocks.GREEN_APRICORN_SAPLING.get(), ItemGroup.MISC) }
@JvmField
val BLUE_APRICORN_SEED = queue("blue_apricorn_seed") { ApricornSeedItem(CobblemonBlocks.BLUE_APRICORN_SAPLING.get(), ItemGroup.MISC) }
@JvmField
val PINK_APRICORN_SEED = queue("pink_apricorn_seed") { ApricornSeedItem(CobblemonBlocks.PINK_APRICORN_SAPLING.get(), ItemGroup.MISC) }
@JvmField
val BLACK_APRICORN_SEED = queue("black_apricorn_seed") { ApricornSeedItem(CobblemonBlocks.BLACK_APRICORN_SAPLING.get(), ItemGroup.MISC) }
@JvmField
val WHITE_APRICORN_SEED = queue("white_apricorn_seed") { ApricornSeedItem(CobblemonBlocks.WHITE_APRICORN_SAPLING.get(), ItemGroup.MISC) }
@JvmField
val APRICORN_LOG = queue("apricorn_log") { blockItem(CobblemonBlocks.APRICORN_LOG.get(), ItemGroup.BUILDING_BLOCKS) }
@JvmField
val STRIPPED_APRICORN_LOG = queue("stripped_apricorn_log") { blockItem(CobblemonBlocks.STRIPPED_APRICORN_LOG.get(), ItemGroup.BUILDING_BLOCKS) }
@JvmField
val APRICORN_WOOD = queue("apricorn_wood") { blockItem(CobblemonBlocks.APRICORN_WOOD.get(), ItemGroup.BUILDING_BLOCKS) }
@JvmField
val STRIPPED_APRICORN_WOOD = queue("stripped_apricorn_wood") { blockItem(CobblemonBlocks.STRIPPED_APRICORN_WOOD.get(), ItemGroup.BUILDING_BLOCKS) }
@JvmField
val APRICORN_PLANKS = queue("apricorn_planks") { blockItem(CobblemonBlocks.APRICORN_PLANKS.get(), ItemGroup.BUILDING_BLOCKS) }
@JvmField
val APRICORN_LEAVES = queue("apricorn_leaves") { blockItem(CobblemonBlocks.APRICORN_LEAVES.get(), ItemGroup.BUILDING_BLOCKS) }
@JvmField
val APRICORN_DOOR = queue("apricorn_door") { blockItem(CobblemonBlocks.APRICORN_DOOR.get(), ItemGroup.REDSTONE) }
@JvmField
val APRICORN_TRAPDOOR = queue("apricorn_trapdoor") { blockItem(CobblemonBlocks.APRICORN_TRAPDOOR.get(), ItemGroup.REDSTONE) }
@JvmField
val APRICORN_FENCE = queue("apricorn_fence") { blockItem(CobblemonBlocks.APRICORN_FENCE.get(), ItemGroup.DECORATIONS) }
@JvmField
val APRICORN_FENCE_GATE = queue("apricorn_fence_gate") { blockItem(CobblemonBlocks.APRICORN_FENCE_GATE.get(), ItemGroup.REDSTONE) }
@JvmField
val APRICORN_BUTTON = queue("apricorn_button") { blockItem(CobblemonBlocks.APRICORN_BUTTON.get(), ItemGroup.REDSTONE) }
@JvmField
val APRICORN_PRESSURE_PLATE = queue("apricorn_pressure_plate") { blockItem(CobblemonBlocks.APRICORN_PRESSURE_PLATE.get(), ItemGroup.REDSTONE) }
val APRICORN_PRESSURE_PLATE = blockItem("apricorn_pressure_plate", CobblemonBlocks.APRICORN_PRESSURE_PLATE)
//@JvmField
// val APRICORN_SIGN = queue("apricorn_sign", SignItem(Item.Properties().stacksTo(16).tab(CreativeModeTab.TAB_DECORATIONS), CobblemonBlocks.APRICORN_SIGN, CobblemonBlocks.APRICORN_WALL_SIGN))
// val APRICORN_SIGN = create("apricorn_sign", SignItem(Item.Properties().stacksTo(16).tab(CreativeModeTab.TAB_DECORATIONS), CobblemonBlocks.APRICORN_SIGN, CobblemonBlocks.APRICORN_WALL_SIGN))
@JvmField
val APRICORN_SLAB = queue("apricorn_slab") { blockItem(CobblemonBlocks.APRICORN_SLAB.get(), ItemGroup.BUILDING_BLOCKS) }
val APRICORN_SLAB = blockItem("apricorn_slab", CobblemonBlocks.APRICORN_SLAB)
@JvmField
val APRICORN_STAIRS = queue("apricorn_stairs") { blockItem(CobblemonBlocks.APRICORN_STAIRS.get(), ItemGroup.BUILDING_BLOCKS) }
val APRICORN_STAIRS = blockItem("apricorn_stairs", CobblemonBlocks.APRICORN_STAIRS)
@JvmField
val HEALING_MACHINE = queue("healing_machine") { blockItem(CobblemonBlocks.HEALING_MACHINE.get(), ItemGroup.REDSTONE) }
val HEALING_MACHINE = blockItem("healing_machine", CobblemonBlocks.HEALING_MACHINE)
@JvmField
val PC = queue("pc") { blockItem(CobblemonBlocks.PC.get(), ItemGroup.REDSTONE) }
val PC = blockItem("pc", CobblemonBlocks.PC)
@JvmField
val PASTURE = blockItem("pasture", CobblemonBlocks.PASTURE)
// Evolution items
@JvmField val LINK_CABLE = this.queue("link_cable") { LinkCableItem() }
@JvmField val DRAGON_SCALE = this.evolutionItem("dragon_scale")
@JvmField val KINGS_ROCK = this.evolutionItem("kings_rock")
@JvmField val METAL_COAT = this.evolutionItem("metal_coat")
@JvmField val UPGRADE = this.evolutionItem("upgrade")
@JvmField val DUBIOUS_DISC = this.evolutionItem("dubious_disc")
@JvmField val DEEP_SEA_SCALE = this.evolutionItem("deep_sea_scale")
@JvmField val DEEP_SEA_TOOTH = this.evolutionItem("deep_sea_tooth")
@JvmField val ELECTIRIZER = this.evolutionItem("electirizer")
@JvmField val MAGMARIZER = this.evolutionItem("magmarizer")
@JvmField val OVAL_STONE = this.evolutionItem("oval_stone")
@JvmField val PROTECTOR = this.evolutionItem("protector")
@JvmField val REAPER_CLOTH = this.evolutionItem("reaper_cloth")
@JvmField val PRISM_SCALE = this.evolutionItem("prism_scale")
@JvmField val SACHET = this.evolutionItem("sachet")
@JvmField val WHIPPED_DREAM = this.evolutionItem("whipped_dream")
@JvmField val STRAWBERRY_SWEET = this.evolutionItem("strawberry_sweet")
@JvmField val LOVE_SWEET = this.evolutionItem("love_sweet")
@JvmField val BERRY_SWEET = this.evolutionItem("berry_sweet")
@JvmField val CLOVER_SWEET = this.evolutionItem("clover_sweet")
@JvmField val FLOWER_SWEET = this.evolutionItem("flower_sweet")
@JvmField val STAR_SWEET = this.evolutionItem("star_sweet")
@JvmField val RIBBON_SWEET = this.evolutionItem("ribbon_sweet")
@JvmField val CHIPPED_POT = this.evolutionItem("chipped_pot")
@JvmField val CRACKED_POT = this.evolutionItem("cracked_pot")
@JvmField val SWEET_APPLE = this.evolutionItem("sweet_apple")
@JvmField val TART_APPLE = this.evolutionItem("tart_apple")
@JvmField val GALARICA_CUFF = this.evolutionItem("galarica_cuff")
@JvmField val GALARICA_WREATH = this.evolutionItem("galarica_wreath")
@JvmField val BLACK_AUGURITE = this.evolutionItem("black_augurite")
@JvmField val PEAT_BLOCK = this.evolutionItem("peat_block")
@JvmField val RAZOR_CLAW = this.evolutionItem("razor_claw")
@JvmField val RAZOR_FANG = this.evolutionItem("razor_fang")
@JvmField val LINK_CABLE = create("link_cable", LinkCableItem())
@JvmField val DRAGON_SCALE = noSettingsItem("dragon_scale")
@JvmField val KINGS_ROCK = noSettingsItem("kings_rock")
@JvmField val METAL_COAT = noSettingsItem("metal_coat")
@JvmField val UPGRADE = noSettingsItem("upgrade")
@JvmField val DUBIOUS_DISC = noSettingsItem("dubious_disc")
@JvmField val DEEP_SEA_SCALE = noSettingsItem("deep_sea_scale")
@JvmField val DEEP_SEA_TOOTH = noSettingsItem("deep_sea_tooth")
@JvmField val ELECTIRIZER = noSettingsItem("electirizer")
@JvmField val MAGMARIZER = noSettingsItem("magmarizer")
@JvmField val OVAL_STONE = noSettingsItem("oval_stone")
@JvmField val PROTECTOR = noSettingsItem("protector")
@JvmField val REAPER_CLOTH = noSettingsItem("reaper_cloth")
@JvmField val PRISM_SCALE = noSettingsItem("prism_scale")
@JvmField val SACHET = noSettingsItem("sachet")
@JvmField val WHIPPED_DREAM = noSettingsItem("whipped_dream")
@JvmField val STRAWBERRY_SWEET = noSettingsItem("strawberry_sweet")
@JvmField val LOVE_SWEET = noSettingsItem("love_sweet")
@JvmField val BERRY_SWEET = noSettingsItem("berry_sweet")
@JvmField val CLOVER_SWEET = noSettingsItem("clover_sweet")
@JvmField val FLOWER_SWEET = noSettingsItem("flower_sweet")
@JvmField val STAR_SWEET = noSettingsItem("star_sweet")
@JvmField val RIBBON_SWEET = noSettingsItem("ribbon_sweet")
@JvmField val CHIPPED_POT = noSettingsItem("chipped_pot")
@JvmField val CRACKED_POT = noSettingsItem("cracked_pot")
@JvmField val SWEET_APPLE = noSettingsItem("sweet_apple")
@JvmField val TART_APPLE = noSettingsItem("tart_apple")
@JvmField val GALARICA_CUFF = noSettingsItem("galarica_cuff")
@JvmField val GALARICA_WREATH = noSettingsItem("galarica_wreath")
@JvmField val BLACK_AUGURITE = noSettingsItem("black_augurite")
@JvmField val PEAT_BLOCK = noSettingsItem("peat_block")
@JvmField val RAZOR_CLAW = noSettingsItem("razor_claw")
@JvmField val RAZOR_FANG = noSettingsItem("razor_fang")
// ToDo enable me when malicious armor goes in the game
//@JvmField val AUSPICIOUS_ARMOR = this.heldItem("auspicious_armor")
//@JvmField val AUSPICIOUS_ARMOR = heldItem("auspicious_armor")
// Medicine
@JvmField
val RARE_CANDY = queue("rare_candy") { CandyItem { _, pokemon -> pokemon.getExperienceToNextLevel() } }
val RARE_CANDY = candyItem("rare_candy") { _, pokemon -> pokemon.getExperienceToNextLevel() }
@JvmField
val EXPERIENCE_CANDY_XS = queue("exp_candy_xs") { CandyItem { _, _ -> CandyItem.DEFAULT_XS_CANDY_YIELD } }
val EXPERIENCE_CANDY_XS = candyItem("exp_candy_xs") { _, _ -> CandyItem.DEFAULT_XS_CANDY_YIELD }
@JvmField
val EXPERIENCE_CANDY_S = queue("exp_candy_s") { CandyItem { _, _ -> CandyItem.DEFAULT_S_CANDY_YIELD } }
val EXPERIENCE_CANDY_S = candyItem("exp_candy_s") { _, _ -> CandyItem.DEFAULT_S_CANDY_YIELD }
@JvmField
val EXPERIENCE_CANDY_M = queue("exp_candy_m") { CandyItem { _, _ -> CandyItem.DEFAULT_M_CANDY_YIELD } }
val EXPERIENCE_CANDY_M = candyItem("exp_candy_m") { _, _ -> CandyItem.DEFAULT_M_CANDY_YIELD }
@JvmField
val EXPERIENCE_CANDY_L = queue("exp_candy_l") { CandyItem { _, _ -> CandyItem.DEFAULT_L_CANDY_YIELD } }
val EXPERIENCE_CANDY_L = candyItem("exp_candy_l") { _, _ -> CandyItem.DEFAULT_L_CANDY_YIELD }
@JvmField
val EXPERIENCE_CANDY_XL = queue("exp_candy_xl") { CandyItem { _, _ -> CandyItem.DEFAULT_XL_CANDY_YIELD } }
val EXPERIENCE_CANDY_XL = candyItem("exp_candy_xl") { _, _ -> CandyItem.DEFAULT_XL_CANDY_YIELD }
@JvmField
val CALCIUM = queue("calcium") { VitaminItem(Stats.SPECIAL_ATTACK) }
val CALCIUM = create("calcium", VitaminItem(Stats.SPECIAL_ATTACK))
@JvmField
val CARBOS = queue("carbos") { VitaminItem(Stats.SPEED) }
val CARBOS = create("carbos", VitaminItem(Stats.SPEED))
@JvmField
val HP_UP = queue("hp_up") { VitaminItem(Stats.HP) }
val HP_UP = create("hp_up", VitaminItem(Stats.HP))
@JvmField
val IRON = queue("iron") { VitaminItem(Stats.DEFENCE) }
val IRON = create("iron", VitaminItem(Stats.DEFENCE))
@JvmField
val PROTEIN = queue("protein") { VitaminItem(Stats.ATTACK) }
val PROTEIN = create("protein", VitaminItem(Stats.ATTACK))
@JvmField
val ZINC = queue("zinc") { VitaminItem(Stats.SPECIAL_DEFENCE) }
val ZINC = create("zinc", VitaminItem(Stats.SPECIAL_DEFENCE))
@JvmField
val MEDICINAL_LEEK = create("medicinal_leek", MedicinalLeekItem(CobblemonBlocks.MEDICINAL_LEEK, Item.Settings().food(FoodComponent.Builder().snack().hunger(1).saturationModifier(0.2f).build())))
@JvmField
val ROASTED_LEEK = create("roasted_leek", Item(Item.Settings().food(FoodComponent.Builder().snack().hunger(3).saturationModifier(0.3f).build())))
@JvmField
val BRAISED_VIVICHOKE = create("braised_vivichoke", Item(Item.Settings().maxCount(1).food(FoodComponent.Builder().hunger(6).saturationModifier(0.6f).build())))
@JvmField
val VIVICHOKE_DIP = create("vivichoke_dip", StewItem(Item.Settings().maxCount(1)
.food(FoodComponent.Builder()
.hunger(10)
.saturationModifier(1.2F)
.statusEffect(StatusEffectInstance(StatusEffects.ABSORPTION, 600, 0), 1F)
.build()
)
))
@JvmField
val ENERGY_ROOT = create("energy_root", EnergyRootItem(CobblemonBlocks.ENERGY_ROOT, Item.Settings().food(FoodComponent.Builder().hunger(1).snack().saturationModifier(0.2f).build())))
@JvmField
val REVIVAL_HERB = create("revival_herb", RevivalHerbItem(CobblemonBlocks.REVIVAL_HERB))
@JvmField
val PEP_UP_FLOWER = blockItem("pep_up_flower", CobblemonBlocks.PEP_UP_FLOWER)
@JvmField
val MEDICINAL_BREW = create("medicinal_brew", Item(Item.Settings()))
@JvmField
val REMEDY = create("remedy", RemedyItem(RemedyItem.NORMAL))
@JvmField
val FINE_REMEDY = create("fine_remedy", RemedyItem(RemedyItem.FINE))
@JvmField
val SUPERB_REMEDY = create("superb_remedy", RemedyItem(RemedyItem.SUPERB))
@JvmField
val POTION = create("potion", PotionItem(PotionType.POTION))
@JvmField
val SUPER_POTION = create("super_potion", PotionItem(PotionType.SUPER_POTION))
@JvmField
val HYPER_POTION = create("hyper_potion", PotionItem(PotionType.HYPER_POTION))
@JvmField
val MAX_POTION = create("max_potion", PotionItem(PotionType.MAX_POTION))
@JvmField
val FULL_RESTORE = create("full_restore", PotionItem(PotionType.FULL_RESTORE))
@JvmField
val HEAL_POWDER = create("heal_powder", HealPowderItem())
@JvmField
val LEEK_AND_POTATO_STEW = create("leek_and_potato_stew", StewItem(Item.Settings().food(FoodComponent.Builder().hunger(8).saturationModifier(0.6f).build()).maxCount(1)))
@JvmField
val REVIVE = create("revive", ReviveItem(max = false))
@JvmField
val MAX_REVIVE = create("max_revive", ReviveItem(max = true))
@JvmField
val PP_UP = create("pp_up", PPUpItem(1))
@JvmField
val PP_MAX = create("pp_max", PPUpItem(3))
@JvmField
val RED_MINT_SEEDS = blockItem("red_mint_seeds", MintType.RED.getCropBlock())
@JvmField
val RED_MINT_LEAF = create("red_mint_leaf", MintLeafItem(MintType.RED))
@JvmField
val BLUE_MINT_SEEDS = blockItem("blue_mint_seeds", MintType.BLUE.getCropBlock())
@JvmField
val BLUE_MINT_LEAF = create("blue_mint_leaf", MintLeafItem(MintType.BLUE))
@JvmField
val CYAN_MINT_SEEDS = blockItem("cyan_mint_seeds", MintType.CYAN.getCropBlock())
@JvmField
val CYAN_MINT_LEAF = create("cyan_mint_leaf", MintLeafItem(MintType.CYAN))
@JvmField
val PINK_MINT_SEEDS = blockItem("pink_mint_seeds", MintType.PINK.getCropBlock())
@JvmField
val PINK_MINT_LEAF = create("pink_mint_leaf", MintLeafItem(MintType.PINK))
@JvmField
val GREEN_MINT_SEEDS = blockItem("green_mint_seeds", MintType.GREEN.getCropBlock())
@JvmField
val GREEN_MINT_LEAF = create("green_mint_leaf", MintLeafItem(MintType.GREEN))
@JvmField
val WHITE_MINT_SEEDS = blockItem("white_mint_seeds", MintType.WHITE.getCropBlock())
@JvmField
val WHITE_MINT_LEAF = create("white_mint_leaf", MintLeafItem(MintType.WHITE))
@JvmField
val LONELY_MINT = create("lonely_mint", MintItem(Natures.LONELY))
@JvmField
val ADAMANT_MINT = create("adamant_mint", MintItem(Natures.ADAMANT))
@JvmField
val NAUGHTY_MINT = create("naughty_mint", MintItem(Natures.NAUGHTY))
@JvmField
val BRAVE_MINT = create("brave_mint", MintItem(Natures.BRAVE))
@JvmField
val BOLD_MINT = create("bold_mint", MintItem(Natures.BOLD))
@JvmField
val IMPISH_MINT = create("impish_mint", MintItem(Natures.IMPISH))
@JvmField
val LAX_MINT = create("lax_mint", MintItem(Natures.LAX))
@JvmField
val RELAXED_MINT = create("relaxed_mint", MintItem(Natures.RELAXED))
@JvmField
val MODEST_MINT = create("modest_mint", MintItem(Natures.MODEST))
@JvmField
val MILD_MINT = create("mild_mint", MintItem(Natures.MILD))
@JvmField
val RASH_MINT = create("rash_mint", MintItem(Natures.RASH))
@JvmField
val QUIET_MINT = create("quiet_mint", MintItem(Natures.QUIET))
@JvmField
val CALM_MINT = create("calm_mint", MintItem(Natures.CALM))
@JvmField
val GENTLE_MINT = create("gentle_mint", MintItem(Natures.GENTLE))
@JvmField
val CAREFUL_MINT = create("careful_mint", MintItem(Natures.CAREFUL))
@JvmField
val SASSY_MINT = create("sassy_mint", MintItem(Natures.SASSY))
@JvmField
val TIMID_MINT = create("timid_mint", MintItem(Natures.TIMID))
@JvmField
val HASTY_MINT = create("hasty_mint", MintItem(Natures.HASTY))
@JvmField
val JOLLY_MINT = create("jolly_mint", MintItem(Natures.JOLLY))
@JvmField
val NAIVE_MINT = create("naive_mint", MintItem(Natures.NAIVE))
@JvmField
val SERIOUS_MINT = create("serious_mint", MintItem(Natures.SERIOUS))
@JvmField val X_ACCURACY = create("x_${Stats.ACCURACY.identifier.path}", XStatItem(Stats.ACCURACY))
@JvmField val X_ATTACK = create("x_${Stats.ATTACK.identifier.path}", XStatItem(Stats.ATTACK))
@JvmField val X_DEFENSE = create("x_${Stats.DEFENCE.identifier.path}", XStatItem(Stats.DEFENCE))
@JvmField val X_SP_ATK = create("x_${Stats.SPECIAL_ATTACK.identifier.path}", XStatItem(Stats.SPECIAL_ATTACK))
@JvmField val X_SP_DEF = create("x_${Stats.SPECIAL_DEFENCE.identifier.path}", XStatItem(Stats.SPECIAL_DEFENCE))
@JvmField val X_SPEED = create("x_${Stats.SPEED.identifier.path}", XStatItem(Stats.SPEED))
@JvmField val DIRE_HIT = create("dire_hit", DireHitItem())
@JvmField val GUARD_SPEC = create("guard_spec", GuardSpecItem())
@JvmField val BURN_HEAL = create("burn_heal", StatusCureItem("item.cobblemon.burn_heal", Statuses.BURN))
@JvmField val PARALYZE_HEAL = create("paralyze_heal", StatusCureItem("item.cobblemon.paralyze_heal", Statuses.PARALYSIS))
@JvmField val ICE_HEAL = create("ice_heal", StatusCureItem("item.cobblemon.ice_heal", Statuses.FROZEN))
@JvmField val ANTIDOTE = create("antidote", StatusCureItem("item.cobblemon.antidote", Statuses.POISON, Statuses.POISON_BADLY))
@JvmField val AWAKENING = create("awakening", StatusCureItem("item.cobblemon.awakening", Statuses.SLEEP))
@JvmField val FULL_HEAL = create("full_heal", StatusCureItem("item.cobblemon.full_heal"))
@JvmField val ETHER = create("ether", EtherItem(max = false))
@JvmField val MAX_ETHER = create("max_ether", EtherItem(max = true))
@JvmField val ELIXIR = create("elixir", ElixirItem(max = false))
@JvmField val MAX_ELIXIR = create("max_elixir", ElixirItem(max = true))
/**
* Evolution Ores and Stones
*/
@JvmField
val DAWN_STONE_ORE = queue("dawn_stone_ore") { blockItem(CobblemonBlocks.DAWN_STONE_ORE.get(), ItemGroup.BUILDING_BLOCKS) }
val DAWN_STONE_ORE = blockItem("dawn_stone_ore", CobblemonBlocks.DAWN_STONE_ORE)
@JvmField
val DUSK_STONE_ORE = queue("dusk_stone_ore") { blockItem(CobblemonBlocks.DUSK_STONE_ORE.get(), ItemGroup.BUILDING_BLOCKS) }
val DUSK_STONE_ORE = blockItem("dusk_stone_ore", CobblemonBlocks.DUSK_STONE_ORE)
@JvmField
val FIRE_STONE_ORE = queue("fire_stone_ore") { blockItem(CobblemonBlocks.FIRE_STONE_ORE.get(), ItemGroup.BUILDING_BLOCKS) }
val FIRE_STONE_ORE = blockItem("fire_stone_ore", CobblemonBlocks.FIRE_STONE_ORE)
@JvmField
val ICE_STONE_ORE = queue("ice_stone_ore") { blockItem(CobblemonBlocks.ICE_STONE_ORE.get(), ItemGroup.BUILDING_BLOCKS) }
val ICE_STONE_ORE = blockItem("ice_stone_ore", CobblemonBlocks.ICE_STONE_ORE)
@JvmField
val LEAF_STONE_ORE = queue("leaf_stone_ore") { blockItem(CobblemonBlocks.LEAF_STONE_ORE.get(), ItemGroup.BUILDING_BLOCKS) }
val LEAF_STONE_ORE = blockItem("leaf_stone_ore", CobblemonBlocks.LEAF_STONE_ORE)
@JvmField
val MOON_STONE_ORE = queue("moon_stone_ore") { blockItem(CobblemonBlocks.MOON_STONE_ORE.get(), ItemGroup.BUILDING_BLOCKS) }
val MOON_STONE_ORE = blockItem("moon_stone_ore", CobblemonBlocks.MOON_STONE_ORE)
@JvmField
val SHINY_STONE_ORE = queue("shiny_stone_ore") { blockItem(CobblemonBlocks.SHINY_STONE_ORE.get(), ItemGroup.BUILDING_BLOCKS) }
val SHINY_STONE_ORE = blockItem("shiny_stone_ore", CobblemonBlocks.SHINY_STONE_ORE)
@JvmField
val SUN_STONE_ORE = queue("sun_stone_ore") { blockItem(CobblemonBlocks.SUN_STONE_ORE.get(), ItemGroup.BUILDING_BLOCKS) }
val SUN_STONE_ORE = blockItem("sun_stone_ore", CobblemonBlocks.SUN_STONE_ORE)
@JvmField
val THUNDER_STONE_ORE = queue("thunder_stone_ore") { blockItem(CobblemonBlocks.THUNDER_STONE_ORE.get(), ItemGroup.BUILDING_BLOCKS) }
val THUNDER_STONE_ORE = blockItem("thunder_stone_ore", CobblemonBlocks.THUNDER_STONE_ORE)
@JvmField
val WATER_STONE_ORE = queue("water_stone_ore") { blockItem(CobblemonBlocks.WATER_STONE_ORE.get(), ItemGroup.BUILDING_BLOCKS) }
val WATER_STONE_ORE = blockItem("water_stone_ore", CobblemonBlocks.WATER_STONE_ORE)
@JvmField
val DEEPSLATE_DAWN_STONE_ORE = queue("deepslate_dawn_stone_ore") { blockItem(CobblemonBlocks.DEEPSLATE_DAWN_STONE_ORE.get(), ItemGroup.BUILDING_BLOCKS) }
val DEEPSLATE_DAWN_STONE_ORE = blockItem("deepslate_dawn_stone_ore", CobblemonBlocks.DEEPSLATE_DAWN_STONE_ORE)
@JvmField
val DEEPSLATE_DUSK_STONE_ORE = queue("deepslate_dusk_stone_ore") { blockItem(CobblemonBlocks.DEEPSLATE_DUSK_STONE_ORE.get(), ItemGroup.BUILDING_BLOCKS) }
val DEEPSLATE_DUSK_STONE_ORE = blockItem("deepslate_dusk_stone_ore", CobblemonBlocks.DEEPSLATE_DUSK_STONE_ORE)
@JvmField
val DEEPSLATE_FIRE_STONE_ORE = queue("deepslate_fire_stone_ore") { blockItem(CobblemonBlocks.DEEPSLATE_FIRE_STONE_ORE.get(), ItemGroup.BUILDING_BLOCKS) }
val DEEPSLATE_FIRE_STONE_ORE = blockItem("deepslate_fire_stone_ore", CobblemonBlocks.DEEPSLATE_FIRE_STONE_ORE)
@JvmField
val DEEPSLATE_ICE_STONE_ORE = queue("deepslate_ice_stone_ore") { blockItem(CobblemonBlocks.DEEPSLATE_ICE_STONE_ORE.get(), ItemGroup.BUILDING_BLOCKS) }
val DEEPSLATE_ICE_STONE_ORE = blockItem("deepslate_ice_stone_ore", CobblemonBlocks.DEEPSLATE_ICE_STONE_ORE)
@JvmField
val DEEPSLATE_LEAF_STONE_ORE = queue("deepslate_leaf_stone_ore") { blockItem(CobblemonBlocks.DEEPSLATE_LEAF_STONE_ORE.get(), ItemGroup.BUILDING_BLOCKS) }
val DEEPSLATE_LEAF_STONE_ORE = blockItem("deepslate_leaf_stone_ore", CobblemonBlocks.DEEPSLATE_LEAF_STONE_ORE)
@JvmField
val DEEPSLATE_MOON_STONE_ORE = queue("deepslate_moon_stone_ore") { blockItem(CobblemonBlocks.DEEPSLATE_MOON_STONE_ORE.get(), ItemGroup.BUILDING_BLOCKS) }
val DEEPSLATE_MOON_STONE_ORE = blockItem("deepslate_moon_stone_ore", CobblemonBlocks.DEEPSLATE_MOON_STONE_ORE)
@JvmField
val DEEPSLATE_SHINY_STONE_ORE = queue("deepslate_shiny_stone_ore") { blockItem(CobblemonBlocks.DEEPSLATE_SHINY_STONE_ORE.get(), ItemGroup.BUILDING_BLOCKS) }
val DEEPSLATE_SHINY_STONE_ORE = blockItem("deepslate_shiny_stone_ore", CobblemonBlocks.DEEPSLATE_SHINY_STONE_ORE)
@JvmField
val DEEPSLATE_SUN_STONE_ORE = queue("deepslate_sun_stone_ore") { blockItem(CobblemonBlocks.DEEPSLATE_SUN_STONE_ORE.get(), ItemGroup.BUILDING_BLOCKS) }
val DEEPSLATE_SUN_STONE_ORE = blockItem("deepslate_sun_stone_ore", CobblemonBlocks.DEEPSLATE_SUN_STONE_ORE)
@JvmField
val DEEPSLATE_THUNDER_STONE_ORE = queue("deepslate_thunder_stone_ore") { blockItem(CobblemonBlocks.DEEPSLATE_THUNDER_STONE_ORE.get(), ItemGroup.BUILDING_BLOCKS) }
val DEEPSLATE_THUNDER_STONE_ORE = blockItem("deepslate_thunder_stone_ore", CobblemonBlocks.DEEPSLATE_THUNDER_STONE_ORE)
@JvmField
val DEEPSLATE_WATER_STONE_ORE = queue("deepslate_water_stone_ore") { blockItem(CobblemonBlocks.DEEPSLATE_WATER_STONE_ORE.get(), ItemGroup.BUILDING_BLOCKS) }
val DEEPSLATE_WATER_STONE_ORE = blockItem("deepslate_water_stone_ore", CobblemonBlocks.DEEPSLATE_WATER_STONE_ORE)
@JvmField
val DRIPSTONE_MOON_STONE_ORE = queue("dripstone_moon_stone_ore") { blockItem(CobblemonBlocks.DRIPSTONE_MOON_STONE_ORE.get(), ItemGroup.BUILDING_BLOCKS) }
val DRIPSTONE_MOON_STONE_ORE = blockItem("dripstone_moon_stone_ore", CobblemonBlocks.DRIPSTONE_MOON_STONE_ORE)
@JvmField
val DAWN_STONE = this.evolutionItem("dawn_stone")
val DAWN_STONE = noSettingsItem("dawn_stone")
@JvmField
val DUSK_STONE = this.evolutionItem("dusk_stone")
val DUSK_STONE = noSettingsItem("dusk_stone")
@JvmField
val FIRE_STONE = this.evolutionItem("fire_stone")
val FIRE_STONE = noSettingsItem("fire_stone")
@JvmField
val ICE_STONE = this.evolutionItem("ice_stone")
val ICE_STONE = noSettingsItem("ice_stone")
@JvmField
val LEAF_STONE = this.evolutionItem("leaf_stone")
val LEAF_STONE = noSettingsItem("leaf_stone")
@JvmField
val MOON_STONE = this.evolutionItem("moon_stone")
val MOON_STONE = noSettingsItem("moon_stone")
@JvmField
val SHINY_STONE = this.evolutionItem("shiny_stone")
val SHINY_STONE = noSettingsItem("shiny_stone")
@JvmField
val SUN_STONE = this.evolutionItem("sun_stone")
val SUN_STONE = noSettingsItem("sun_stone")
@JvmField
val THUNDER_STONE = this.evolutionItem("thunder_stone")
val THUNDER_STONE = noSettingsItem("thunder_stone")
@JvmField
val WATER_STONE = this.evolutionItem("water_stone")
val WATER_STONE = noSettingsItem("water_stone")
// Held Items
@JvmField
val ASSAULT_VEST = this.heldItem("assault_vest")
val ASSAULT_VEST = heldItem("assault_vest")
@JvmField
val BIG_ROOT = this.heldItem("big_root")
val BIG_ROOT = blockItem("big_root", CobblemonBlocks.BIG_ROOT)
@JvmField
val BLACK_BELT = this.heldItem("black_belt")
val BLACK_BELT = heldItem("black_belt")
@JvmField
val BLACK_GLASSES = this.heldItem("black_glasses")
val BLACK_GLASSES = heldItem("black_glasses")
@JvmField
val BLACK_SLUDGE = this.heldItem("black_sludge")
val BLACK_SLUDGE = heldItem("black_sludge")
@JvmField
val CHARCOAL = this.heldItem("charcoal_stick", remappedName = "charcoal")
val CHARCOAL = heldItem("charcoal_stick", remappedName = "charcoal")
@JvmField
val CHOICE_BAND = this.heldItem("choice_band")
val CHOICE_BAND = heldItem("choice_band")
@JvmField
val CHOICE_SCARF = this.heldItem("choice_scarf")
val CHOICE_SCARF = heldItem("choice_scarf")
@JvmField
val CHOICE_SPECS = this.heldItem("choice_specs")
val CHOICE_SPECS = heldItem("choice_specs")
@JvmField
val DRAGON_FANG = this.heldItem("dragon_fang")
val DRAGON_FANG = heldItem("dragon_fang")
@JvmField
val EXP_SHARE = this.heldItem("exp_share")
val EXP_SHARE = heldItem("exp_share")
@JvmField
val FOCUS_BAND = this.heldItem("focus_band")
val FOCUS_BAND = heldItem("focus_band")
@JvmField
val HARD_STONE = this.heldItem("hard_stone")
val HARD_STONE = heldItem("hard_stone")
@JvmField
val HEAVY_DUTY_BOOTS = this.heldItem("heavy_duty_boots")
val HEAVY_DUTY_BOOTS = heldItem("heavy_duty_boots")
@JvmField
val LEFTOVERS = this.heldItem("leftovers")
val LEFTOVERS = heldItem("leftovers")
@JvmField
val LIGHT_CLAY = this.heldItem("light_clay")
val LIGHT_CLAY = heldItem("light_clay")
@JvmField
val LUCKY_EGG = this.heldItem("lucky_egg")
val LUCKY_EGG = heldItem("lucky_egg")
@JvmField
val MAGNET = this.heldItem("magnet")
val MAGNET = heldItem("magnet")
@JvmField
val MIRACLE_SEED = this.heldItem("miracle_seed")
val MIRACLE_SEED = heldItem("miracle_seed")
@JvmField
val MUSCLE_BAND = this.heldItem("muscle_band")
val MUSCLE_BAND = heldItem("muscle_band")
@JvmField
val MYSTIC_WATER = this.heldItem("mystic_water")
val MYSTIC_WATER = heldItem("mystic_water")
@JvmField
val NEVER_MELT_ICE = this.heldItem("never_melt_ice")
val NEVER_MELT_ICE = heldItem("never_melt_ice")
@JvmField
val POISON_BARB = this.heldItem("poison_barb")
val POISON_BARB = heldItem("poison_barb")
@JvmField
val QUICK_CLAW = this.heldItem("quick_claw")
val QUICK_CLAW = heldItem("quick_claw")
@JvmField
val ROCKY_HELMET = this.heldItem("rocky_helmet")
val ROCKY_HELMET = heldItem("rocky_helmet")
@JvmField
val SAFETY_GOGGLES = this.heldItem("safety_goggles")
val SAFETY_GOGGLES = heldItem("safety_goggles")
@JvmField
val SHARP_BEAK = this.heldItem("sharp_beak")
val SHARP_BEAK = heldItem("sharp_beak")
@JvmField
val SILK_SCARF = this.heldItem("silk_scarf")
val SILK_SCARF = heldItem("silk_scarf")
@JvmField
val SILVER_POWDER = this.heldItem("silver_powder")
val SILVER_POWDER = heldItem("silver_powder")
@JvmField
val SOFT_SAND = this.heldItem("soft_sand")
val SOFT_SAND = heldItem("soft_sand")
@JvmField
val SPELL_TAG = this.heldItem("spell_tag")
val SPELL_TAG = heldItem("spell_tag")
@JvmField
val TWISTED_SPOON = this.heldItem("twisted_spoon")
val TWISTED_SPOON = heldItem("twisted_spoon")
@JvmField
val WISE_GLASSES = this.heldItem("wise_glasses")
val WISE_GLASSES = heldItem("wise_glasses")
@JvmField
val MENTAL_HERB = heldItem("mental_herb")
@JvmField
val MIRROR_HERB = heldItem("mirror_herb")
@JvmField
val POWER_HERB = heldItem("power_herb")
@JvmField
val WHITE_HERB = heldItem("white_herb")
@JvmField
val BRIGHT_POWDER = heldItem("bright_powder")
@JvmField
val METAL_POWDER = heldItem("metal_powder")
@JvmField
val QUICK_POWDER = heldItem("quick_powder")
@JvmField
val DESTINY_KNOT = heldItem("destiny_knot")
@JvmField
val EVERSTONE = heldItem("everstone")
// Mulch
@JvmField
val MULCH_BASE = noSettingsItem("mulch_base")
@JvmField
val COARSE_MULCH = mulchItem("coarse_mulch", MulchVariant.COARSE)
@JvmField
val GROWTH_MULCH = mulchItem("growth_mulch", MulchVariant.GROWTH)
@JvmField
val HUMID_MULCH = mulchItem("humid_mulch", MulchVariant.HUMID)
@JvmField
val LOAMY_MULCH = mulchItem("loamy_mulch", MulchVariant.LOAMY)
@JvmField
val PEAT_MULCH = mulchItem("peat_mulch", MulchVariant.PEAT)
@JvmField
val RICH_MULCH = mulchItem("rich_mulch", MulchVariant.RICH)
@JvmField
val SANDY_MULCH = mulchItem("sandy_mulch", MulchVariant.SANDY)
@JvmField
val SURPRISE_MULCH = mulchItem("surprise_mulch", MulchVariant.SURPRISE)
// Misc
@JvmField
val POKEMON_MODEL = queue("pokemon_model") { PokemonItem() }
val POKEMON_MODEL = this.create("pokemon_model", PokemonItem())
fun pokeballs(): List<RegistrySupplier<PokeBallItem>> = this.pokeballs
private fun blockItem(name: String, block: Block): BlockItem = this.create(name, BlockItem(block, Item.Settings()))
private fun blockItem(block: Block, tab: ItemGroup) : BlockItem {
return BlockItem(block, Item.Settings().group(tab))
private fun noSettingsItem(name: String): CobblemonItem = this.create(name, CobblemonItem(Item.Settings()))
private fun mulchItem(name: String, mulchVariant: MulchVariant): MulchItem = this.create(name, MulchItem(mulchVariant))
private fun pokeBallItem(pokeBall: PokeBall): PokeBallItem {
val item = create(pokeBall.name.path, PokeBallItem(pokeBall))
pokeBall.item = item
pokeBalls.add(item)
return item
}
private fun itemNameBlockItem(block: Block, tab: ItemGroup) : BlockItem {
return AliasedBlockItem(block, Item.Settings().group(tab))
}
private fun candyItem(name: String, calculator: CandyItem.Calculator): CandyItem = this.create(name, CandyItem(calculator))
private fun evolutionItem(name: String) = queue(name) { CobblemonItem(Item.Settings().group(CobblemonItemGroups.EVOLUTION_ITEM_GROUP)) }
private fun pokeballItem(pokeBall: PokeBall): RegistrySupplier<PokeBallItem> {
val supplier = this.queue(pokeBall.name.path) { PokeBallItem(pokeBall) }
pokeBall.itemSupplier = supplier
this.pokeballs.add(supplier)
return supplier
}
private fun heldItem(name: String, remappedName: String? = null): RegistrySupplier<CobblemonItem> = queue(name) {
val item = CobblemonItem(Item.Settings().group(CobblemonItemGroups.HELD_ITEM_GROUP))
if (remappedName != null) {
CobblemonHeldItemManager.registerRemap(item, remappedName)
private fun heldItem(name: String, remappedName: String? = null): CobblemonItem = create(
name,
CobblemonItem(Item.Settings()).also {
if (remappedName != null) {
CobblemonHeldItemManager.registerRemap(it, remappedName)
}
}
return@queue item
}
)
}
@@ -0,0 +1,40 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common
import com.bedrockk.molang.Expression
import com.cobblemon.mod.common.api.data.DataRegistry
import com.cobblemon.mod.common.api.reactive.SimpleObservable
import com.cobblemon.mod.common.mechanics.RemediesMechanic
import com.cobblemon.mod.common.util.adapters.ExpressionAdapter
import com.cobblemon.mod.common.util.cobblemonResource
import com.google.gson.GsonBuilder
import net.minecraft.resource.ResourceManager
import net.minecraft.resource.ResourceType
import net.minecraft.server.network.ServerPlayerEntity
import net.minecraft.util.Identifier
object CobblemonMechanics : DataRegistry {
override val id: Identifier = cobblemonResource("mechanics")
override val type = ResourceType.SERVER_DATA
override val observable = SimpleObservable<CobblemonMechanics>()
val gson = GsonBuilder()
.setPrettyPrinting()
.registerTypeAdapter(Expression::class.java, ExpressionAdapter)
.create()
var remedies = RemediesMechanic()
override fun sync(player: ServerPlayerEntity) {}
override fun reload(manager: ResourceManager) {
manager.getResourceOrThrow(cobblemonResource("mechanics/remedies.json")).inputStream.use {
remedies = gson.fromJson(it.reader(), RemediesMechanic::class.java)
}
}
}
@@ -8,35 +8,72 @@
package com.cobblemon.mod.common
import com.cobblemon.mod.common.net.messages.client.battle.BattlePersistentStatusPacket
import com.cobblemon.mod.common.api.events.CobblemonEvents
import com.cobblemon.mod.common.api.events.net.MessageBuiltEvent
import com.cobblemon.mod.common.api.net.ClientNetworkPacketHandler
import com.cobblemon.mod.common.api.net.NetworkPacket
import com.cobblemon.mod.common.net.PacketHandler
import com.cobblemon.mod.common.net.messages.client.battle.BattleApplyCaptureResponsePacket
import com.cobblemon.mod.common.net.messages.client.battle.BattleCaptureEndPacket
import com.cobblemon.mod.common.net.messages.client.battle.BattleCaptureShakePacket
import com.cobblemon.mod.common.net.messages.client.battle.BattleCaptureStartPacket
import com.cobblemon.mod.common.net.messages.client.battle.BattleEndPacket
import com.cobblemon.mod.common.net.messages.client.battle.BattleFaintPacket
import com.cobblemon.mod.common.net.messages.client.battle.BattleHealthChangePacket
import com.cobblemon.mod.common.net.messages.client.battle.BattleInitializePacket
import com.cobblemon.mod.common.net.messages.client.battle.BattleMakeChoicePacket
import com.cobblemon.mod.common.net.messages.client.battle.BattleMessagePacket
import com.cobblemon.mod.common.net.messages.client.battle.BattleQueueRequestPacket
import com.cobblemon.mod.common.net.messages.client.battle.BattleSetTeamPokemonPacket
import com.cobblemon.mod.common.net.messages.client.battle.BattleSwitchPokemonPacket
import com.cobblemon.mod.common.net.messages.client.battle.BattleUpdateTeamPokemonPacket
import com.cobblemon.mod.common.net.messages.client.battle.ChallengeNotificationPacket
import com.cobblemon.mod.common.net.messages.client.data.*
import com.cobblemon.mod.common.api.net.ServerNetworkPacketHandler
import com.cobblemon.mod.common.client.net.SetClientPlayerDataHandler
import com.cobblemon.mod.common.client.net.battle.*
import com.cobblemon.mod.common.client.net.data.DataRegistrySyncPacketHandler
import com.cobblemon.mod.common.client.net.data.UnlockReloadPacketHandler
import com.cobblemon.mod.common.client.net.effect.SpawnSnowstormParticleHandler
import com.cobblemon.mod.common.client.net.gui.InteractPokemonUIPacketHandler
import com.cobblemon.mod.common.client.net.gui.SummaryUIPacketHandler
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.pasture.ClosePastureHandler
import com.cobblemon.mod.common.client.net.pasture.OpenPastureHandler
import com.cobblemon.mod.common.client.net.pasture.PokemonPasturedHandler
import com.cobblemon.mod.common.client.net.pasture.PokemonUnpasturedHandler
import com.cobblemon.mod.common.client.net.pokemon.update.PokemonUpdatePacketHandler
import com.cobblemon.mod.common.client.net.settings.ServerSettingsPacketHandler
import com.cobblemon.mod.common.client.net.sound.PokemonCryHandler
import com.cobblemon.mod.common.client.net.sound.UnvalidatedPlaySoundS2CPacketHandler
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
import com.cobblemon.mod.common.client.net.storage.SwapClientPokemonHandler
import com.cobblemon.mod.common.client.net.storage.party.InitializePartyHandler
import com.cobblemon.mod.common.client.net.storage.party.MoveClientPartyPokemonHandler
import com.cobblemon.mod.common.client.net.storage.party.SetPartyPokemonHandler
import com.cobblemon.mod.common.client.net.storage.party.SetPartyReferenceHandler
import com.cobblemon.mod.common.client.net.storage.pc.ClosePCHandler
import com.cobblemon.mod.common.client.net.storage.pc.InitializePCHandler
import com.cobblemon.mod.common.client.net.storage.pc.MoveClientPCPokemonHandler
import com.cobblemon.mod.common.client.net.storage.pc.OpenPCHandler
import com.cobblemon.mod.common.client.net.storage.pc.SetPCBoxPokemonHandler
import com.cobblemon.mod.common.client.net.storage.pc.SetPCPokemonHandler
import com.cobblemon.mod.common.client.net.toast.ToastPacketHandler
import com.cobblemon.mod.common.client.net.trade.TradeAcceptanceChangedHandler
import com.cobblemon.mod.common.client.net.trade.TradeCancelledHandler
import com.cobblemon.mod.common.client.net.trade.TradeCompletedHandler
import com.cobblemon.mod.common.client.net.trade.TradeOfferExpiredHandler
import com.cobblemon.mod.common.client.net.trade.TradeOfferNotificationHandler
import com.cobblemon.mod.common.client.net.trade.TradeStartedHandler
import com.cobblemon.mod.common.client.net.trade.TradeUpdatedHandler
import com.cobblemon.mod.common.net.messages.client.battle.*
import com.cobblemon.mod.common.net.messages.client.callback.OpenMoveCallbackPacket
import com.cobblemon.mod.common.net.messages.client.callback.OpenPartyCallbackPacket
import com.cobblemon.mod.common.net.messages.client.callback.OpenPartyMoveCallbackPacket
import com.cobblemon.mod.common.net.messages.client.data.AbilityRegistrySyncPacket
import com.cobblemon.mod.common.net.messages.client.data.MovesRegistrySyncPacket
import com.cobblemon.mod.common.net.messages.client.data.PropertiesCompletionRegistrySyncPacket
import com.cobblemon.mod.common.net.messages.client.data.SpeciesRegistrySyncPacket
import com.cobblemon.mod.common.net.messages.client.data.UnlockReloadPacket
import com.cobblemon.mod.common.net.messages.client.effect.SpawnSnowstormParticlePacket
import com.cobblemon.mod.common.net.messages.client.pasture.ClosePasturePacket
import com.cobblemon.mod.common.net.messages.client.pasture.OpenPasturePacket
import com.cobblemon.mod.common.net.messages.client.pasture.PokemonPasturedPacket
import com.cobblemon.mod.common.net.messages.client.pasture.PokemonUnpasturedPacket
import com.cobblemon.mod.common.net.messages.client.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.RemoveEvolutionPacket
import com.cobblemon.mod.common.net.messages.client.settings.ServerSettingsPacket
import com.cobblemon.mod.common.net.messages.client.sound.PokemonCryPacket
import com.cobblemon.mod.common.net.messages.client.sound.UnvalidatedPlaySoundS2CPacket
import com.cobblemon.mod.common.net.messages.client.spawn.SpawnPokeballPacket
import com.cobblemon.mod.common.net.messages.client.spawn.SpawnPokemonPacket
import com.cobblemon.mod.common.net.messages.client.starter.OpenStarterUIPacket
import com.cobblemon.mod.common.net.messages.client.starter.SetClientPlayerDataPacket
import com.cobblemon.mod.common.net.messages.client.storage.RemoveClientPokemonPacket
@@ -51,6 +88,14 @@ import com.cobblemon.mod.common.net.messages.client.storage.pc.MoveClientPCPokem
import com.cobblemon.mod.common.net.messages.client.storage.pc.OpenPCPacket
import com.cobblemon.mod.common.net.messages.client.storage.pc.SetPCBoxPokemonPacket
import com.cobblemon.mod.common.net.messages.client.storage.pc.SetPCPokemonPacket
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
import com.cobblemon.mod.common.net.messages.client.trade.TradeCompletedPacket
import com.cobblemon.mod.common.net.messages.client.trade.TradeOfferExpiredPacket
import com.cobblemon.mod.common.net.messages.client.trade.TradeOfferNotificationPacket
import com.cobblemon.mod.common.net.messages.client.trade.TradeStartedPacket
import com.cobblemon.mod.common.net.messages.client.trade.TradeUpdatedPacket
import com.cobblemon.mod.common.net.messages.client.ui.InteractPokemonUIPacket
import com.cobblemon.mod.common.net.messages.client.ui.SummaryUIPacket
import com.cobblemon.mod.common.net.messages.server.BattleChallengePacket
@@ -59,195 +104,306 @@ import com.cobblemon.mod.common.net.messages.server.RequestMoveSwapPacket
import com.cobblemon.mod.common.net.messages.server.SelectStarterPacket
import com.cobblemon.mod.common.net.messages.server.SendOutPokemonPacket
import com.cobblemon.mod.common.net.messages.server.battle.BattleSelectActionsPacket
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
import com.cobblemon.mod.common.net.messages.server.callback.party.PartySelectCancelledPacket
import com.cobblemon.mod.common.net.messages.server.callback.partymove.PartyMoveSelectCancelledPacket
import com.cobblemon.mod.common.net.messages.server.callback.partymove.PartyPokemonMoveSelectedPacket
import com.cobblemon.mod.common.net.messages.server.pasture.PasturePokemonPacket
import com.cobblemon.mod.common.net.messages.server.pasture.UnpastureAllPokemonPacket
import com.cobblemon.mod.common.net.messages.server.pasture.UnpasturePokemonPacket
import com.cobblemon.mod.common.net.messages.server.pokemon.interact.InteractPokemonPacket
import com.cobblemon.mod.common.net.messages.server.pokemon.update.SetNicknamePacket
import com.cobblemon.mod.common.net.messages.server.pokemon.update.evolution.AcceptEvolutionPacket
import com.cobblemon.mod.common.net.messages.server.starter.RequestStarterScreenPacket
import com.cobblemon.mod.common.net.messages.server.storage.SwapPCPartyPokemonPacket
import com.cobblemon.mod.common.net.messages.server.storage.party.MovePartyPokemonPacket
import com.cobblemon.mod.common.net.messages.server.storage.party.ReleasePartyPokemonPacket
import com.cobblemon.mod.common.net.messages.server.storage.party.SwapPartyPokemonPacket
import com.cobblemon.mod.common.net.messages.server.storage.pc.*
import com.cobblemon.mod.common.util.getServer
import java.util.concurrent.CompletableFuture
import com.cobblemon.mod.common.net.messages.server.storage.pc.MovePCPokemonPacket
import com.cobblemon.mod.common.net.messages.server.storage.pc.MovePCPokemonToPartyPacket
import com.cobblemon.mod.common.net.messages.server.storage.pc.MovePartyPokemonToPCPacket
import com.cobblemon.mod.common.net.messages.server.storage.pc.ReleasePCPokemonPacket
import com.cobblemon.mod.common.net.messages.server.storage.pc.SwapPCPokemonPacket
import com.cobblemon.mod.common.net.messages.server.storage.pc.UnlinkPlayerFromPCPacket
import com.cobblemon.mod.common.net.messages.server.trade.AcceptTradeRequestPacket
import com.cobblemon.mod.common.net.messages.server.trade.CancelTradePacket
import com.cobblemon.mod.common.net.messages.server.trade.ChangeTradeAcceptancePacket
import com.cobblemon.mod.common.net.messages.server.trade.OfferTradePacket
import com.cobblemon.mod.common.net.messages.server.trade.UpdateTradeOfferPacket
import com.cobblemon.mod.common.net.serverhandling.ChallengeHandler
import com.cobblemon.mod.common.net.serverhandling.battle.BattleSelectActionsHandler
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
import com.cobblemon.mod.common.net.serverhandling.callback.party.PartySelectCancelledHandler
import com.cobblemon.mod.common.net.serverhandling.callback.partymove.PartyMoveSelectCancelledHandler
import com.cobblemon.mod.common.net.serverhandling.callback.partymove.PartyPokemonMoveSelectedHandler
import com.cobblemon.mod.common.net.serverhandling.evolution.AcceptEvolutionHandler
import com.cobblemon.mod.common.net.serverhandling.pasture.PasturePokemonHandler
import com.cobblemon.mod.common.net.serverhandling.pasture.UnpastureAllPokemonHandler
import com.cobblemon.mod.common.net.serverhandling.pasture.UnpasturePokemonHandler
import com.cobblemon.mod.common.net.serverhandling.pokemon.interact.InteractPokemonHandler
import com.cobblemon.mod.common.net.serverhandling.pokemon.update.SetNicknameHandler
import com.cobblemon.mod.common.net.serverhandling.starter.RequestStarterScreenHandler
import com.cobblemon.mod.common.net.serverhandling.starter.SelectStarterPacketHandler
import com.cobblemon.mod.common.net.serverhandling.storage.BenchMoveHandler
import com.cobblemon.mod.common.net.serverhandling.storage.RequestMoveSwapHandler
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.ReleasePCPokemonHandler
import com.cobblemon.mod.common.net.serverhandling.storage.party.SwapPartyPokemonHandler
import com.cobblemon.mod.common.net.serverhandling.storage.pc.MovePCPokemonHandler
import com.cobblemon.mod.common.net.serverhandling.storage.pc.MovePCPokemonToPartyHandler
import com.cobblemon.mod.common.net.serverhandling.storage.pc.MovePartyPokemonToPCHandler
import com.cobblemon.mod.common.net.serverhandling.storage.pc.ReleasePartyPokemonHandler
import com.cobblemon.mod.common.net.serverhandling.storage.pc.SwapPCPokemonHandler
import com.cobblemon.mod.common.net.serverhandling.storage.pc.UnlinkPlayerFromPCHandler
import com.cobblemon.mod.common.net.serverhandling.trade.AcceptTradeRequestHandler
import com.cobblemon.mod.common.net.serverhandling.trade.CancelTradeHandler
import com.cobblemon.mod.common.net.serverhandling.trade.ChangeTradeAcceptanceHandler
import com.cobblemon.mod.common.net.serverhandling.trade.OfferTradeHandler
import com.cobblemon.mod.common.net.serverhandling.trade.UpdateTradeOfferHandler
import com.cobblemon.mod.common.util.server
import kotlin.reflect.KClass
import net.minecraft.network.PacketByteBuf
import net.minecraft.network.listener.ClientPlayPacketListener
import net.minecraft.network.packet.Packet
import net.minecraft.server.network.ServerPlayerEntity
import net.minecraft.util.Identifier
/**
* Registers Cobblemon packets. Packet handlers are set up on handling the [MessageBuiltEvent] dispatched from here.
* Registers Cobblemon network packets.
*
* This class also contains short functions for dispatching our packets to a player, all players, or to the entire server.
*
* @author Hiroku
* @author Hiroku, Licious
* @since November 27th, 2021
*/
object CobblemonNetwork {
const val PROTOCOL_VERSION = "1"
object CobblemonNetwork : NetworkManager {
var clientHandlersRegistered = CompletableFuture<Unit>()
var serverHandlersRegistered = CompletableFuture<Unit>()
init {
clientHandlersRegistered.runAfterBoth(serverHandlersRegistered) { register() }
}
lateinit var networkDelegate: NetworkDelegate
fun ServerPlayerEntity.sendPacket(packet: NetworkPacket) = sendToPlayer(this, packet)
fun sendToPlayer(player: ServerPlayerEntity, packet: NetworkPacket) = networkDelegate.sendPacketToPlayer(player, packet)
fun sendToServer(packet: NetworkPacket) = networkDelegate.sendPacketToServer(packet)
fun sendToAllPlayers(packet: NetworkPacket) = sendToPlayers(getServer()!!.playerManager.playerList, packet)
fun sendToPlayers(players: Iterable<ServerPlayerEntity>, packet: NetworkPacket) = players.forEach { sendToPlayer(it, packet) }
interface PreparedMessage<T : NetworkPacket> {
fun registerMessage()
fun registerHandler(handler: PacketHandler<T>)
}
interface NetworkContext {
val player: ServerPlayerEntity?
}
fun register() {
// Don't forget to register handlers in either ClientPacketRegistrar or ServerPacketRegistrar!
/**
* Client Packets
*/
fun ServerPlayerEntity.sendPacket(packet: NetworkPacket<*>) = sendPacketToPlayer(this, packet)
fun sendToServer(packet: NetworkPacket<*>) = this.sendPacketToServer(packet)
fun sendToAllPlayers(packet: NetworkPacket<*>) = sendPacketToPlayers(server()!!.playerManager.playerList, packet)
fun sendPacketToPlayers(players: Iterable<ServerPlayerEntity>, packet: NetworkPacket<*>) = players.forEach { sendPacketToPlayer(it, packet) }
override fun registerClientBound() {
// Pokemon Update Packets
buildClientMessage<FriendshipUpdatePacket>()
buildClientMessage<MoveSetUpdatePacket>()
buildClientMessage<NatureUpdatePacket>()
buildClientMessage<ShinyUpdatePacket>()
buildClientMessage<SpeciesUpdatePacket>()
buildClientMessage<HealthUpdatePacket>()
buildClientMessage<ExperienceUpdatePacket>()
buildClientMessage<StatusUpdatePacket>()
buildClientMessage<CaughtBallUpdatePacket>()
buildClientMessage<BenchedMovesUpdatePacket>()
buildClientMessage<GenderUpdatePacket>()
buildClientMessage<AspectsUpdatePacket>()
buildClientMessage<AbilityUpdatePacket>()
buildClientMessage<EVsUpdatePacket>()
buildClientMessage<IVsUpdatePacket>()
buildClientMessage<HeldItemUpdatePacket>()
this.createClientBound(FriendshipUpdatePacket.ID, FriendshipUpdatePacket::decode, PokemonUpdatePacketHandler())
this.createClientBound(MoveSetUpdatePacket.ID, MoveSetUpdatePacket::decode, PokemonUpdatePacketHandler())
this.createClientBound(NatureUpdatePacket.ID, NatureUpdatePacket::decode, PokemonUpdatePacketHandler())
this.createClientBound(ShinyUpdatePacket.ID, ShinyUpdatePacket::decode, PokemonUpdatePacketHandler())
this.createClientBound(SpeciesUpdatePacket.ID, SpeciesUpdatePacket::decode, PokemonUpdatePacketHandler())
this.createClientBound(NicknameUpdatePacket.ID, NicknameUpdatePacket::decode, PokemonUpdatePacketHandler())
this.createClientBound(HealthUpdatePacket.ID, HealthUpdatePacket::decode, PokemonUpdatePacketHandler())
this.createClientBound(ExperienceUpdatePacket.ID, ExperienceUpdatePacket::decode, PokemonUpdatePacketHandler())
this.createClientBound(StatusUpdatePacket.ID, StatusUpdatePacket::decode, PokemonUpdatePacketHandler())
this.createClientBound(CaughtBallUpdatePacket.ID, CaughtBallUpdatePacket::decode, PokemonUpdatePacketHandler())
this.createClientBound(BenchedMovesUpdatePacket.ID, BenchedMovesUpdatePacket::decode, PokemonUpdatePacketHandler())
this.createClientBound(GenderUpdatePacket.ID, GenderUpdatePacket::decode, PokemonUpdatePacketHandler())
this.createClientBound(AspectsUpdatePacket.ID, AspectsUpdatePacket::decode, PokemonUpdatePacketHandler())
this.createClientBound(AbilityUpdatePacket.ID, AbilityUpdatePacket::decode, PokemonUpdatePacketHandler())
this.createClientBound(EVsUpdatePacket.ID, EVsUpdatePacket::decode, PokemonUpdatePacketHandler())
this.createClientBound(IVsUpdatePacket.ID, IVsUpdatePacket::decode, PokemonUpdatePacketHandler())
this.createClientBound(HeldItemUpdatePacket.ID, HeldItemUpdatePacket::decode, PokemonUpdatePacketHandler())
this.createClientBound(PokemonStateUpdatePacket.ID, PokemonStateUpdatePacket::decode, PokemonUpdatePacketHandler())
this.createClientBound(TetheringUpdatePacket.ID, TetheringUpdatePacket::decode, PokemonUpdatePacketHandler())
// Evolution start
buildClientMessage<AddEvolutionPacket>()
buildClientMessage<ClearEvolutionsPacket>()
buildClientMessage<RemoveEvolutionPacket>()
this.createClientBound(AddEvolutionPacket.ID, AddEvolutionPacket::decode, PokemonUpdatePacketHandler())
this.createClientBound(ClearEvolutionsPacket.ID, ClearEvolutionsPacket::decode, PokemonUpdatePacketHandler())
this.createClientBound(RemoveEvolutionPacket.ID, RemoveEvolutionPacket::decode, PokemonUpdatePacketHandler())
// Evolution End
buildClientMessage<PokemonStateUpdatePacket>()
// Storage Packets
buildClientMessage<InitializePartyPacket>()
buildClientMessage<SetPartyPokemonPacket>()
buildClientMessage<MoveClientPartyPokemonPacket>()
buildClientMessage<SetPartyReferencePacket>()
this.createClientBound(InitializePartyPacket.ID, InitializePartyPacket::decode, InitializePartyHandler)
this.createClientBound(SetPartyPokemonPacket.ID, SetPartyPokemonPacket::decode, SetPartyPokemonHandler)
this.createClientBound(MoveClientPartyPokemonPacket.ID, MoveClientPartyPokemonPacket::decode, MoveClientPartyPokemonHandler)
this.createClientBound(SetPartyReferencePacket.ID, SetPartyReferencePacket::decode, SetPartyReferenceHandler)
buildClientMessage<InitializePCPacket>()
buildClientMessage<MoveClientPCPokemonPacket>()
buildClientMessage<SetPCBoxPokemonPacket>()
buildClientMessage<SetPCPokemonPacket>()
buildClientMessage<OpenPCPacket>()
buildClientMessage<ClosePCPacket>()
this.createClientBound(InitializePCPacket.ID, InitializePCPacket::decode, InitializePCHandler)
this.createClientBound(MoveClientPCPokemonPacket.ID, MoveClientPCPokemonPacket::decode, MoveClientPCPokemonHandler)
this.createClientBound(SetPCBoxPokemonPacket.ID, SetPCBoxPokemonPacket::decode, SetPCBoxPokemonHandler)
this.createClientBound(SetPCPokemonPacket.ID, SetPCPokemonPacket::decode, SetPCPokemonHandler)
this.createClientBound(OpenPCPacket.ID, OpenPCPacket::decode, OpenPCHandler)
this.createClientBound(ClosePCPacket.ID, ClosePCPacket::decode, ClosePCHandler)
buildClientMessage<SwapClientPokemonPacket>()
buildClientMessage<RemoveClientPokemonPacket>()
this.createClientBound(SwapClientPokemonPacket.ID, SwapClientPokemonPacket::decode, SwapClientPokemonHandler)
this.createClientBound(RemoveClientPokemonPacket.ID, RemoveClientPokemonPacket::decode, RemoveClientPokemonHandler)
// UI Packets
buildClientMessage<SummaryUIPacket>()
buildClientMessage<InteractPokemonUIPacket>()
this.createClientBound(SummaryUIPacket.ID, SummaryUIPacket::decode, SummaryUIPacketHandler)
this.createClientBound(InteractPokemonUIPacket.ID, InteractPokemonUIPacket::decode, InteractPokemonUIPacketHandler)
// Starter packets
buildClientMessage<OpenStarterUIPacket>()
buildClientMessage<SetClientPlayerDataPacket>()
this.createClientBound(OpenStarterUIPacket.ID, OpenStarterUIPacket::decode, StarterUIPacketHandler)
this.createClientBound(SetClientPlayerDataPacket.ID, SetClientPlayerDataPacket::decode, SetClientPlayerDataHandler)
// Battle packets
buildClientMessage<BattleEndPacket>()
buildClientMessage<BattleInitializePacket>()
buildClientMessage<BattleQueueRequestPacket>()
buildClientMessage<BattleFaintPacket>()
buildClientMessage<BattleMakeChoicePacket>()
buildClientMessage<BattleHealthChangePacket>()
buildClientMessage<BattleSetTeamPokemonPacket>()
buildClientMessage<BattleSwitchPokemonPacket>()
buildClientMessage<BattleMessagePacket>()
buildClientMessage<BattleCaptureStartPacket>()
buildClientMessage<BattleCaptureEndPacket>()
buildClientMessage<BattleCaptureShakePacket>()
buildClientMessage<BattleApplyCaptureResponsePacket>()
buildClientMessage<ChallengeNotificationPacket>()
buildClientMessage<BattleUpdateTeamPokemonPacket>()
buildClientMessage<BattlePersistentStatusPacket>()
this.createClientBound(BattleEndPacket.ID, BattleEndPacket::decode, BattleEndHandler)
this.createClientBound(BattleInitializePacket.ID, BattleInitializePacket::decode, BattleInitializeHandler)
this.createClientBound(BattleQueueRequestPacket.ID, BattleQueueRequestPacket::decode, BattleQueueRequestHandler)
this.createClientBound(BattleFaintPacket.ID, BattleFaintPacket::decode, BattleFaintHandler)
this.createClientBound(BattleMakeChoicePacket.ID, BattleMakeChoicePacket::decode, BattleMakeChoiceHandler)
this.createClientBound(BattleHealthChangePacket.ID, BattleHealthChangePacket::decode, BattleHealthChangeHandler)
this.createClientBound(BattleSetTeamPokemonPacket.ID, BattleSetTeamPokemonPacket::decode, BattleSetTeamPokemonHandler)
this.createClientBound(BattleSwitchPokemonPacket.ID, BattleSwitchPokemonPacket::decode, BattleSwitchPokemonHandler)
this.createClientBound(BattleMessagePacket.ID, BattleMessagePacket::decode, BattleMessageHandler)
this.createClientBound(BattleCaptureStartPacket.ID, BattleCaptureStartPacket::decode, BattleCaptureStartHandler)
this.createClientBound(BattleCaptureEndPacket.ID, BattleCaptureEndPacket::decode, BattleCaptureEndHandler)
this.createClientBound(BattleCaptureShakePacket.ID, BattleCaptureShakePacket::decode, BattleCaptureShakeHandler)
this.createClientBound(BattleApplyPassResponsePacket.ID, BattleApplyPassResponsePacket::decode, BattleApplyPassResponseHandler)
this.createClientBound(BattleChallengeNotificationPacket.ID, BattleChallengeNotificationPacket::decode, BattleChallengeNotificationHandler)
this.createClientBound(BattleUpdateTeamPokemonPacket.ID, BattleUpdateTeamPokemonPacket::decode, BattleUpdateTeamPokemonHandler)
this.createClientBound(BattlePersistentStatusPacket.ID, BattlePersistentStatusPacket::decode, BattlePersistentStatusHandler)
this.createClientBound(BattleMadeInvalidChoicePacket.ID, BattleMadeInvalidChoicePacket::decode, BattleMadeInvalidChoiceHandler)
this.createClientBound(BattleMusicPacket.ID, BattleMusicPacket::decode, BattleMusicHandler)
this.createClientBound(BattleChallengeExpiredPacket.ID, BattleChallengeExpiredPacket::decode, BattleChallengeExpiredHandler)
// Settings packets
buildClientMessage<ServerSettingsPacket>()
this.createClientBound(ServerSettingsPacket.ID, ServerSettingsPacket::decode, ServerSettingsPacketHandler)
// Data registries
buildClientMessage<UnlockReloadPacket>()
buildClientMessage<AbilityRegistrySyncPacket>()
buildClientMessage<MovesRegistrySyncPacket>()
buildClientMessage<SpeciesRegistrySyncPacket>()
buildClientMessage<PropertiesCompletionRegistrySyncPacket>()
this.createClientBound(AbilityRegistrySyncPacket.ID, AbilityRegistrySyncPacket::decode, DataRegistrySyncPacketHandler())
this.createClientBound(MovesRegistrySyncPacket.ID, MovesRegistrySyncPacket::decode, DataRegistrySyncPacketHandler())
this.createClientBound(SpeciesRegistrySyncPacket.ID, SpeciesRegistrySyncPacket::decode, DataRegistrySyncPacketHandler())
this.createClientBound(PropertiesCompletionRegistrySyncPacket.ID, PropertiesCompletionRegistrySyncPacket::decode, DataRegistrySyncPacketHandler())
this.createClientBound(UnlockReloadPacket.ID, UnlockReloadPacket::decode, UnlockReloadPacketHandler)
// Effects
buildClientMessage<SpawnSnowstormParticlePacket>()
this.createClientBound(SpawnSnowstormParticlePacket.ID, SpawnSnowstormParticlePacket::decode, SpawnSnowstormParticleHandler)
// Hax
buildClientMessage<UnvalidatedPlaySoundS2CPacket>()
this.createClientBound(UnvalidatedPlaySoundS2CPacket.ID, UnvalidatedPlaySoundS2CPacket::decode, UnvalidatedPlaySoundS2CPacketHandler)
this.createClientBound(SpawnPokemonPacket.ID, SpawnPokemonPacket::decode, SpawnExtraDataEntityHandler())
this.createClientBound(SpawnPokeballPacket.ID, SpawnPokeballPacket::decode, SpawnExtraDataEntityHandler())
this.createClientBound(ToastPacket.ID, ToastPacket::decode, ToastPacketHandler)
/**
* Server Packets
*/
// Trade packets
this.createClientBound(TradeAcceptanceChangedPacket.ID, TradeAcceptanceChangedPacket::decode, TradeAcceptanceChangedHandler)
this.createClientBound(TradeCancelledPacket.ID, TradeCancelledPacket::decode, TradeCancelledHandler)
this.createClientBound(TradeCompletedPacket.ID, TradeCompletedPacket::decode, TradeCompletedHandler)
this.createClientBound(TradeUpdatedPacket.ID, TradeUpdatedPacket::decode, TradeUpdatedHandler)
this.createClientBound(TradeOfferNotificationPacket.ID, TradeOfferNotificationPacket::decode, TradeOfferNotificationHandler)
this.createClientBound(TradeOfferExpiredPacket.ID, TradeOfferExpiredPacket::decode, TradeOfferExpiredHandler)
this.createClientBound(TradeStartedPacket.ID, TradeStartedPacket::decode, TradeStartedHandler)
// Pasture
this.createClientBound(OpenPasturePacket.ID, OpenPasturePacket::decode, OpenPastureHandler)
this.createClientBound(ClosePasturePacket.ID, ClosePasturePacket::decode, ClosePastureHandler)
this.createClientBound(PokemonPasturedPacket.ID, PokemonPasturedPacket::decode, PokemonPasturedHandler)
this.createClientBound(PokemonUnpasturedPacket.ID, PokemonUnpasturedPacket::decode, PokemonUnpasturedHandler)
// Behaviours
this.createClientBound(PokemonCryPacket.ID, PokemonCryPacket::decode, PokemonCryHandler)
// Move select packets
this.createClientBound(OpenMoveCallbackPacket.ID, OpenMoveCallbackPacket::decode, OpenMoveCallbackHandler)
// Party select packets
this.createClientBound(OpenPartyCallbackPacket.ID, OpenPartyCallbackPacket::decode, OpenPartyCallbackHandler)
// Party move select packets
this.createClientBound(OpenPartyMoveCallbackPacket.ID, OpenPartyMoveCallbackPacket::decode, OpenPartyMoveCallbackHandler)
}
override fun registerServerBound() {
// Pokemon Update Packets
// Evolution start
buildServerMessage<AcceptEvolutionPacket>()
// Evolution End
this.createServerBound(SetNicknamePacket.ID, SetNicknamePacket::decode, SetNicknameHandler)
// Evolution Packets
this.createServerBound(AcceptEvolutionPacket.ID, AcceptEvolutionPacket::decode, AcceptEvolutionHandler)
// Interaction Packets
buildServerMessage<InteractPokemonPacket>()
this.createServerBound(InteractPokemonPacket.ID, InteractPokemonPacket::decode, InteractPokemonHandler)
// Storage Packets
buildServerMessage<SendOutPokemonPacket>()
buildServerMessage<RequestMoveSwapPacket>()
buildServerMessage<BenchMovePacket>()
buildServerMessage<BattleChallengePacket>()
this.createServerBound(SendOutPokemonPacket.ID, SendOutPokemonPacket::decode, SendOutPokemonHandler)
this.createServerBound(RequestMoveSwapPacket.ID, RequestMoveSwapPacket::decode, RequestMoveSwapHandler)
this.createServerBound(BenchMovePacket.ID, BenchMovePacket::decode, BenchMoveHandler)
this.createServerBound(BattleChallengePacket.ID, BattleChallengePacket::decode, ChallengeHandler)
buildServerMessage<MovePCPokemonToPartyPacket>()
buildServerMessage<MovePartyPokemonToPCPacket>()
buildServerMessage<ReleasePartyPokemonPacket>()
buildServerMessage<ReleasePCPokemonPacket>()
buildServerMessage<UnlinkPlayerFromPCPacket>()
this.createServerBound(MovePCPokemonToPartyPacket.ID, MovePCPokemonToPartyPacket::decode, MovePCPokemonToPartyHandler)
this.createServerBound(MovePartyPokemonToPCPacket.ID, MovePartyPokemonToPCPacket::decode, MovePartyPokemonToPCHandler)
this.createServerBound(ReleasePartyPokemonPacket.ID, ReleasePartyPokemonPacket::decode, ReleasePartyPokemonHandler)
this.createServerBound(ReleasePCPokemonPacket.ID, ReleasePCPokemonPacket::decode, ReleasePCPokemonHandler)
this.createServerBound(UnlinkPlayerFromPCPacket.ID, UnlinkPlayerFromPCPacket::decode, UnlinkPlayerFromPCHandler)
// Starter packets
buildServerMessage<SelectStarterPacket>()
buildServerMessage<RequestStarterScreenPacket>()
this.createServerBound(SelectStarterPacket.ID, SelectStarterPacket::decode, SelectStarterPacketHandler)
this.createServerBound(RequestStarterScreenPacket.ID, RequestStarterScreenPacket::decode, RequestStarterScreenHandler)
buildServerMessage<SwapPCPokemonPacket>()
buildServerMessage<SwapPartyPokemonPacket>()
this.createServerBound(SwapPCPokemonPacket.ID, SwapPCPokemonPacket::decode, SwapPCPokemonHandler)
this.createServerBound(SwapPartyPokemonPacket.ID, SwapPartyPokemonPacket::decode, SwapPartyPokemonHandler)
buildServerMessage<MovePCPokemonPacket>()
buildServerMessage<MovePartyPokemonPacket>()
this.createServerBound(MovePCPokemonPacket.ID, MovePCPokemonPacket::decode, MovePCPokemonHandler)
this.createServerBound(MovePartyPokemonPacket.ID, MovePartyPokemonPacket::decode, MovePartyPokemonHandler)
buildServerMessage<SwapPCPartyPokemonPacket>()
this.createServerBound(SwapPCPartyPokemonPacket.ID, SwapPCPartyPokemonPacket::decode, SwapPCPartyPokemonHandler)
// Battle packets
buildServerMessage<BattleSelectActionsPacket>()
this.createServerBound(BattleSelectActionsPacket.ID, BattleSelectActionsPacket::decode, BattleSelectActionsHandler)
// Trade
this.createServerBound(AcceptTradeRequestPacket.ID, AcceptTradeRequestPacket::decode, AcceptTradeRequestHandler)
this.createServerBound(CancelTradePacket.ID, CancelTradePacket::decode, CancelTradeHandler)
this.createServerBound(ChangeTradeAcceptancePacket.ID, ChangeTradeAcceptancePacket::decode, ChangeTradeAcceptanceHandler)
this.createServerBound(OfferTradePacket.ID, OfferTradePacket::decode, OfferTradeHandler)
this.createServerBound(UpdateTradeOfferPacket.ID, UpdateTradeOfferPacket::decode, UpdateTradeOfferHandler)
// Pasture
this.createServerBound(PasturePokemonPacket.ID, PasturePokemonPacket::decode, PasturePokemonHandler)
this.createServerBound(UnpasturePokemonPacket.ID, UnpasturePokemonPacket::decode, UnpasturePokemonHandler)
this.createServerBound(UnpastureAllPokemonPacket.ID, UnpastureAllPokemonPacket::decode, UnpastureAllPokemonHandler)
// Move select packets
this.createServerBound(MoveSelectedPacket.ID, MoveSelectedPacket::decode, MoveSelectedHandler)
this.createServerBound(MoveSelectCancelledPacket.ID, MoveSelectCancelledPacket::decode, MoveSelectCancelledHandler)
// Party select packets
this.createServerBound(PartyPokemonSelectedPacket.ID, PartyPokemonSelectedPacket::decode, PartyPokemonSelectedHandler)
this.createServerBound(PartySelectCancelledPacket.ID, PartySelectCancelledPacket::decode, PartySelectCancelledHandler)
// Party move select packets
this.createServerBound(PartyPokemonMoveSelectedPacket.ID, PartyPokemonMoveSelectedPacket::decode, PartyPokemonMoveSelectedHandler)
this.createServerBound(PartyMoveSelectCancelledPacket.ID, PartyMoveSelectCancelledPacket::decode, PartyMoveSelectCancelledHandler)
}
private inline fun <reified P : NetworkPacket> buildClientMessage() =
buildMessage<P>(toServer = false)
private inline fun <reified P : NetworkPacket> buildServerMessage() =
buildMessage<P>(toServer = true)
private inline fun <reified P : NetworkPacket> buildMessage(toServer: Boolean) {
val message = networkDelegate.buildMessage(P::class.java, toServer)
// Gives client or server the chance to attach its packet handler
CobblemonEvents.MESSAGE_BUILT.post(MessageBuiltEvent(P::class.java, toServer, message))
message.registerMessage()
private inline fun <reified T : NetworkPacket<T>> createClientBound(identifier: Identifier, noinline decoder: (PacketByteBuf) -> T, handler: ClientNetworkPacketHandler<T>) {
Cobblemon.implementation.networkManager.createClientBound(identifier, T::class, { message, buffer -> message.encode(buffer) }, decoder, handler)
}
private inline fun <reified T : NetworkPacket<T>> createServerBound(identifier: Identifier, noinline decoder: (PacketByteBuf) -> T, handler: ServerNetworkPacketHandler<T>) {
Cobblemon.implementation.networkManager.createServerBound(identifier, T::class, { message, buffer -> message.encode(buffer) }, decoder, handler)
}
override fun <T : NetworkPacket<T>> createClientBound(
identifier: Identifier,
kClass: KClass<T>,
encoder: (T, PacketByteBuf) -> Unit,
decoder: (PacketByteBuf) -> T,
handler: ClientNetworkPacketHandler<T>
) {
Cobblemon.implementation.networkManager.createClientBound(identifier, kClass, encoder, decoder, handler)
}
override fun <T : NetworkPacket<T>> createServerBound(
identifier: Identifier,
kClass: KClass<T>,
encoder: (T, PacketByteBuf) -> Unit,
decoder: (PacketByteBuf) -> T,
handler: ServerNetworkPacketHandler<T>
) {
Cobblemon.implementation.networkManager.createServerBound(identifier, kClass, encoder, decoder, handler)
}
override fun sendPacketToPlayer(player: ServerPlayerEntity, packet: NetworkPacket<*>) = Cobblemon.implementation.networkManager.sendPacketToPlayer(player, packet)
override fun sendPacketToServer(packet: NetworkPacket<*>) = Cobblemon.implementation.networkManager.sendPacketToServer(packet)
override fun <T : NetworkPacket<*>> asVanillaClientBound(packet: T): Packet<ClientPlayPacketListener> = Cobblemon.implementation.networkManager.asVanillaClientBound(packet)
}
@@ -1,73 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common
import com.cobblemon.mod.common.util.cobblemonResource
import dev.architectury.registry.level.biome.BiomeModifications
import net.minecraft.util.registry.RegistryEntry
import net.minecraft.util.registry.RegistryEntryList
import net.minecraft.world.gen.GenerationStep
import net.minecraft.world.gen.feature.ConfiguredFeatures
import net.minecraft.world.gen.feature.Feature
import net.minecraft.world.gen.feature.PlacedFeature
import net.minecraft.world.gen.feature.PlacedFeatures
import net.minecraft.world.gen.feature.SimpleRandomFeatureConfig
import net.minecraft.world.gen.feature.VegetationPlacedFeatures
import net.minecraft.world.gen.placementmodifier.RarityFilterPlacementModifier
object CobblemonPlacements {
lateinit var BLACK_APRICORN_TREE: RegistryEntry<PlacedFeature>
lateinit var BLUE_APRICORN_TREE: RegistryEntry<PlacedFeature>
lateinit var GREEN_APRICORN_TREE: RegistryEntry<PlacedFeature>
lateinit var PINK_APRICORN_TREE: RegistryEntry<PlacedFeature>
lateinit var RED_APRICORN_TREE: RegistryEntry<PlacedFeature>
lateinit var WHITE_APRICORN_TREE: RegistryEntry<PlacedFeature>
lateinit var YELLOW_APRICORN_TREE: RegistryEntry<PlacedFeature>
lateinit var APRICORN_TREES: RegistryEntry<PlacedFeature>
fun register() {
BLACK_APRICORN_TREE = PlacedFeatures.register(cobblemonResource("black_apricorn_tree").toString(), CobblemonConfiguredFeatures.BLACK_APRICORN_TREE, PlacedFeatures.wouldSurvive(
CobblemonBlocks.BLACK_APRICORN_SAPLING.get()))
BLUE_APRICORN_TREE = PlacedFeatures.register(cobblemonResource("blue_apricorn_tree").toString(), CobblemonConfiguredFeatures.BLUE_APRICORN_TREE, PlacedFeatures.wouldSurvive(
CobblemonBlocks.BLUE_APRICORN_SAPLING.get()))
GREEN_APRICORN_TREE = PlacedFeatures.register(cobblemonResource("green_apricorn_tree").toString(), CobblemonConfiguredFeatures.GREEN_APRICORN_TREE, PlacedFeatures.wouldSurvive(
CobblemonBlocks.GREEN_APRICORN_SAPLING.get()))
PINK_APRICORN_TREE = PlacedFeatures.register(cobblemonResource("pink_apricorn_tree").toString(), CobblemonConfiguredFeatures.PINK_APRICORN_TREE, PlacedFeatures.wouldSurvive(
CobblemonBlocks.PINK_APRICORN_SAPLING.get()))
RED_APRICORN_TREE = PlacedFeatures.register(cobblemonResource("red_apricorn_tree").toString(), CobblemonConfiguredFeatures.RED_APRICORN_TREE, PlacedFeatures.wouldSurvive(
CobblemonBlocks.RED_APRICORN_SAPLING.get()))
WHITE_APRICORN_TREE = PlacedFeatures.register(cobblemonResource("white_apricorn_tree").toString(), CobblemonConfiguredFeatures.WHITE_APRICORN_TREE, PlacedFeatures.wouldSurvive(
CobblemonBlocks.WHITE_APRICORN_SAPLING.get()))
YELLOW_APRICORN_TREE = PlacedFeatures.register(cobblemonResource("yellow_apricorn_tree").toString(), CobblemonConfiguredFeatures.YELLOW_APRICORN_TREE, PlacedFeatures.wouldSurvive(
CobblemonBlocks.YELLOW_APRICORN_SAPLING.get()))
val apricornTreeVariety = ConfiguredFeatures.register(
cobblemonResource("apricorn_trees").toString(), Feature.SIMPLE_RANDOM_SELECTOR, SimpleRandomFeatureConfig(
RegistryEntryList.of(
BLACK_APRICORN_TREE,
BLUE_APRICORN_TREE,
GREEN_APRICORN_TREE,
PINK_APRICORN_TREE,
RED_APRICORN_TREE,
WHITE_APRICORN_TREE,
YELLOW_APRICORN_TREE
)
)
)
APRICORN_TREES = PlacedFeatures.register(cobblemonResource("apricorn_trees").toString(), apricornTreeVariety, VegetationPlacedFeatures.modifiers(RarityFilterPlacementModifier.of(8)))
BiomeModifications.addProperties({ context -> true}, { context, properties ->
properties.generationProperties.addFeature(GenerationStep.Feature.VEGETAL_DECORATION, APRICORN_TREES)
})
}
}
@@ -8,50 +8,76 @@
package com.cobblemon.mod.common
import com.cobblemon.mod.common.registry.CompletableRegistry
import com.cobblemon.mod.common.platform.PlatformRegistry
import com.cobblemon.mod.common.util.cobblemonResource
import net.minecraft.registry.Registries
import net.minecraft.registry.Registry
import net.minecraft.registry.RegistryKey
import net.minecraft.registry.RegistryKeys
import net.minecraft.sound.SoundEvent
import net.minecraft.util.registry.Registry
object CobblemonSounds : CompletableRegistry<SoundEvent>(Registry.SOUND_EVENT_KEY) {
private fun queue(name: String) = queue(name) { SoundEvent(cobblemonResource(name)) }
object CobblemonSounds : PlatformRegistry<Registry<SoundEvent>, RegistryKey<Registry<SoundEvent>>, SoundEvent>() {
override val registry: Registry<SoundEvent> = Registries.SOUND_EVENT
override val registryKey: RegistryKey<Registry<SoundEvent>> = RegistryKeys.SOUND_EVENT
@JvmField
val GUI_CLICK = queue("gui.click")
val GUI_CLICK = this.create("gui.click")
@JvmField
val PC_ON = queue("pc.on")
val PC_ON = this.create("pc.on")
@JvmField
val PC_OFF = queue("pc.off")
val PC_OFF = this.create("pc.off")
@JvmField
val PC_GRAB = queue("pc.grab")
val PC_GRAB = this.create("pc.grab")
@JvmField
val PC_DROP = queue("pc.drop")
val PC_DROP = this.create("pc.drop")
@JvmField
val PC_RELEASE = queue("pc.release")
val PC_RELEASE = this.create("pc.release")
@JvmField
val PC_CLICK = this.create("pc.click")
@JvmField
val HEALING_MACHINE_ACTIVE = queue("healing_machine.active")
val HEALING_MACHINE_ACTIVE = this.create("healing_machine.active")
@JvmField
val POKE_BALL_CAPTURE_STARTED = queue("poke_ball.capture_started")
val POKE_BALL_CAPTURE_STARTED = this.create("poke_ball.capture_started")
@JvmField
val POKE_BALL_CAPTURE_SUCCEEDED = queue("poke_ball.capture_succeeded")
val POKE_BALL_CAPTURE_SUCCEEDED = this.create("poke_ball.capture_succeeded")
@JvmField
val POKE_BALL_SHAKE = queue("poke_ball.shake")
val POKE_BALL_SHAKE = this.create("poke_ball.shake")
@JvmField
val POKE_BALL_OPEN = queue("poke_ball.open")
val POKE_BALL_OPEN = this.create("poke_ball.open")
@JvmField
val POKE_BALL_HIT = queue("poke_ball.hit")
val POKE_BALL_HIT = this.create("poke_ball.hit")
@JvmField
val POKE_BALL_SEND_OUT = queue("poke_ball.send_out")
val POKE_BALL_SEND_OUT = this.create("poke_ball.send_out")
@JvmField
val POKE_BALL_RECALL = queue("poke_ball.recall")
val POKE_BALL_RECALL = this.create("poke_ball.recall")
@JvmField
val ITEM_USE = queue("item.use")
val ITEM_USE = this.create("item.use")
@JvmField
val CAN_EVOLVE = queue("pokemon.can_evolve")
val CAN_EVOLVE = this.create("pokemon.can_evolve")
@JvmField
val EVOLVING = queue("pokemon.evolving")
val EVOLVING = this.create("pokemon.evolving")
@JvmField
val PVN_BATTLE = this.create("battle.pvn.default")
@JvmField
val PVP_BATTLE = this.create("battle.pvp.default")
@JvmField
val PVW_BATTLE = this.create("battle.pvw.default")
@JvmField
val MEDICINE_HERB_USE = this.create("medicine_herb.use")
@JvmField
val MEDICINE_LIQUID_USE = this.create("medicine_liquid.use")
@JvmField
val MEDICINE_PILLS_USE = this.create("medicine_pills.use")
@JvmField
val MEDICINE_SPRAY_USE = this.create("medicine_spray.use")
private fun create(name: String): SoundEvent = this.create(name, SoundEvent.of(cobblemonResource(name)))
}
@@ -0,0 +1,92 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common
import net.minecraft.registry.Registries
import net.minecraft.village.TradeOffers
import net.minecraft.village.VillagerData
import net.minecraft.village.VillagerProfession
/**
* A generator for various trade offers in the mod.
*/
object CobblemonTradeOffers {
/**
* Creates a list of all Cobblemon trade offers for every villager profession.
*
* @return The resulting list.
*/
fun tradeOffersForAll(): List<VillagerTradeOffer> = Registries.VILLAGER_PROFESSION.map(this::tradeOffersFor).flatten()
/**
* Creates a list of all Cobblemon trade offers for the given [VillagerProfession].
*
* @param profession The [VillagerProfession] being queried.
* @return The resulting list.
*/
fun tradeOffersFor(profession: VillagerProfession): List<VillagerTradeOffer> = when (profession) {
VillagerProfession.FARMER -> listOf(VillagerTradeOffer(VillagerProfession.FARMER, 3, listOf(TradeOffers.SellItemFactory(CobblemonItems.VIVICHOKE_SEEDS, 32, 1, 1, 6))))
else -> emptyList()
}
/**
* Creates a list of all Cobblemon trade offers for the Wandering trader.
*
* @return The resulting list.
*/
fun resolveWanderingTradeOffers(): List<WandererTradeOffer> = listOf(
WandererTradeOffer(false, listOf(TradeOffers.SellItemFactory(CobblemonItems.VIVICHOKE_SEEDS, 32, 1, 1, 6)))
)
/**
* Represents a trade offer that can be attached to a villager or a wandering trader.
*/
interface TradeOfferHolder {
/**
* The list of the possible [TradeOffers.Factory].
*/
val tradeOffers: List<TradeOffers.Factory>
}
/**
* Represents a trade offer from a villager.
*
* @property profession The target profession for this trade.
* @property requiredLevel The level required must be a possible level.
* @property tradeOffers The list of the possible [TradeOffers.Factory].
*
* @throws IllegalArgumentException If the [requiredLevel] is not within the bounds of [VillagerData.MIN_LEVEL] & [VillagerData.MAX_LEVEL].
*/
data class VillagerTradeOffer(
val profession: VillagerProfession,
val requiredLevel: Int,
override val tradeOffers: List<TradeOffers.Factory>
) : TradeOfferHolder {
init {
if (this.requiredLevel < VillagerData.MIN_LEVEL || this.requiredLevel > VillagerData.MAX_LEVEL) {
throw IllegalArgumentException("${this.requiredLevel} is not a valid level for a villager trade accepted range is ${VillagerData.MIN_LEVEL}-${VillagerData.MAX_LEVEL}")
}
}
}
/**
* Represents a trade offer from a wandering trader.
*
* @property isRareTrade If this is rare or common trade.
* @property tradeOffers The list of the possible [TradeOffers.Factory].
*/
data class WandererTradeOffer(
val isRareTrade: Boolean,
override val tradeOffers: List<TradeOffers.Factory>
) : TradeOfferHolder
}
@@ -8,12 +8,10 @@
package com.cobblemon.mod.common.advancement
import com.cobblemon.mod.common.advancement.criterion.CaughtPokemonCriterionCondition
import com.cobblemon.mod.common.advancement.criterion.PickStarterCriterionCondition
import com.cobblemon.mod.common.advancement.criterion.SimpleCountableCriterionCondition
import com.cobblemon.mod.common.advancement.criterion.SimpleCriterionTrigger
import com.cobblemon.mod.common.Cobblemon
import com.cobblemon.mod.common.advancement.criterion.*
import com.cobblemon.mod.common.util.cobblemonResource
import net.minecraft.advancement.criterion.Criteria
import net.minecraft.advancement.criterion.Criterion
/**
* Contains all the advancement criteria in Cobblemon.
@@ -22,40 +20,57 @@ import net.minecraft.advancement.criterion.Criteria
* @since October 26th, 2022
*/
object CobblemonCriteria {
val PICK_STARTER = Criteria.register(
val PICK_STARTER = this.create(
SimpleCriterionTrigger(
cobblemonResource("pick_starter"),
PickStarterCriterionCondition::class.java
)
)
val CATCH_POKEMON = Criteria.register(
val CATCH_POKEMON = this.create(
SimpleCriterionTrigger(
cobblemonResource("catch_pokemon"),
CaughtPokemonCriterionCondition::class.java
)
)
val CATCH_SHINY_POKEMON = Criteria.register(
val CATCH_SHINY_POKEMON = this.create(
SimpleCriterionTrigger(
cobblemonResource("catch_shiny_pokemon"),
SimpleCountableCriterionCondition::class.java
)
)
val EGG_HATCH = Criteria.register(
val EGG_HATCH = this.create(
SimpleCriterionTrigger(
cobblemonResource("eggs_hatched"),
SimpleCountableCriterionCondition::class.java
)
)
val EVOLVE_POKEMON = Criteria.register(
val EVOLVE_POKEMON = this.create(
SimpleCriterionTrigger(
cobblemonResource("pokemon_evolved"),
SimpleCountableCriterionCondition::class.java
)
)
val WIN_BATTLE = Criteria.register(
val WIN_BATTLE = this.create(
SimpleCriterionTrigger(
cobblemonResource("battles_won"),
SimpleCountableCriterionCondition::class.java
)
)
val DEFEAT_POKEMON = this.create(
SimpleCriterionTrigger(
cobblemonResource("pokemon_defeated"),
SimpleCountableCriterionCondition::class.java
)
)
val COLLECT_ASPECT = this.create(
AspectCriterionTrigger(
cobblemonResource("aspects_collected"),
AspectCriterionCondition::class.java
)
)
private fun <T : Criterion<*>> create(criteria: T): T = Cobblemon.implementation.registerCriteria(criteria)
}
@@ -0,0 +1,45 @@
/*
* 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.google.gson.JsonArray
import com.google.gson.JsonObject
import net.minecraft.predicate.entity.LootContextPredicate
import net.minecraft.server.network.ServerPlayerEntity
import net.minecraft.util.Identifier
open class AspectCriterionTrigger(identifier: Identifier, criterionClass: Class<AspectCriterionCondition>) : SimpleCriterionTrigger<MutableMap<Identifier, MutableSet<String>>, AspectCriterionCondition>(identifier, criterionClass) {
}
class AspectCriterionCondition(id: Identifier, predicate: LootContextPredicate) : SimpleCriterionCondition<MutableMap<Identifier, MutableSet<String>>>(id, predicate) {
var pokemon = Identifier("cobblemon:pikachu")
var aspects = mutableListOf<String>()
override fun toJson(json: JsonObject) {
json.add("aspects", JsonArray(aspects.size).also {
aspects.forEach { aspect -> it.add(aspect) }
})
json.addProperty("pokemon", pokemon.toString())
}
override fun fromJson(json: JsonObject) {
aspects.clear()
json.getAsJsonArray("aspects").forEach { element ->
aspects.add(element.asString)
}
pokemon = json.get("pokemon").asString.asIdentifierDefaultingNamespace()
}
override fun matches(player: ServerPlayerEntity, context: MutableMap<Identifier, MutableSet<String>>): Boolean {
val caughtAspects = context.getOrDefault(pokemon, mutableSetOf())
return this.aspects.all { it in caughtAspects }
}
}
@@ -9,7 +9,7 @@
package com.cobblemon.mod.common.advancement.criterion
import com.google.gson.JsonObject
import net.minecraft.predicate.entity.EntityPredicate.Extended
import net.minecraft.predicate.entity.LootContextPredicate
import net.minecraft.server.network.ServerPlayerEntity
import net.minecraft.util.Identifier
@@ -21,7 +21,7 @@ import net.minecraft.util.Identifier
*/
open class CountablePokemonTypeContext(times: Int, var type: String) : CountableContext(times)
class CaughtPokemonCriterionCondition(id: Identifier, entity: Extended) : CountableCriterionCondition<CountablePokemonTypeContext>(id, entity) {
class CaughtPokemonCriterionCondition(id: Identifier, predicate: LootContextPredicate) : CountableCriterionCondition<CountablePokemonTypeContext>(id, predicate) {
var type = "any"
override fun toJson(json: JsonObject) {
super.toJson(json)
@@ -9,7 +9,7 @@
package com.cobblemon.mod.common.advancement.criterion
import com.google.gson.JsonObject
import net.minecraft.predicate.entity.EntityPredicate.Extended
import net.minecraft.predicate.entity.LootContextPredicate
import net.minecraft.server.network.ServerPlayerEntity
import net.minecraft.util.Identifier
@@ -20,7 +20,7 @@ import net.minecraft.util.Identifier
* @author Hiroku
* @since November 4th, 2022
*/
abstract class CountableCriterionCondition<T : CountableContext>(id: Identifier, entity: Extended) : SimpleCriterionCondition<T>(id, entity) {
abstract class CountableCriterionCondition<T : CountableContext>(id: Identifier, predicate: LootContextPredicate) : SimpleCriterionCondition<T>(id, predicate) {
var count = 0
override fun fromJson(json: JsonObject) {
count = json.get("count")?.asInt ?: 0
@@ -43,7 +43,7 @@ abstract class CountableCriterionCondition<T : CountableContext>(id: Identifier,
* @author Hiroku
* @since November 4th, 2022
*/
class SimpleCountableCriterionCondition(id: Identifier, entity: Extended) : CountableCriterionCondition<CountableContext>(id, entity)
class SimpleCountableCriterionCondition(id: Identifier, predicate: LootContextPredicate) : CountableCriterionCondition<CountableContext>(id, predicate)
fun SimpleCriterionTrigger<CountableContext, SimpleCountableCriterionCondition>.trigger(player: ServerPlayerEntity, times: Int) = trigger(player, CountableContext(times))
/**
@@ -11,7 +11,7 @@ package com.cobblemon.mod.common.advancement.criterion
import com.cobblemon.mod.common.api.pokemon.PokemonProperties
import com.cobblemon.mod.common.pokemon.Pokemon
import com.google.gson.JsonObject
import net.minecraft.predicate.entity.EntityPredicate.Extended
import net.minecraft.predicate.entity.LootContextPredicate
import net.minecraft.server.network.ServerPlayerEntity
import net.minecraft.util.Identifier
@@ -21,7 +21,7 @@ import net.minecraft.util.Identifier
* @author Licious, Hiroku
* @since October 26th, 2022
*/
class PickStarterCriterionCondition(id: Identifier, entity: Extended) : SimpleCriterionCondition<Pokemon>(id, entity) {
class PickStarterCriterionCondition(id: Identifier, predicate: LootContextPredicate) : SimpleCriterionCondition<Pokemon>(id, predicate) {
var properties = PokemonProperties()
override fun toJson(json: JsonObject) {
json.addProperty("properties", properties.originalString)
@@ -13,7 +13,7 @@ import net.minecraft.advancement.criterion.AbstractCriterion
import net.minecraft.advancement.criterion.AbstractCriterionConditions
import net.minecraft.predicate.entity.AdvancementEntityPredicateDeserializer
import net.minecraft.predicate.entity.AdvancementEntityPredicateSerializer
import net.minecraft.predicate.entity.EntityPredicate.Extended
import net.minecraft.predicate.entity.LootContextPredicate
import net.minecraft.server.network.ServerPlayerEntity
import net.minecraft.util.Identifier
@@ -31,16 +31,17 @@ open class SimpleCriterionTrigger<T, C : SimpleCriterionCondition<T>>(
val criterionClass: Class<C>
) : AbstractCriterion<C>() {
override fun getId() = _id
fun trigger(player: ServerPlayerEntity, context: T) = this.trigger(player) { it.matches(player, context) }
override fun conditionsFromJson(
obj: JsonObject,
playerPredicate: Extended,
playerPredicate: LootContextPredicate,
predicateDeserializer: AdvancementEntityPredicateDeserializer
): C {
val instance = criterionClass.getConstructor(Identifier::class.java, Extended::class.java).newInstance(id, playerPredicate)
val instance = criterionClass.getConstructor(Identifier::class.java, LootContextPredicate::class.java).newInstance(id, playerPredicate)
instance.fromJson(obj)
return instance
}
fun trigger(player: ServerPlayerEntity, context: T) = this.trigger(player) { it.matches(player, context) }
}
/**
@@ -52,8 +53,8 @@ open class SimpleCriterionTrigger<T, C : SimpleCriterionCondition<T>>(
*/
abstract class SimpleCriterionCondition<T>(
id: Identifier,
entity: Extended
): AbstractCriterionConditions(id, entity) {
playerPredicate: LootContextPredicate
): AbstractCriterionConditions(id, playerPredicate) {
override fun toJson(predicateSerializer: AdvancementEntityPredicateSerializer): JsonObject {
val json = super.toJson(predicateSerializer)
toJson(json)
@@ -37,7 +37,7 @@ object Abilities : DataRegistry {
PotentialAbility.types.add(CommonAbilityType)
PotentialAbility.types.add(HiddenAbilityType)
this.abilityMap.clear()
val abilitiesJson = ShowdownService.get().getAbilityIds()
val abilitiesJson = ShowdownService.service.getAbilityIds()
for (i in 0 until abilitiesJson.size()) {
val id = abilitiesJson[i].asString
val ability = AbilityTemplate(id)
@@ -10,9 +10,9 @@ package com.cobblemon.mod.common.api.apricorn
import com.cobblemon.mod.common.CobblemonBlocks
import com.cobblemon.mod.common.CobblemonItems
import com.cobblemon.mod.common.item.ApricornItem
import com.cobblemon.mod.common.block.ApricornBlock
import com.cobblemon.mod.common.block.ApricornSaplingBlock
import com.cobblemon.mod.common.item.ApricornItem
import net.minecraft.block.MapColor
import net.minecraft.item.BlockItem
@@ -33,43 +33,43 @@ enum class Apricorn {
YELLOW;
fun item(): ApricornItem = when(this) {
BLACK -> CobblemonItems.BLACK_APRICORN.get()
BLUE -> CobblemonItems.BLUE_APRICORN.get()
GREEN -> CobblemonItems.GREEN_APRICORN.get()
PINK -> CobblemonItems.PINK_APRICORN.get()
RED -> CobblemonItems.RED_APRICORN.get()
WHITE -> CobblemonItems.WHITE_APRICORN.get()
YELLOW -> CobblemonItems.YELLOW_APRICORN.get()
BLACK -> CobblemonItems.BLACK_APRICORN
BLUE -> CobblemonItems.BLUE_APRICORN
GREEN -> CobblemonItems.GREEN_APRICORN
PINK -> CobblemonItems.PINK_APRICORN
RED -> CobblemonItems.RED_APRICORN
WHITE -> CobblemonItems.WHITE_APRICORN
YELLOW -> CobblemonItems.YELLOW_APRICORN
}
fun seed(): BlockItem = when(this) {
BLACK -> CobblemonItems.BLACK_APRICORN_SEED.get()
BLUE -> CobblemonItems.BLUE_APRICORN_SEED.get()
GREEN -> CobblemonItems.GREEN_APRICORN_SEED.get()
PINK -> CobblemonItems.PINK_APRICORN_SEED.get()
RED -> CobblemonItems.RED_APRICORN_SEED.get()
WHITE -> CobblemonItems.WHITE_APRICORN_SEED.get()
YELLOW -> CobblemonItems.YELLOW_APRICORN_SEED.get()
BLACK -> CobblemonItems.BLACK_APRICORN_SEED
BLUE -> CobblemonItems.BLUE_APRICORN_SEED
GREEN -> CobblemonItems.GREEN_APRICORN_SEED
PINK -> CobblemonItems.PINK_APRICORN_SEED
RED -> CobblemonItems.RED_APRICORN_SEED
WHITE -> CobblemonItems.WHITE_APRICORN_SEED
YELLOW -> CobblemonItems.YELLOW_APRICORN_SEED
}
fun block(): ApricornBlock = when(this) {
BLACK -> CobblemonBlocks.BLACK_APRICORN.get()
BLUE -> CobblemonBlocks.BLUE_APRICORN.get()
GREEN -> CobblemonBlocks.GREEN_APRICORN.get()
PINK -> CobblemonBlocks.PINK_APRICORN.get()
RED -> CobblemonBlocks.RED_APRICORN.get()
WHITE -> CobblemonBlocks.WHITE_APRICORN.get()
YELLOW -> CobblemonBlocks.YELLOW_APRICORN.get()
BLACK -> CobblemonBlocks.BLACK_APRICORN
BLUE -> CobblemonBlocks.BLUE_APRICORN
GREEN -> CobblemonBlocks.GREEN_APRICORN
PINK -> CobblemonBlocks.PINK_APRICORN
RED -> CobblemonBlocks.RED_APRICORN
WHITE -> CobblemonBlocks.WHITE_APRICORN
YELLOW -> CobblemonBlocks.YELLOW_APRICORN
}
fun sapling(): ApricornSaplingBlock = when(this) {
BLACK -> CobblemonBlocks.BLACK_APRICORN_SAPLING.get()
BLUE -> CobblemonBlocks.BLUE_APRICORN_SAPLING.get()
GREEN -> CobblemonBlocks.GREEN_APRICORN_SAPLING.get()
PINK -> CobblemonBlocks.PINK_APRICORN_SAPLING.get()
RED -> CobblemonBlocks.RED_APRICORN_SAPLING.get()
WHITE -> CobblemonBlocks.WHITE_APRICORN_SAPLING.get()
YELLOW -> CobblemonBlocks.YELLOW_APRICORN_SAPLING.get()
BLACK -> CobblemonBlocks.BLACK_APRICORN_SAPLING
BLUE -> CobblemonBlocks.BLUE_APRICORN_SAPLING
GREEN -> CobblemonBlocks.GREEN_APRICORN_SAPLING
PINK -> CobblemonBlocks.PINK_APRICORN_SAPLING
RED -> CobblemonBlocks.RED_APRICORN_SAPLING
WHITE -> CobblemonBlocks.WHITE_APRICORN_SAPLING
YELLOW -> CobblemonBlocks.YELLOW_APRICORN_SAPLING
}
fun mapColor(): MapColor = when(this) {
@@ -0,0 +1,73 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.battles.interpreter
import com.cobblemon.mod.common.battles.pokemon.BattlePokemon
/**
* The context of how a condition was created or changed during a battle.
*
* @author Segfault Guy
* @since April 10th, 2023
*/
interface BattleContext {
/** The effect or condition this [BattleContext] represents. */
val id: String
/** The turn this [BattleContext] was created. */
val turn: Int
/** The [BattleContext.Type] tied to this [BattleContext]. */
val type: Type
/** The [BattlePokemon] that directly or indirectly caused this [BattleContext]. */
val origin: BattlePokemon?
/**
* The type of [BattleContext].
*
* @property damaging Whether a context of this type is a source of damage.
* @property exclusive Whether only one context of this type can exist.
*
* @author Segfault Guy
* @since April 10th, 2023
*/
enum class Type(val damaging: Boolean, val exclusive: Boolean) {
ITEM(true, true),
STATUS(true, false),
VOLATILE(true, false),
HAZARD(true, false),
WEATHER(true, true),
ROOM(false, true),
SPORT(false, false),
TERRAIN(false, true),
GRAVITY(false, true),
TAILWIND(false, true),
SCREEN(false, false),
FAINT(false, false),
BOOST(false, false),
UNBOOST(false, false),
MISC(false, false);
}
}
data class BasicContext(
override val id: String,
override val turn: Int,
override val type: BattleContext.Type,
override val origin: BattlePokemon?
) : BattleContext
data class MissingContext(
override val id: String = "error",
override val turn: Int = 0,
override val type: BattleContext.Type = BattleContext.Type.MISC,
override val origin: BattlePokemon? = null
) : BattleContext
@@ -11,6 +11,8 @@ package com.cobblemon.mod.common.api.battles.interpreter
import com.cobblemon.mod.common.api.battles.model.PokemonBattle
import com.cobblemon.mod.common.api.battles.model.actor.BattleActor
import com.cobblemon.mod.common.battles.ActiveBattlePokemon
import com.cobblemon.mod.common.battles.pokemon.BattlePokemon
import java.util.UUID
/**
* A class responsible for parsing a raw simulator protocol message received from Showdown.
@@ -24,7 +26,6 @@ import com.cobblemon.mod.common.battles.ActiveBattlePokemon
* @since December 31st, 2022
*/
class BattleMessage(rawMessage: String) {
/**
* The ID of the action received in the message.
*/
@@ -116,6 +117,10 @@ class BattleMessage(rawMessage: String) {
return this
}
fun pokemonByUuid(index: Int, battle: PokemonBattle): BattlePokemon? {
return this.argumentAt(index)?.let { UUID.fromString(it) }?.let { uuid -> battle.actors.flatMap { it.pokemonList }.find { it.uuid == uuid } }
}
/**
* Queries an argument at the given [index] for a 'pnx' that will be parsed into a [BattleActor] and [ActiveBattlePokemon].
*
@@ -124,10 +129,49 @@ class BattleMessage(rawMessage: String) {
* @return A pair of [BattleActor] and [ActiveBattlePokemon] if the argument exists and successfully parses them otherwise null.
*/
fun actorAndActivePokemon(index: Int, battle: PokemonBattle): Pair<BattleActor, ActiveBattlePokemon>? {
val pnx = this.argumentAt(index)?.takeIf { it.length >= 3 }?.substring(0, 3) ?: return null
val (pnx, _) = this.pnxAndUuid(index) ?: return null
return this.actorAndActivePokemon(pnx, battle)
}
/*
Example:
|-curestatus|p1: a8e5710e-6835-4387-99d3-331b45f848e6|slp|[msg]
|-curestatus|p1: 0686b20d-3019-4167-92e2-786834245743|slp|[msg]
// Function used to grab BattlePokemon (As we need to be able to grab non active pokemon to cure their status)
// by using playerNumber(actorID) and pokemon uuid(pokemonID)
*/
fun getBattlePokemon(index: Int, battle: PokemonBattle): BattlePokemon? {
val actorAndPokemonID = this.argumentAt(index)?.takeIf { it.length >= 2 }?.split(": ") ?: return null
if (actorAndPokemonID.count() < 2) return null
val actorID = actorAndPokemonID[0]
val pokemonID = actorAndPokemonID[1]
return this.getBattlePokemon(actorID, pokemonID, battle)
}
fun getSourceBattlePokemon(battle: PokemonBattle): BattlePokemon? {
val sourcePokemonArgument = this.optionalArguments.get("of") ?: return null
val actorAndPokemonID = sourcePokemonArgument.takeIf { it.length >= 2 }?.split(": ") ?: return null
if (actorAndPokemonID.count() < 2) return null
val actorID = actorAndPokemonID[0]
val pokemonID = actorAndPokemonID[1]
return this.getBattlePokemon(actorID, pokemonID, battle)
}
/**
* Deconstructs the Showdown ID of a Pokemon at the given [index] into its 'pnx' and 'uuid' parts.
*
* @param index The index of the argument containing the Showdown ID of a Pokemon.
* @return A 'pnx' String representing position and a 'uuid' String representing the unique Pokemon if parsed correctly, otherwise null.
*/
fun pnxAndUuid(index: Int): Pair<String, String>? {
val argument = this.argumentAt(index)?.takeIf { it.length >= 2 }?.split(":")?.takeIf { it.size == 2 } ?: return null
val pnx = argument[0].takeIf { it.matches(PNX_MATCHER) } ?: return null
val uuid = argument[1].trim()
return pnx to uuid
}
/**
* Attempts to parse an [Effect] from an argument at the given [index].
*
@@ -158,7 +202,7 @@ class BattleMessage(rawMessage: String) {
* @return A pair of [BattleActor] and [ActiveBattlePokemon] if the argument exists and successfully parses them otherwise null.
*/
fun actorAndActivePokemonFromOptional(battle: PokemonBattle, argumentName: String = "of"): Pair<BattleActor, ActiveBattlePokemon>? {
val pnx = this.optionalArgument(argumentName)?.substring(0, 3) ?: return null
val pnx = this.optionalArgument(argumentName)?.takeIf { it.length >= 3 }?.substring(0, 3) ?: return null
return this.actorAndActivePokemon(pnx, battle)
}
@@ -183,12 +227,26 @@ class BattleMessage(rawMessage: String) {
null
}
private fun getBattlePokemon(pnx: String, pokemonID: String, battle: PokemonBattle): BattlePokemon? = try {
battle.getBattlePokemon(pnx, pokemonID)
} catch (_: Exception) {
null
}
companion object {
private const val SEPARATOR = "|"
private const val OPTIONAL_ARG_START = "["
private const val OPTIONAL_ARG_END = "]"
}
/**
* Pattern to match a Showdown position e.g. p2a, p1b
*/
val PNX_MATCHER = Regex("p\\d[a-c]")
/**
* Pattern to match a Showdown side position e.g. p2, p1
*/
val PN_MATCHER = Regex("p\\d")
}
}
@@ -36,6 +36,9 @@ interface Effect {
*/
val rawData: String
val typelessData: String
get() = rawData.substringAfter(type.prefix).trim()
/**
* Represents the type of the [Effect].
*
@@ -49,6 +52,7 @@ interface Effect {
ABILITY("ability:"),
ITEM("item:"),
MOVE("move:"),
BAGITEM("bagitem:"),
PURE(""),
}
@@ -16,6 +16,8 @@ import com.cobblemon.mod.common.api.battles.model.actor.ActorType
import com.cobblemon.mod.common.api.battles.model.actor.BattleActor
import com.cobblemon.mod.common.api.battles.model.actor.EntityBackedBattleActor
import com.cobblemon.mod.common.api.battles.model.actor.FleeableBattleActor
import com.cobblemon.mod.common.api.events.CobblemonEvents
import com.cobblemon.mod.common.api.events.battles.BattleFledEvent
import com.cobblemon.mod.common.api.net.NetworkPacket
import com.cobblemon.mod.common.api.tags.CobblemonItemTags
import com.cobblemon.mod.common.api.text.red
@@ -30,16 +32,24 @@ import com.cobblemon.mod.common.battles.dispatch.BattleDispatch
import com.cobblemon.mod.common.battles.dispatch.DispatchResult
import com.cobblemon.mod.common.battles.dispatch.GO
import com.cobblemon.mod.common.battles.dispatch.WaitDispatch
import com.cobblemon.mod.common.battles.interpreter.ContextManager
import com.cobblemon.mod.common.battles.pokemon.BattlePokemon
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import com.cobblemon.mod.common.battles.runner.ShowdownService
import com.cobblemon.mod.common.net.messages.client.battle.BattleEndPacket
import com.cobblemon.mod.common.net.messages.client.battle.BattleMessagePacket
import com.cobblemon.mod.common.net.messages.client.battle.BattleMusicPacket
import com.cobblemon.mod.common.pokemon.evolution.progress.DefeatEvolutionProgress
import com.cobblemon.mod.common.util.battleLang
import com.cobblemon.mod.common.util.getPlayer
import com.cobblemon.mod.common.util.party
import net.minecraft.server.network.ServerPlayerEntity
import net.minecraft.entity.Entity
import java.util.UUID
import java.util.concurrent.ConcurrentLinkedQueue
import net.minecraft.text.Text
import java.io.File
import kotlin.io.path.Path
import kotlin.io.path.writeLines
import net.minecraft.server.network.ServerPlayerEntity
/**
* Individual battle instance
@@ -79,6 +89,7 @@ open class PokemonBattle(
val battleId = UUID.randomUUID()
val showdownMessages = mutableListOf<String>()
val battleLog = mutableListOf<String>()
var started = false
var ended = false
// TEMP battle showcase stuff
@@ -93,6 +104,10 @@ open class PokemonBattle(
val captureActions = mutableListOf<BattleCaptureAction>()
val majorBattleActions = hashMapOf<UUID, BattleMessage>()
val minorBattleActions = hashMapOf<UUID, BattleMessage>()
val contextManager = ContextManager()
/** Whether or not there is one side with at least one player, and the other only has wild Pokémon. */
val isPvW: Boolean
get() {
@@ -135,6 +150,11 @@ open class PokemonBattle(
return actors.find { actor -> actor.uuid == actorId }
}
/**
* Gets the first battle actor whom the given player controls, or null if there is no such actor.
*/
fun getActor(player: ServerPlayerEntity) = actors.firstOrNull { it.isForPlayer(player) }
/**
* Gets a BattleActor and an [ActiveBattlePokemon] from a pnx key, e.g. p2a
*
@@ -149,13 +169,25 @@ open class PokemonBattle(
return actor to pokemon
}
fun getBattlePokemon(pnx: String, pokemonID: String): BattlePokemon {
val actor = actors.find { it.showdownId == pnx.substring(0, 2) }
?: throw IllegalStateException("Invalid pnx: $pnx - unknown actor")
return actor.pokemonList.find { it.uuid.toString() == pokemonID }
?: throw IllegalStateException("Invalid pnx: $pnx - unknown pokemon")
}
fun broadcastChatMessage(component: Text) {
spectators.forEach { spectatorId ->
spectatorId.getPlayer()?.let {
CobblemonNetwork.sendPacketToPlayer(it, BattleMessagePacket(component))
}
}
return actors.forEach { it.sendMessage(component) }
}
fun writeShowdownAction(vararg messages: String) {
log(messages.joinToString("\n"))
ShowdownService.get().send(battleId, messages.toList().toTypedArray())
ShowdownService.service.send(battleId, messages.toList().toTypedArray())
}
fun turn(newTurnNumber: Int) {
@@ -196,14 +228,26 @@ open class PokemonBattle(
if (experience > 0) {
opponent.awardExperience(opponentPokemon, experience)
}
Cobblemon.evYieldCalculator.calculate(opponentPokemon).forEach { (stat, amount) ->
Cobblemon.evYieldCalculator.calculate(opponentPokemon, faintedPokemon).forEach { (stat, amount) ->
pokemon.evs.add(stat, amount)
}
}
}
}
}
// Heal Mon if wild
actors.filter { it.type == ActorType.WILD }
.filterIsInstance<EntityBackedBattleActor<*>>()
.mapNotNull { it.entity }
.filterIsInstance<PokemonEntity>()
.forEach{it.pokemon.heal()}
actors.forEach { actor ->
actor.pokemonList.forEach { battlePokemon ->
battlePokemon.entity?.let { entity -> battlePokemon.postBattleEntityOperation(entity) }
}
}
sendUpdate(BattleEndPacket())
sendUpdate(BattleMusicPacket(null))
BattleRegistry.closeBattle(this)
}
@@ -216,9 +260,27 @@ open class PokemonBattle(
if (!mute) {
LOGGER.info(message)
}
battleLog.add(message)
}
fun sendUpdate(packet: NetworkPacket) {
fun saveBattleLog() {
val battleLogsDir = File("./battle_logs/")
if (!battleLogsDir.exists()) {
battleLogsDir.mkdirs()
}
val logFile = File(battleLogsDir, "$battleId.txt")
logFile.bufferedWriter().use { out ->
battleLog.forEach {
out.write(it)
out.newLine()
}
}
LOGGER.info("Saved battle log as $battleId.txt")
}
fun sendUpdate(packet: NetworkPacket<*>) {
actors.forEach { it.sendUpdate(packet) }
sendSpectatorUpdate(packet)
}
@@ -231,23 +293,23 @@ open class PokemonBattle(
* @param opponentPacket The packet sent to the opposing actors.
* @param spectatorsAsAlly If the spectators receive the [allyPacket] or the [opponentPacket], default is false.
*/
fun sendSidedUpdate(source: BattleActor, allyPacket: NetworkPacket, opponentPacket: NetworkPacket, spectatorsAsAlly: Boolean = false) {
fun sendSidedUpdate(source: BattleActor, allyPacket: NetworkPacket<*>, opponentPacket: NetworkPacket<*>, spectatorsAsAlly: Boolean = false) {
source.getSide().actors.forEach { it.sendUpdate(allyPacket) }
source.getSide().getOppositeSide().actors.forEach { it.sendUpdate(opponentPacket) }
sendSpectatorUpdate(if (spectatorsAsAlly) allyPacket else opponentPacket)
}
fun sendToActors(packet: NetworkPacket) {
CobblemonNetwork.sendToPlayers(actors.flatMap { it.getPlayerUUIDs().mapNotNull { it.getPlayer() } }, packet)
fun sendToActors(packet: NetworkPacket<*>) {
CobblemonNetwork.sendPacketToPlayers(actors.flatMap { it.getPlayerUUIDs().mapNotNull { it.getPlayer() } }, packet)
}
fun sendSplitUpdate(privateActor: BattleActor, publicPacket: NetworkPacket, privatePacket: NetworkPacket) {
fun sendSplitUpdate(privateActor: BattleActor, publicPacket: NetworkPacket<*>, privatePacket: NetworkPacket<*>) {
actors.forEach { it.sendUpdate(if (it == privateActor) privatePacket else publicPacket) }
sendSpectatorUpdate(publicPacket)
}
fun sendSpectatorUpdate(packet: NetworkPacket) {
CobblemonNetwork.sendToPlayers(spectators.mapNotNull { it.getPlayer() }, packet)
fun sendSpectatorUpdate(packet: NetworkPacket<*>) {
CobblemonNetwork.sendPacketToPlayers(spectators.mapNotNull { it.getPlayer() }, packet)
}
fun dispatch(dispatcher: () -> DispatchResult) {
@@ -288,17 +350,26 @@ open class PokemonBattle(
}
fun tick() {
while (dispatchResult.canProceed()) {
val dispatch = dispatches.poll() ?: break
dispatchResult = dispatch(this)
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()
this.actors.filterIsInstance<PlayerBattleActor>().forEach { it.entity?.sendMessage(message) }
this.saveBattleLog()
this.stop()
return
}
if (dispatches.isEmpty()) {
afterDispatches.toList().forEach { it() }
afterDispatches.clear()
}
if (started && isPvW && !ended) {
if (started && isPvW && !ended && dispatches.isEmpty()) {
checkFlee()
}
}
@@ -322,8 +393,14 @@ open class PokemonBattle(
nearestPlayerActorDistance != null && nearestPlayerActorDistance < pokemonActor.fleeDistance
}
}
if (wildPokemonOutOfRange) {
// Heal Wild Pokemon
actors.filter { it.type == ActorType.WILD }
.filterIsInstance<EntityBackedBattleActor<*>>()
.mapNotNull { it.entity }
.filterIsInstance<PokemonEntity>()
.forEach{it.pokemon.heal()}
CobblemonEvents.BATTLE_FLED.post(BattleFledEvent(this, actors.asSequence().filterIsInstance<PlayerBattleActor>().iterator().next()))
actors.filterIsInstance<EntityBackedBattleActor<*>>().mapNotNull { it.entity }.forEach { it.sendMessage(battleLang("flee").yellow()) }
stop()
}
@@ -372,5 +449,4 @@ open class PokemonBattle(
LOGGER.error("Missing interpretation on '{}' action: \nPublic » {}\nPrivate » {}", publicMessage.id, publicMessage.rawMessage, privateMessage.rawMessage)
return Text.literal("Missing interpretation on '${publicMessage.id}' action please report to the developers").red()
}
}
}
@@ -8,9 +8,12 @@
package com.cobblemon.mod.common.api.battles.model.actor
import com.cobblemon.mod.common.Cobblemon.LOGGER
import com.cobblemon.mod.common.api.battles.model.ai.BattleAI
import com.cobblemon.mod.common.api.net.NetworkPacket
import com.cobblemon.mod.common.battles.PassActionResponse
import com.cobblemon.mod.common.battles.pokemon.BattlePokemon
import com.cobblemon.mod.common.exception.IllegalActionChoiceException
import com.cobblemon.mod.common.net.messages.client.battle.BattleMakeChoicePacket
import java.util.UUID
@@ -19,11 +22,17 @@ abstract class AIBattleActor(
pokemonList: List<BattlePokemon>,
val battleAI: BattleAI
) : BattleActor(gameId, pokemonList.toMutableList()) {
override fun sendUpdate(packet: NetworkPacket) {
override fun sendUpdate(packet: NetworkPacket<*>) {
super.sendUpdate(packet)
if (packet is BattleMakeChoicePacket) {
setActionResponses(request!!.iterate(this.activePokemon, battleAI::choose) )
try {
setActionResponses(request!!.iterate(this.activePokemon, battleAI::choose))
} catch (exception: IllegalActionChoiceException) {
LOGGER.error("AI was unable to choose a move, we're going to need to pass!")
exception.printStackTrace()
setActionResponses(request!!.iterate(this.activePokemon) { _, _, _ -> PassActionResponse })
}
}
}
}
@@ -11,12 +11,13 @@ package com.cobblemon.mod.common.api.battles.model.actor
import com.cobblemon.mod.common.api.battles.model.PokemonBattle
import com.cobblemon.mod.common.api.net.NetworkPacket
import com.cobblemon.mod.common.battles.ActiveBattlePokemon
import com.cobblemon.mod.common.battles.BallActionResponse
import com.cobblemon.mod.common.battles.ForcePassActionResponse
import com.cobblemon.mod.common.battles.ShowdownActionRequest
import com.cobblemon.mod.common.battles.ShowdownActionResponse
import com.cobblemon.mod.common.battles.pokemon.BattlePokemon
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import com.cobblemon.mod.common.exception.IllegalActionChoiceException
import com.cobblemon.mod.common.net.messages.client.battle.BattleApplyPassResponsePacket
import com.cobblemon.mod.common.net.messages.client.battle.BattleMakeChoicePacket
import com.cobblemon.mod.common.net.messages.client.battle.BattleMessagePacket
import java.util.UUID
@@ -40,11 +41,24 @@ abstract class BattleActor(
var request: ShowdownActionRequest? = null
var responses = mutableListOf<ShowdownActionResponse>()
var expectingCaptureActions = 0
val expectingPassActions = mutableListOf<ShowdownActionResponse>()
var mustChoose = false
/** 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
abstract val type: ActorType
fun canFitForcedAction() = mustChoose && request?.let { request ->
val countMovable = (request.active?.count() ?: 0) - request.forceSwitch.count { it }
return@let countMovable > expectingPassActions.size && !battle.ended
} ?: false
fun forceChoose(response: ShowdownActionResponse) {
expectingPassActions.add(response)
sendUpdate(BattleApplyPassResponsePacket())
}
fun getSide() = if (this in battle.side1.actors) battle.side1 else battle.side2
open fun getPlayerUUIDs(): Iterable<UUID> = emptyList()
@@ -60,7 +74,7 @@ abstract class BattleActor(
val requestActive = request.active
if (requestActive == null || requestActive.isEmpty() || request.wait) {
this.request = null
expectingCaptureActions = 0
expectingPassActions.clear()
return
}
}
@@ -78,23 +92,24 @@ abstract class BattleActor(
fun setActionResponses(responses: List<ShowdownActionResponse>) {
val request = request ?: return
val originalCaptureActions = expectingCaptureActions
val originalPassActions = expectingPassActions.toList()
responses.forEachIndexed { index, response ->
val activeBattlePokemon = activePokemon.let { if (it.size > index) it[index] else return }
val showdownMoveSet = request.active?.let { if (it.size > index) it[index] else null }
val forceSwitch = request.forceSwitch.let { if (it.size > index) it[index] else false }
if (!response.isValid(activeBattlePokemon, showdownMoveSet, forceSwitch)) {
expectingCaptureActions = originalCaptureActions
expectingPassActions.clear()
expectingPassActions.addAll(originalPassActions)
throw IllegalActionChoiceException(this, "Invalid action choice for ${activeBattlePokemon.battlePokemon!!.getName().string}: $response")
} else if (response is BallActionResponse) {
expectingCaptureActions--
} else if (response is ForcePassActionResponse) {
this.responses.add(expectingPassActions.removeAt(0))
} else {
this.responses.add(response)
}
this.responses.add(response)
}
if (expectingCaptureActions > 0) {
if (expectingPassActions.size > 0) {
throw IllegalActionChoiceException(this, "Invalid action choice: a capture was expected. Are you hacking me?")
}
expectingCaptureActions = originalCaptureActions
mustChoose = false
battle.checkForInputDispatch()
}
@@ -110,7 +125,7 @@ abstract class BattleActor(
}
responses.clear()
request = null
expectingCaptureActions = 0
expectingPassActions.clear()
battle.writeShowdownAction(">$showdownId ${showdownMessages.joinToString()}")
}
@@ -129,5 +144,5 @@ abstract class BattleActor(
sendUpdate(BattleMessagePacket(component))
}
open fun awardExperience(battlePokemon: BattlePokemon, experience: Int) {}
open fun sendUpdate(packet: NetworkPacket) {}
open fun sendUpdate(packet: NetworkPacket<*>) {}
}
@@ -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.api.callback
import com.cobblemon.mod.common.Cobblemon
import com.cobblemon.mod.common.CobblemonNetwork.sendPacket
import com.cobblemon.mod.common.api.moves.Move
import com.cobblemon.mod.common.api.moves.MoveTemplate
import com.cobblemon.mod.common.api.moves.Moves
import com.cobblemon.mod.common.api.text.text
import com.cobblemon.mod.common.battles.InBattleMove
import com.cobblemon.mod.common.net.IntSize
import com.cobblemon.mod.common.net.messages.client.callback.OpenMoveCallbackPacket
import com.cobblemon.mod.common.util.readSizedInt
import com.cobblemon.mod.common.util.writeSizedInt
import java.util.UUID
import net.minecraft.network.PacketByteBuf
import net.minecraft.server.network.ServerPlayerEntity
import net.minecraft.text.Text
/**
* Used for opening move selection screens for players and handling their choice. Currently
* only supports up to 4 moves to select from.
*
* @author Hiroku
* @since July 1st, 2023
*/
object MoveSelectCallbacks {
val callbacks = mutableMapOf<UUID, MoveSelectCallback>()
@JvmOverloads
fun create(
player: ServerPlayerEntity,
title: Text = "".text(),
possibleMoves: List<MoveSelectDTO>,
cancel: (ServerPlayerEntity) -> Unit = {},
handler: (ServerPlayerEntity, index: Int, MoveSelectDTO) -> Unit
) {
val callback = MoveSelectCallback(
shownMoves = possibleMoves,
cancel = cancel,
handler = handler
)
callbacks[player.uuid] = callback
player.sendPacket(OpenMoveCallbackPacket(callback.uuid, title.copy(), possibleMoves))
}
@JvmOverloads
fun create(
player: ServerPlayerEntity,
moves: List<Move>,
canSelect: (Move) -> Boolean = { true },
cancel: (ServerPlayerEntity) -> Unit = {},
handler: (Move) -> Unit
) = create(
player = player,
possibleMoves = moves.map { battleMove -> MoveSelectDTO(battleMove).also { it.enabled = canSelect(battleMove) } },
cancel = cancel,
handler = { _, index, _ -> handler(moves[index]) }
)
@JvmOverloads
fun createBattleSelect(
player: ServerPlayerEntity,
moves: List<InBattleMove>,
canSelect: (InBattleMove) -> Boolean = { true },
cancel: (ServerPlayerEntity) -> Unit = {},
handler: (InBattleMove) -> Unit
) = create(
player = player,
possibleMoves = moves.map { battleMove -> MoveSelectDTO(battleMove).also { it.enabled = canSelect(battleMove) } },
cancel = cancel,
handler = { _, index, _ -> handler(moves[index]) }
)
fun handleCancelled(player: ServerPlayerEntity, uuid: UUID) {
val callback = callbacks[player.uuid] ?: return
if (callback.uuid != uuid) {
return
}
callbacks.remove(player.uuid)
callback.cancel(player)
}
fun handleCallback(player: ServerPlayerEntity, uuid: UUID, index: Int) {
val callback = callbacks[player.uuid] ?: return
callbacks.remove(player.uuid)
if (callback.uuid != uuid) {
Cobblemon.LOGGER.warn("A move select callback ran but with a mismatching UUID from ${player.gameProfile.name}. Hacking attempts?")
} else if (index >= callback.shownMoves.size) {
Cobblemon.LOGGER.warn("${player.gameProfile.name} used move select callback with an index that was out of bounds. Hacking attempts? Tried $index, possible size was ${callback.shownMoves.size}")
} else if (!callback.shownMoves[index].enabled) {
Cobblemon.LOGGER.warn("${player.gameProfile.name} used move select callback with a move that is not enabled. Hacking attempts?")
} else {
callback.handler(player, index, callback.shownMoves[index])
}
}
}
class MoveSelectCallback(
val uuid: UUID = UUID.randomUUID(),
val shownMoves: List<MoveSelectDTO>,
val cancel: (ServerPlayerEntity) -> Unit = {},
val handler: (ServerPlayerEntity, Int, MoveSelectDTO) -> Unit
)
class MoveSelectDTO(val moveTemplate: MoveTemplate, var enabled: Boolean, val pp: Int = -1, val ppMax: Int = -1) {
@JvmOverloads
constructor(move: Move, enabled: Boolean = true): this(moveTemplate = move.template, enabled = enabled, pp = move.currentPp, ppMax = move.maxPp)
@JvmOverloads
constructor(move: InBattleMove, enabled: Boolean = true): this(moveTemplate = Moves.getByNameOrDummy(move.move), enabled = enabled, pp = move.pp, ppMax = move.maxpp)
constructor(buffer: PacketByteBuf): this(
moveTemplate = Moves.getByNameOrDummy(buffer.readString()),
enabled = buffer.readBoolean(),
pp = buffer.readSizedInt(IntSize.BYTE),
ppMax = buffer.readSizedInt(IntSize.BYTE)
)
fun writeToBuffer(buffer: PacketByteBuf) {
buffer.writeString(moveTemplate.name)
buffer.writeBoolean(enabled)
buffer.writeSizedInt(IntSize.BYTE, pp)
buffer.writeSizedInt(IntSize.BYTE, ppMax)
}
}
@@ -0,0 +1,114 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.callback
import com.cobblemon.mod.common.Cobblemon
import com.cobblemon.mod.common.CobblemonNetwork.sendPacket
import com.cobblemon.mod.common.api.moves.Move
import com.cobblemon.mod.common.net.messages.client.callback.OpenPartyMoveCallbackPacket
import com.cobblemon.mod.common.pokemon.Pokemon
import java.util.UUID
import net.minecraft.server.network.ServerPlayerEntity
/**
* Used for opening a party select screen for players which routes to move selection when they choose a Pokémon.
* You can do the same sort of thing with combined [MoveSelectCallbacks] and [PartySelectCallbacks] but it isn't
* as smooth an experience.
*
* @author Hiroku
* @since July 29th, 2023
*/
object PartyMoveSelectCallbacks {
val callbacks = mutableMapOf<UUID, PartyMoveSelectCallback>()
@JvmOverloads
fun create(
player: ServerPlayerEntity,
pokemon: List<Pair<PartySelectPokemonDTO, List<MoveSelectDTO>>>,
cancel: (ServerPlayerEntity) -> Unit = {},
handler: (ServerPlayerEntity, pokemonIndex: Int, PartySelectPokemonDTO, moveIndex: Int, MoveSelectDTO) -> Unit
) {
val callback = PartyMoveSelectCallback(
pokemon = pokemon,
cancel = cancel,
handler = handler
)
callbacks[player.uuid] = callback
player.sendPacket(OpenPartyMoveCallbackPacket(callback.uuid, callback.pokemon))
}
@JvmOverloads
fun createFromPokemon(
player: ServerPlayerEntity,
pokemon: List<Pokemon>,
moves: (Pokemon) -> List<Move> = { it.moveSet.getMoves() },
canSelectPokemon: (Pokemon) -> Boolean = { true },
canSelectMove: (Pokemon, Move) -> Boolean = { _, _ -> true },
cancel: (ServerPlayerEntity) -> Unit = {},
handler: (Pokemon, Move) -> Unit
) {
val pokemonList = mutableListOf<Pair<PartySelectPokemonDTO, List<MoveSelectDTO>>>()
for (pk in pokemon) {
val enabled = canSelectPokemon(pk)
val moveList = moves(pk).map { MoveSelectDTO(it, enabled = canSelectMove(pk, it)) }
pokemonList.add(PartySelectPokemonDTO(pk, enabled) to moveList)
}
create(
player = player,
pokemon = pokemonList,
cancel = cancel,
handler = { _, pkIndex, _, moveIndex, _ ->
handler(pokemon[pkIndex], pokemon[pkIndex].moveSet[moveIndex] ?: return@create)
}
)
}
fun handleCancelled(player: ServerPlayerEntity, uuid: UUID) {
val callback = callbacks[player.uuid] ?: return
if (callback.uuid != uuid) {
return
}
callbacks.remove(player.uuid)
callback.cancel(player)
}
fun handleCallback(player: ServerPlayerEntity, uuid: UUID, pokemonIndex: Int, moveIndex: Int) {
val callback = callbacks[player.uuid] ?: return
callbacks.remove(player.uuid)
if (callback.uuid != uuid) {
return Cobblemon.LOGGER.warn("A party move select callback ran but with a mismatching UUID from ${player.gameProfile.name}. Hacking attempts?")
} else if (pokemonIndex >= callback.pokemon.size) {
return Cobblemon.LOGGER.warn("${player.gameProfile.name} used party move select callback with a Pokémon index that was out of bounds. Hacking attempts? Tried $pokemonIndex, possible size was ${callback.pokemon.size}")
}
val (pokemon, moves) = callback.pokemon[pokemonIndex]
if (!pokemon.enabled) {
return Cobblemon.LOGGER.warn("${player.gameProfile.name} used party move select callback with a Pokémon that is not enabled. Hacking attempts?")
} else if (moveIndex >= moves.size) {
return Cobblemon.LOGGER.warn("${player.gameProfile.name} used party move select callback with a move index that was out of bounds. Hacking attempts? Tried $pokemonIndex-$moveIndex, possible size was ${moves.size}")
}
val move = moves[moveIndex]
if (!move.enabled) {
Cobblemon.LOGGER.warn("${player.gameProfile.name} used party move select callback with a move that is not enabled. Hacking attempts?")
} else {
callback.handler(player, pokemonIndex, pokemon, moveIndex, move)
}
}
}
class PartyMoveSelectCallback(
val uuid: UUID = UUID.randomUUID(),
val pokemon: List<Pair<PartySelectPokemonDTO, List<MoveSelectDTO>>>,
val cancel: (ServerPlayerEntity) -> Unit = {},
val handler: (ServerPlayerEntity, pokemonIndex: Int, PartySelectPokemonDTO, moveIndex: Int, MoveSelectDTO) -> Unit
)
@@ -0,0 +1,152 @@
/*
* 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.callback
import com.cobblemon.mod.common.Cobblemon
import com.cobblemon.mod.common.CobblemonNetwork.sendPacket
import com.cobblemon.mod.common.api.pokemon.PokemonProperties
import com.cobblemon.mod.common.api.pokemon.PokemonPropertyExtractor
import com.cobblemon.mod.common.api.text.text
import com.cobblemon.mod.common.battles.pokemon.BattlePokemon
import com.cobblemon.mod.common.net.messages.client.callback.OpenPartyCallbackPacket
import com.cobblemon.mod.common.pokemon.Pokemon
import java.util.UUID
import net.minecraft.item.ItemStack
import net.minecraft.nbt.NbtCompound
import net.minecraft.network.PacketByteBuf
import net.minecraft.server.network.ServerPlayerEntity
import net.minecraft.text.Text
/**
* Used for opening party Pokémon selection screens for players and handling their choice. Currently
* only supports up to 6 Pokémon to select from.
*
* @author Hiroku
* @since July 1st, 2023
*/
object PartySelectCallbacks {
val callbacks = mutableMapOf<UUID, PartySelectCallback>()
@JvmOverloads
fun create(
player: ServerPlayerEntity,
title: Text = "".text(),
pokemon: List<PartySelectPokemonDTO>,
cancel: (ServerPlayerEntity) -> Unit = {},
handler: (ServerPlayerEntity, index: Int) -> Unit
) {
val callback = PartySelectCallback(
shownPokemon = pokemon,
cancel = cancel,
handler = handler
)
callbacks[player.uuid] = callback
player.sendPacket(
OpenPartyCallbackPacket(
uuid = callback.uuid,
title = title.copy(),
pokemon = pokemon
)
)
}
@JvmOverloads
fun createBattleSelect(
player: ServerPlayerEntity,
pokemon: List<BattlePokemon>,
canSelect: (BattlePokemon) -> Boolean,
cancel: (ServerPlayerEntity) -> Unit = {},
handler: (BattlePokemon) -> Unit
) = create(
player = player,
cancel = cancel,
pokemon = pokemon.map { pk -> PartySelectPokemonDTO(pk.effectedPokemon).also { it.enabled = canSelect(pk) } }
) { _, index -> handler(pokemon[index]) }
@JvmOverloads
fun createFromPokemon(
player: ServerPlayerEntity,
pokemon: List<Pokemon>,
canSelect: (Pokemon) -> Boolean,
cancel: (ServerPlayerEntity) -> Unit = {},
handler: (Pokemon) -> Unit
) = create(
player = player,
cancel = cancel,
pokemon = pokemon.map { pk -> PartySelectPokemonDTO(pk).also { it.enabled = canSelect(pk) } }
) { _, index -> handler(pokemon[index]) }
fun handleCancelled(player: ServerPlayerEntity, uuid: UUID) {
val callback = callbacks[player.uuid] ?: return
if (callback.uuid != uuid) {
return
}
callbacks.remove(player.uuid)
callback.cancel(player)
}
fun handleCallback(player: ServerPlayerEntity, uuid: UUID, index: Int) {
val callback = callbacks[player.uuid] ?: return
callbacks.remove(player.uuid)
if (callback.uuid != uuid) {
Cobblemon.LOGGER.warn("A party select callback ran but with a mismatching UUID from ${player.gameProfile.name}. Hacking attempts?")
} else if (index >= callback.shownPokemon.size) {
Cobblemon.LOGGER.warn("${player.gameProfile.name} used party select callback with an out of bounds index. Hacking attempts? Tried $index, Pokémon list size was ${callback.shownPokemon.size}")
} else if (!callback.shownPokemon[index].enabled) {
Cobblemon.LOGGER.warn("${player.gameProfile.name} used party select callback with a Pokémon that is not enabled. Hacking attempts?")
} else {
callback.handler(player, index)
}
}
}
class PartySelectCallback(
val uuid: UUID = UUID.randomUUID(),
val shownPokemon: List<PartySelectPokemonDTO>,
val cancel: (ServerPlayerEntity) -> Unit = {},
val handler: (ServerPlayerEntity, index: Int) -> Unit
)
open class PartySelectPokemonDTO(
val pokemonProperties: PokemonProperties,
val heldItem: ItemStack = ItemStack.EMPTY,
var hpRatio: Float = 1F,
var enabled: Boolean
) {
@JvmOverloads
constructor(pokemon: Pokemon, enabled: Boolean = true): this(
pokemonProperties = pokemon.createPokemonProperties(
PokemonPropertyExtractor.ASPECTS,
PokemonPropertyExtractor.SPECIES,
PokemonPropertyExtractor.LEVEL,
PokemonPropertyExtractor.NICKNAME,
PokemonPropertyExtractor.POKEBALL,
PokemonPropertyExtractor.STATUS
),
heldItem = pokemon.heldItemNoCopy(),
hpRatio = pokemon.currentHealth / pokemon.hp.toFloat(),
enabled = enabled
)
constructor(buffer: PacketByteBuf): this(
pokemonProperties = PokemonProperties().loadFromNBT(buffer.readNbt() as NbtCompound),
heldItem = buffer.readItemStack(),
hpRatio = buffer.readFloat(),
enabled = buffer.readBoolean()
)
fun writeToBuffer(buffer: PacketByteBuf) {
buffer.writeNbt(pokemonProperties.saveToNBT())
buffer.writeItemStack(heldItem)
buffer.writeFloat(hpRatio)
buffer.writeBoolean(enabled)
}
}
@@ -8,7 +8,7 @@
package com.cobblemon.mod.common.api.conditional
import net.minecraft.util.registry.Registry
import net.minecraft.registry.Registry
/**
* A condition which applies to an entry in some [Registry].
@@ -9,8 +9,8 @@
package com.cobblemon.mod.common.api.conditional
import com.google.gson.JsonElement
import net.minecraft.registry.Registry
import net.minecraft.util.Identifier
import net.minecraft.util.registry.Registry
/**
* A condition for some registry type which asserts that the entry must have the given [Identifier].
@@ -9,10 +9,10 @@
package com.cobblemon.mod.common.api.conditional
import com.google.gson.JsonElement
import net.minecraft.tag.TagKey
import net.minecraft.registry.Registry
import net.minecraft.registry.RegistryKey
import net.minecraft.registry.tag.TagKey
import net.minecraft.util.Identifier
import net.minecraft.util.registry.Registry
import net.minecraft.util.registry.RegistryKey
/**
* A condition for some registry type that asserts that the entry must be inside the given [TagKey]. This is presented
@@ -40,11 +40,11 @@ open class RegistryLikeTagCondition<T>(val tag: TagKey<T>) : RegistryLikeConditi
}
override fun fits(t: T, registry: Registry<T>): Boolean {
val registryHasTag = registry.containsTag(tag)
if (!registryHasTag) {
// LOGGER.warn("No tag in registry: ${tag.id}")
return false
}
// val registryHasTag = registry.containsTag(tag)
// if (!registryHasTag) {
//// LOGGER.warn("No tag in registry: ${tag.id}")
// return false
// }
return registry.getKey(t)
.flatMap(registry::getEntry)
@@ -11,7 +11,6 @@ package com.cobblemon.mod.common.api.data
import com.cobblemon.mod.common.api.codec.CodecMapped
import com.cobblemon.mod.common.api.codec.MappedCodec
import com.mojang.serialization.Codec
import java.lang.IllegalArgumentException
import net.minecraft.network.PacketByteBuf
/**
@@ -12,9 +12,7 @@ import com.cobblemon.mod.common.util.endsWith
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import java.io.File
import java.nio.file.Path
import java.util.concurrent.ExecutionException
import kotlin.io.path.pathString
import net.minecraft.resource.ResourceManager
import net.minecraft.util.Identifier
@@ -19,11 +19,11 @@ import net.minecraft.entity.ItemEntity
import net.minecraft.entity.LivingEntity
import net.minecraft.item.ItemStack
import net.minecraft.nbt.NbtCompound
import net.minecraft.registry.RegistryKeys
import net.minecraft.server.network.ServerPlayerEntity
import net.minecraft.server.world.ServerWorld
import net.minecraft.util.Identifier
import net.minecraft.util.math.Vec3d
import net.minecraft.util.registry.Registry
/**
* A drop that is an actual item.
@@ -41,7 +41,7 @@ class ItemDropEntry : DropEntry {
val nbt: NbtCompound? = null
override fun drop(entity: LivingEntity?, world: ServerWorld, pos: Vec3d, player: ServerPlayerEntity?) {
val item = world.registryManager.get(Registry.ITEM_KEY).get(item) ?: return LOGGER.error("Unable to load drop item: $item")
val item = world.registryManager.get(RegistryKeys.ITEM).get(item) ?: return LOGGER.error("Unable to load drop item: $item")
val stack = ItemStack(item, quantityRange?.random() ?: quantity)
val inLava = world.getBlockState(pos.toBlockPos()).block == Blocks.LAVA
val dropMethod = (dropMethod ?: Cobblemon.config.defaultDropItemMethod).let {
@@ -8,53 +8,40 @@
package com.cobblemon.mod.common.api.events
import com.cobblemon.mod.common.api.events.battles.BattleFaintedEvent
import com.cobblemon.mod.common.api.events.battles.BattleFledEvent
import com.cobblemon.mod.common.api.events.battles.BattleStartedPostEvent
import com.cobblemon.mod.common.api.events.battles.BattleStartedPreEvent
import com.cobblemon.mod.common.api.events.battles.BattleVictoryEvent
import com.cobblemon.mod.common.api.events.drops.LootDroppedEvent
import com.cobblemon.mod.common.api.events.entity.EntityAttributeEvent
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.SpawnEvent
import com.cobblemon.mod.common.api.events.farming.ApricornHarvestEvent
import com.cobblemon.mod.common.api.events.item.LeftoversCreatedEvent
import com.cobblemon.mod.common.api.events.net.MessageBuiltEvent
import com.cobblemon.mod.common.api.events.pokemon.ExperienceGainedPostEvent
import com.cobblemon.mod.common.api.events.pokemon.ExperienceGainedPreEvent
import com.cobblemon.mod.common.api.events.pokemon.FriendshipUpdatedEvent
import com.cobblemon.mod.common.api.events.pokemon.LevelUpEvent
import com.cobblemon.mod.common.api.events.pokemon.PokemonCapturedEvent
import com.cobblemon.mod.common.api.events.pokemon.PokemonFaintedEvent
import com.cobblemon.mod.common.api.events.pokemon.ShoulderMountEvent
import com.cobblemon.mod.common.api.events.pokeball.ThrownPokeballHitEvent
import com.cobblemon.mod.common.api.events.pokemon.*
import com.cobblemon.mod.common.api.events.pokemon.evolution.EvolutionAcceptedEvent
import com.cobblemon.mod.common.api.events.pokemon.evolution.EvolutionCompleteEvent
import com.cobblemon.mod.common.api.events.pokemon.evolution.EvolutionDisplayEvent
import com.cobblemon.mod.common.api.events.pokemon.interaction.ExperienceCandyUseEvent
import com.cobblemon.mod.common.api.events.starter.StarterChosenEvent
import com.cobblemon.mod.common.api.events.storage.ReleasePokemonEvent
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
import com.cobblemon.mod.common.api.reactive.Observable.Companion.filter
import com.cobblemon.mod.common.api.reactive.Observable.Companion.map
import com.cobblemon.mod.common.api.reactive.SimpleObservable
import com.cobblemon.mod.common.util.asObservable
import com.cobblemon.mod.common.util.asServerObservable
import com.cobblemon.mod.common.util.asTickObservable
import dev.architectury.event.EventResult
import dev.architectury.event.events.common.EntityEvent
import dev.architectury.event.events.common.EntityEvent.LivingDeath
import dev.architectury.event.events.common.LifecycleEvent
import dev.architectury.event.events.common.PlayerEvent
import dev.architectury.event.events.common.PlayerEvent.PlayerJoin
import dev.architectury.event.events.common.PlayerEvent.PlayerQuit
import dev.architectury.event.events.common.TickEvent
import net.minecraft.entity.LivingEntity
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import net.minecraft.server.network.ServerPlayerEntity
object CobblemonEvents {
@JvmField
val MESSAGE_BUILT = EventObservable<MessageBuiltEvent<*>>()
@JvmField
val DATA_SYNCHRONIZED = SimpleObservable<ServerPlayerEntity>()
@JvmField
val ENTITY_ATTRIBUTE = EventObservable<EntityAttributeEvent>()
@JvmField
val SHOULDER_MOUNT = CancelableObservable<ShoulderMountEvent>()
@JvmField
val FRIENDSHIP_UPDATED = EventObservable<FriendshipUpdatedEvent>()
@@ -66,13 +53,32 @@ object CobblemonEvents {
val EVOLUTION_DISPLAY = EventObservable<EvolutionDisplayEvent>()
@JvmField
val EVOLUTION_COMPLETE = EventObservable<EvolutionCompleteEvent>()
@JvmField
val POKEMON_NICKNAMED = CancelableObservable<PokemonNicknamedEvent>()
@JvmField
val THROWN_POKEBALL_HIT = CancelableObservable<ThrownPokeballHitEvent>()
@JvmField
val POKEMON_CAPTURED = EventObservable<PokemonCapturedEvent>()
// @JvmField
// val EGG_HATCH = EventObservable<HatchEggEvent>()
@JvmField
val BATTLE_STARTED_PRE = CancelableObservable<BattleStartedPreEvent>()
@JvmField
val BATTLE_STARTED_POST = EventObservable<BattleStartedPostEvent>()
@JvmField
val BATTLE_FLED = EventObservable<BattleFledEvent>()
@JvmField
val BATTLE_VICTORY = EventObservable<BattleVictoryEvent>()
@JvmField
val BATTLE_FAINTED = EventObservable<BattleFaintedEvent>()
@JvmField
val POKEMON_SENT_PRE = CancelableObservable<PokemonSentPreEvent>()
@JvmField
val POKEMON_SENT_POST = EventObservable<PokemonSentPostEvent>()
@JvmField
val POKEMON_RECALLED = EventObservable<PokemonRecalledEvent>()
@JvmField
val LEVEL_UP_EVENT = EventObservable<LevelUpEvent>()
@@ -83,6 +89,15 @@ object CobblemonEvents {
val POKEMON_ENTITY_LOAD = CancelableObservable<PokemonEntityLoadEvent>()
@JvmField
val POKEMON_ENTITY_SAVE_TO_WORLD = CancelableObservable<PokemonEntitySaveToWorldEvent>()
@JvmField
val ENTITY_SPAWN = CancelableObservable<SpawnEvent<*>>()
@JvmField
val POKEMON_ENTITY_SPAWN = ENTITY_SPAWN
.pipe(
filter { it.entity is PokemonEntity },
map { it as SpawnEvent<PokemonEntity> }
)
@JvmField
val EXPERIENCE_GAINED_EVENT_PRE = CancelableObservable<ExperienceGainedPreEvent>()
@@ -107,27 +122,6 @@ object CobblemonEvents {
val APRICORN_HARVESTED = EventObservable<ApricornHarvestEvent>()
@JvmField
val LEFTOVERS_CREATED = CancelableObservable<LeftoversCreatedEvent>()
@JvmField
val SERVER_STARTING = LifecycleEvent.SERVER_STARTING.asServerObservable()
@JvmField
val SERVER_STOPPING = LifecycleEvent.SERVER_STOPPING.asServerObservable()
@JvmField
val SERVER_STARTED = LifecycleEvent.SERVER_STARTED.asServerObservable()
@JvmField
val SERVER_STOPPED = LifecycleEvent.SERVER_STOPPED.asServerObservable()
@JvmField
val TICK_PRE = TickEvent.SERVER_PRE.asTickObservable()
@JvmField
val TICK_POST = TickEvent.SERVER_POST.asTickObservable()
@JvmField
val PLAYER_JOIN = PlayerEvent.PLAYER_JOIN.asObservable<PlayerJoin, ServerPlayerEntity> { obs -> PlayerJoin { obs.emit(it) } }
@JvmField
val PLAYER_QUIT = PlayerEvent.PLAYER_QUIT.asObservable<PlayerQuit, ServerPlayerEntity> { obs -> PlayerQuit { obs.emit(it) } }
@JvmField
val LIVING_DEATH = EntityEvent.LIVING_DEATH.asObservable<LivingDeath, LivingEntity> { obs -> LivingDeath { entity, source -> obs.emit(entity); EventResult.pass() } }
val BIG_ROOT_PROPAGATED = CancelableObservable<BigRootPropagatedEvent>()
}
@@ -0,0 +1,26 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.events.battles
import com.cobblemon.mod.common.api.battles.model.PokemonBattle
/**
* Interface for events involving the Showdown battle engine
*
* @author Segfault Guy
* @since March 25th 2023
*/
interface BattleEvent {
/**
* The [PokemonBattle] that is the subject of the event.
*/
val battle: PokemonBattle
}
@@ -0,0 +1,26 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.events.battles
import com.cobblemon.mod.common.api.battles.interpreter.BattleContext
import com.cobblemon.mod.common.api.battles.model.PokemonBattle
import com.cobblemon.mod.common.battles.pokemon.BattlePokemon
/**
* Event fired when a [BattlePokemon] faints. Exposes the [BattlePokemon] that fainted and the [BattleContext]
* of how it fainted.
*
* @author Segfault Guy
* @since April 6th, 2023
*/
data class BattleFaintedEvent (
override val battle: PokemonBattle,
val killed: BattlePokemon,
val context: BattleContext
) : BattleEvent
@@ -0,0 +1,25 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.events.battles
import com.cobblemon.mod.common.api.battles.model.PokemonBattle
import com.cobblemon.mod.common.battles.actor.PlayerBattleActor
/**
* Event fired when a [PokemonBattle] is fled by a [PlayerBattleActor].
*
* @author Segfault Guy
* @since March 25th 2023
*/
data class BattleFledEvent (
override val battle: PokemonBattle,
val player: PlayerBattleActor
) : BattleEvent
@@ -0,0 +1,43 @@
/*
* 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.battles
import com.cobblemon.mod.common.api.battles.model.PokemonBattle
import com.cobblemon.mod.common.api.battles.model.actor.BattleActor
import com.cobblemon.mod.common.api.events.Cancelable
import com.cobblemon.mod.common.battles.BattleFormat
/**
* Event fired before a [PokemonBattle] is started. Canceling this event prevents the battle from being
* created and launched.
*
* @author Segfault Guy
* @since March 26th 2023
*/
data class BattleStartedPreEvent (
val participants: Collection<BattleActor>,
val format: BattleFormat,
val isPvP: Boolean,
val isPvN: Boolean,
val isPvW: Boolean
) : Cancelable()
/**
* Event fired after a [PokemonBattle] starts.
*
* @author Segfault Guy
* @since March 26th 2023
*/
data class BattleStartedPostEvent (
override val battle: PokemonBattle
) : BattleEvent
@@ -18,6 +18,8 @@ import com.cobblemon.mod.common.api.battles.model.actor.BattleActor
* @since November 3rd, 2022
*/
data class BattleVictoryEvent (
val battle: PokemonBattle,
val winners : List<BattleActor>
)
override val battle: PokemonBattle,
val winners : List<BattleActor>,
val losers : List<BattleActor>,
val wasWildCapture : Boolean
) : BattleEvent
@@ -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.events.entity
import net.minecraft.entity.EntityType
import net.minecraft.entity.attribute.DefaultAttributeContainer
/**
* Event fired when we're registering entity attributes. This is really just a hack to get
* attributes working on the Forge side because I'm a dumbass and have no idea how to fix
* it properly.
*
* @author Hiroku
* @since February 20th, 2022
*/
class EntityAttributeEvent(val entityType: EntityType<*>, val attributeSupplier: DefaultAttributeContainer.Builder)
@@ -0,0 +1,24 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.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.context.SpawningContext
import net.minecraft.entity.Entity
/**
* Event fired when an entity is spawned using the [BestSpawner]. The entity that was spawned
* and the [SpawningContext] of the spawn are provided. Cancelling this event will prevent the
* entity from spawning.
*
* @author Hiroku
* @since April 22nd, 2023
*/
class SpawnEvent<T : Entity>(val entity: T, val ctx: SpawningContext) : Cancelable()
@@ -1,24 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.events.net
import com.cobblemon.mod.common.CobblemonNetwork
import com.cobblemon.mod.common.api.net.NetworkPacket
/**
* Fired when a new packet is being initialized and a handler should be applied. Internal use only!
*
* @author Hiroku
* @since November 27th, 2021
*/
class MessageBuiltEvent<T : NetworkPacket>(
val clazz: Class<T>,
val isToServer: Boolean,
val messageBuilder: CobblemonNetwork.PreparedMessage<T>
)
@@ -0,0 +1,21 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.events.pokeball
import com.cobblemon.mod.common.api.events.Cancelable
import com.cobblemon.mod.common.entity.pokeball.EmptyPokeBallEntity
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
/**
* Event fired when a thrown Pokeball hits a Pokémon. Cancelling this event prevents the capture being started.
*/
class ThrownPokeballHitEvent(
val pokeBall : EmptyPokeBallEntity,
val pokemon : PokemonEntity
) : Cancelable()
@@ -0,0 +1,29 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.events.pokemon
import com.cobblemon.mod.common.api.events.Cancelable
import com.cobblemon.mod.common.pokemon.Pokemon
import net.minecraft.server.network.ServerPlayerEntity
import net.minecraft.text.MutableText
/**
* Event fired when a player attempts to nickname a Pokémon. The nickname that will be applied can be edited, or
* the event itself can be cancelled to prevent the nickname from changing.
*
* If [nickname] is null, it means they're trying to remove the nickname.
*
* @author Hiroku
* @since April 22nd, 2023
*/
class PokemonNicknamedEvent(val player: ServerPlayerEntity, val pokemon: Pokemon, var nickname: MutableText?): Cancelable() {
/** A shortcut to using [nickname].getString(). Learn how Text works! */
val nicknameString: String?
get() = nickname?.string
}
@@ -0,0 +1,23 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.events.pokemon
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import com.cobblemon.mod.common.pokemon.Pokemon
/**
* Event fired when a [PokemonEntity] is recalled.
*
* @author Segfault Guy
* @since March 25th, 2023
*/
data class PokemonRecalledEvent (
val pokemon: Pokemon,
val oldEntity: PokemonEntity?
)
@@ -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.pokemon
import com.cobblemon.mod.common.api.events.Cancelable
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import com.cobblemon.mod.common.pokemon.Pokemon
import net.minecraft.server.world.ServerWorld
import net.minecraft.util.math.Vec3d
/**
* Event fired when a party [Pokemon] is sent out. Cancelling this event prevents a corresponding
* [PokemonEntity] from being instantiated and spawned into the world.
*
* @author Segfault Guy
* @since March 25th, 2023
*/
data class PokemonSentPreEvent(
val pokemon: Pokemon,
val level: ServerWorld,
val position: Vec3d
) : Cancelable()
/**
* Event fired after a [PokemonEntity] is spawned from a player's party and after its animations are finished.
* Only fired for party [Pokemon] sent out with animations.
*
* @author Segfault Guy
* @since March 25th, 2023
*/
data class PokemonSentPostEvent(
val pokemon: Pokemon,
val pokemonEntity: PokemonEntity
)
@@ -0,0 +1,33 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.events.world
import com.cobblemon.mod.common.api.events.Cancelable
import com.cobblemon.mod.common.block.BigRootBlock
import com.cobblemon.mod.common.block.EnergyRootBlock
import net.minecraft.block.BlockState
import net.minecraft.server.world.ServerWorld
import net.minecraft.util.math.BlockPos
/**
* Event fired when a [BigRootBlock] attempts to spread. The event includes the original root position
* as well as the position of the new root. [resultingSpread] controls whether the new root will be an
* [EnergyRootBlock]. The new root position and whether it is an energy root is mutable.
*
* Cancelling this event will prevent propagation from occurring.
*
* @since June 17th, 2023
* @author Hiroku
*/
class BigRootPropagatedEvent(
val world: ServerWorld,
val pos: BlockPos,
var newRootPosition: BlockPos,
var resultingSpread: BlockState
) : Cancelable()
@@ -18,6 +18,7 @@ import com.cobblemon.mod.common.pokemon.Species
import com.mojang.blaze3d.platform.GlStateManager
import com.mojang.blaze3d.systems.RenderSystem
import net.minecraft.client.MinecraftClient
import net.minecraft.client.gui.DrawContext
import net.minecraft.client.render.BufferRenderer
import net.minecraft.client.render.DiffuseLighting
import net.minecraft.client.render.GameRenderer
@@ -31,8 +32,9 @@ import net.minecraft.text.MutableText
import net.minecraft.text.OrderedText
import net.minecraft.text.Text
import net.minecraft.util.Identifier
import net.minecraft.util.math.Matrix4f
import net.minecraft.util.math.Vec3f
import net.minecraft.util.math.RotationAxis
import org.joml.Matrix4f
import org.joml.Vector3f
fun blitk(
matrixStack: MatrixStack,
@@ -53,7 +55,7 @@ fun blitk(
blend: Boolean = true,
scale: Float = 1F
) {
RenderSystem.setShader { GameRenderer.getPositionTexShader() }
RenderSystem.setShader { GameRenderer.getPositionTexProgram() }
texture?.run { RenderSystem.setShaderTexture(0, this) }
if (blend) {
RenderSystem.enableBlend()
@@ -71,6 +73,7 @@ fun blitk(
vOffset.toFloat() / textureHeight.toFloat(), (vOffset.toFloat() + height.toFloat()) / textureHeight.toFloat()
)
matrixStack.pop()
RenderSystem.setShaderColor(1f, 1f, 1f, 1f)
}
fun drawRectangle(
@@ -93,11 +96,11 @@ fun drawRectangle(
bufferbuilder.vertex(matrix, x, y, blitOffset).texture(minU, minV).next()
// TODO: Figure out if this is correct replacement.
// OLD: BufferRenderer.draw(bufferbuilder)
BufferRenderer.drawWithShader(bufferbuilder.end())
BufferRenderer.drawWithGlobalProgram(bufferbuilder.end())
}
fun drawCenteredText(
poseStack: MatrixStack,
context: DrawContext,
font: Identifier? = null,
text: Text,
x: Number,
@@ -106,15 +109,12 @@ fun drawCenteredText(
shadow: Boolean = true
) {
val comp = (text as MutableText).let { if (font != null) it.font(font) else it }
val mcFont = MinecraftClient.getInstance().textRenderer
if (shadow)
mcFont.drawWithShadow(poseStack, comp, x.toFloat() - mcFont.getWidth(comp) / 2, y.toFloat(), colour)
else
mcFont.draw(poseStack, comp, x.toFloat() - mcFont.getWidth(comp) / 2, y.toFloat(), colour)
val textRenderer = MinecraftClient.getInstance().textRenderer
context.drawText(textRenderer, comp, x.toInt() - textRenderer.getWidth(comp) / 2, y.toInt(), colour, shadow)
}
fun drawText(
poseStack: MatrixStack,
context: DrawContext,
font: Identifier? = null,
text: MutableText,
x: Number,
@@ -124,22 +124,17 @@ fun drawText(
shadow: Boolean = true
) {
val comp = if (font == null) text else text.setStyle(text.style.withFont(font))
val mcFont = MinecraftClient.getInstance().textRenderer
val textRenderer = MinecraftClient.getInstance().textRenderer
var x = x
if (centered) {
val width = mcFont.getWidth(comp)
val width = textRenderer.getWidth(comp)
x = x.toDouble() - width / 2
}
if (shadow) {
mcFont.drawWithShadow(poseStack, comp, x.toFloat(), y.toFloat(), colour)
} else {
mcFont.draw(poseStack, comp, x.toFloat(), y.toFloat(), colour)
}
context.drawText(textRenderer, comp, x.toInt(), y.toInt(), colour, shadow)
}
fun drawText(
poseStack: MatrixStack,
context: DrawContext,
text: OrderedText,
x: Number,
y: Number,
@@ -147,21 +142,17 @@ fun drawText(
colour: Int,
shadow: Boolean = true
) {
val mcFont = MinecraftClient.getInstance().textRenderer
var x = x
val textRenderer = MinecraftClient.getInstance().textRenderer
var tweakedX = x
if (centered) {
val width = mcFont.getWidth(text)
x = x.toDouble() - width / 2
val width = textRenderer.getWidth(text)
tweakedX = tweakedX.toDouble() - width / 2
}
if (shadow)
mcFont.drawWithShadow(poseStack, text, x.toFloat(), y.toFloat(), colour)
else
mcFont.draw(poseStack, text, x.toFloat(), y.toFloat(), colour)
context.drawText(textRenderer, text, tweakedX.toInt(), y.toInt(), colour, shadow)
}
fun drawString(
poseStack: MatrixStack,
context: DrawContext,
text: String,
x: Number,
y: Number,
@@ -174,11 +165,8 @@ fun drawString(
it.getWithStyle(it.style.withFont(this))
}
}
val mcFont = MinecraftClient.getInstance().textRenderer
if (shadow)
mcFont.drawWithShadow(poseStack, comp, x.toFloat(), y.toFloat(), colour)
else
mcFont.draw(poseStack, comp, x.toFloat(), y.toFloat(), colour)
val textRenderer = MinecraftClient.getInstance().textRenderer
context.drawText(textRenderer, comp, x.toInt(), y.toInt(), colour, shadow)
}
fun drawPortraitPokemon(
@@ -187,7 +175,8 @@ fun drawPortraitPokemon(
matrixStack: MatrixStack,
scale: Float = 13F,
reversed: Boolean = false,
state: PoseableEntityState<PokemonEntity>? = null
state: PoseableEntityState<PokemonEntity>? = null,
partialTicks: Float
) {
val model = PokemonModelRepository.getPoser(species.resourceIdentifier, aspects)
val texture = PokemonModelRepository.getTexture(species.resourceIdentifier, aspects, state)
@@ -195,14 +184,15 @@ fun drawPortraitPokemon(
val renderType = model.getLayer(texture)
RenderSystem.applyModelViewMatrix()
val quaternion1 = Vec3f.POSITIVE_Y.getDegreesQuaternion(-32F * if (reversed) -1F else 1F)
val quaternion2 = Vec3f.POSITIVE_X.getDegreesQuaternion(5F)
val quaternion1 = RotationAxis.POSITIVE_Y.rotationDegrees(-32F * if (reversed) -1F else 1F)
val quaternion2 = RotationAxis.POSITIVE_X.rotationDegrees(5F)
if (state == null) {
model.setupAnimStateless(setOf(PoseType.PORTRAIT, PoseType.PROFILE))
} else {
model.getPose(PoseType.PORTRAIT)?.let { state.setPose(it.poseName) }
state.timeEnteredPose = 0F
state.updatePartialTicks(partialTicks)
model.setupAnimStateful(null, state, 0F, 0F, 0F, 0F, 0F)
}
@@ -211,12 +201,12 @@ fun drawPortraitPokemon(
matrixStack.scale(scale, scale, -scale)
matrixStack.translate(0.0, -PORTRAIT_DIAMETER / 18.0, 0.0)
matrixStack.translate(model.portraitTranslation.x * if (reversed) -1F else 1F, model.portraitTranslation.y, model.portraitTranslation.z - 4)
matrixStack.scale(model.portraitScale, model.portraitScale, 0.1F)
matrixStack.scale(model.portraitScale, model.portraitScale, 1 / model.portraitScale)
matrixStack.multiply(quaternion1)
matrixStack.multiply(quaternion2)
val light1 = Vec3f(0.2F, 1.0F, -1.0F)
val light2 = Vec3f(0.1F, 0.0F, 8.0F)
val light1 = Vector3f(0.2F, 1.0F, -1.0F)
val light2 = Vector3f(0.1F, 0.0F, 8.0F)
RenderSystem.setShaderLights(light1, light2)
quaternion1.conjugate()
@@ -10,6 +10,7 @@ package com.cobblemon.mod.common.api.gui
import java.util.stream.Collectors
import net.minecraft.client.MinecraftClient
import net.minecraft.client.gui.DrawContext
import net.minecraft.client.util.math.MatrixStack
import net.minecraft.text.StringVisitable
import net.minecraft.text.Style
@@ -38,7 +39,7 @@ class MultiLineLabelK(
}
fun renderLeftAligned(
poseStack: MatrixStack,
context: DrawContext,
x: Number, y: Number,
ySpacing: Number,
colour: Int,
@@ -46,7 +47,7 @@ class MultiLineLabelK(
) {
comps.forEachIndexed { index, textWithWidth ->
drawString(
poseStack = poseStack,
context = context,
x = x, y = y.toFloat() + ySpacing.toFloat() * index,
colour = colour,
shadow = shadow,
@@ -91,7 +91,7 @@ abstract class ParentWidget(
return super.charTyped(pCodePoint, pModifiers)
}
override fun appendNarrations(pNarrationElementOutput: NarrationMessageBuilder) {
override fun appendDefaultNarrations(pNarrationElementOutput: NarrationMessageBuilder) {
}
/**
@@ -106,4 +106,6 @@ abstract class ParentWidget(
*/
fun ishHovered(mouseX: Number, mouseY: Number) = mouseX in this.x..(this.x + this.width) && mouseY in this.y..(this.y + this.height)
override fun appendClickableNarrations(builder: NarrationMessageBuilder) {}
}
@@ -0,0 +1,149 @@
/*
* 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.item
import com.cobblemon.mod.common.api.battles.model.actor.BattleActor
import com.cobblemon.mod.common.api.callback.MoveSelectCallbacks
import com.cobblemon.mod.common.api.callback.PartyMoveSelectCallbacks
import com.cobblemon.mod.common.api.moves.Move
import com.cobblemon.mod.common.api.text.red
import com.cobblemon.mod.common.battles.BagItemActionResponse
import com.cobblemon.mod.common.battles.pokemon.BattlePokemon
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import com.cobblemon.mod.common.item.battle.BagItem
import com.cobblemon.mod.common.pokemon.Pokemon
import com.cobblemon.mod.common.util.battleLang
import com.cobblemon.mod.common.util.getBattleState
import com.cobblemon.mod.common.util.isHeld
import com.cobblemon.mod.common.util.isLookingAt
import com.cobblemon.mod.common.util.party
import net.minecraft.item.ItemStack
import net.minecraft.server.network.ServerPlayerEntity
import net.minecraft.util.TypedActionResult
import net.minecraft.util.math.Box
/**
* Interface to make it easier to define items that will, upon use, prompt you to
* select a Pokémon and move for the item to be used on. This can be by interacting
* with the Pokémon directly (which will skip the Pokémon selection screen) or by
* interacting with air which will first show a Pokémon selection screen.
*
* @author Hiroku
* @since July 29th, 2023
*/
interface PokemonAndMoveSelectingItem {
fun use(player: ServerPlayerEntity, stack: ItemStack): TypedActionResult<ItemStack>? {
val entity = player.world
.getOtherEntities(player, Box.of(player.pos, 16.0, 16.0, 16.0))
.filter { player.isLookingAt(it, stepDistance = 0.1F) }
.minByOrNull { it.distanceTo(player) } as? PokemonEntity?
player.getBattleState()?.let { (_, actor) ->
if (bagItem == null) {
return TypedActionResult.fail(stack)
}
if (!actor.canFitForcedAction()) {
player.sendMessage(battleLang("bagitem.cannot").red())
return TypedActionResult.fail(stack)
}
val battlePokemon = actor.pokemonList.find { it.effectedPokemon == entity?.pokemon }
if (entity == null) {
return interactGeneralBattle(player, stack, actor)
} else if (battlePokemon != null) {
return interactWithSpecificBattle(player, stack, battlePokemon)
}
} ?: run {
if (entity != null) {
val pokemon = entity.pokemon
if (entity.ownerUuid == player.uuid) {
return interactWithSpecific(player, stack, pokemon)
} else {
return TypedActionResult.fail(stack)
}
} else {
return interactGeneral(player, stack)
}
}
return null
}
val bagItem: BagItem?
fun applyToPokemon(player: ServerPlayerEntity, stack: ItemStack, pokemon: Pokemon, move: Move)
fun applyToBattlePokemon(player: ServerPlayerEntity, stack: ItemStack, battlePokemon: BattlePokemon, move: Move) {
val battle = battlePokemon.actor.battle
val bagItem = bagItem
if (!battlePokemon.actor.canFitForcedAction()) {
player.sendMessage(battleLang("bagitem.cannot").red())
} else if (!bagItem!!.canUse(battle, battlePokemon)) {
player.sendMessage(battleLang("bagitem.invalid").red())
} else {
battlePokemon.actor.forceChoose(BagItemActionResponse(bagItem, battlePokemon, move.template.name))
if (!player.isCreative) {
stack.decrement(1)
}
}
}
fun canUseOnPokemon(pokemon: Pokemon): Boolean
fun canUseOnBattlePokemon(battlePokemon: BattlePokemon): Boolean = bagItem!!.canUse(battlePokemon.actor.battle, battlePokemon)
fun canUseOnMove(pokemon: Pokemon, move: Move): Boolean = canUseOnMove(move)
fun canUseOnMove(move: Move): Boolean
fun interactWithSpecific(player: ServerPlayerEntity, stack: ItemStack, pokemon: Pokemon): TypedActionResult<ItemStack>? {
MoveSelectCallbacks.create(
player = player,
moves = pokemon.moveSet.toList(),
canSelect = ::canUseOnMove,
handler = { move -> if (stack.isHeld(player)) applyToPokemon(player, stack, pokemon, move) }
)
return TypedActionResult.success(stack)
}
fun interactWithSpecificBattle(player: ServerPlayerEntity, stack: ItemStack, battlePokemon: BattlePokemon): TypedActionResult<ItemStack>? {
return if (canUseOnBattlePokemon(battlePokemon)) {
MoveSelectCallbacks.create(
player = player,
moves = battlePokemon.moveSet.getMoves(),
canSelect = ::canUseOnMove,
handler = { applyToBattlePokemon(player, stack, battlePokemon, it) }
)
TypedActionResult.success(stack)
} else {
player.sendMessage(battleLang("bagitem.invalid").red())
TypedActionResult.fail(stack)
}
}
fun interactGeneral(player: ServerPlayerEntity, stack: ItemStack): TypedActionResult<ItemStack>? {
PartyMoveSelectCallbacks.createFromPokemon(
player = player,
pokemon = player.party().toList(),
canSelectPokemon = ::canUseOnPokemon,
canSelectMove = ::canUseOnMove,
handler = { pk, mv -> if (stack.isHeld(player)) applyToPokemon(player, stack, pk, mv) }
)
return TypedActionResult.success(stack)
}
fun interactGeneralBattle(player: ServerPlayerEntity, stack: ItemStack, actor: BattleActor): TypedActionResult<ItemStack>? {
PartyMoveSelectCallbacks.createFromPokemon(
player = player,
pokemon = actor.pokemonList.map { it.effectedPokemon },
moves = { pk -> actor.pokemonList.find { it.effectedPokemon == pk }!!.moveSet.getMoves() },
canSelectPokemon = { pk -> canUseOnBattlePokemon(actor.pokemonList.find { it.effectedPokemon == pk }!!) },
canSelectMove = ::canUseOnMove,
handler = { pk, mv -> applyToBattlePokemon(player, stack, actor.pokemonList.find { it.effectedPokemon == pk }!!, mv) }
)
return TypedActionResult.success(stack)
}
}
@@ -0,0 +1,136 @@
/*
* 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.item
import com.cobblemon.mod.common.api.battles.model.actor.BattleActor
import com.cobblemon.mod.common.api.callback.PartySelectCallbacks
import com.cobblemon.mod.common.api.text.red
import com.cobblemon.mod.common.battles.BagItemActionResponse
import com.cobblemon.mod.common.battles.pokemon.BattlePokemon
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import com.cobblemon.mod.common.item.battle.BagItem
import com.cobblemon.mod.common.pokemon.Pokemon
import com.cobblemon.mod.common.util.battleLang
import com.cobblemon.mod.common.util.getBattleState
import com.cobblemon.mod.common.util.isHeld
import com.cobblemon.mod.common.util.isLookingAt
import com.cobblemon.mod.common.util.party
import net.minecraft.item.ItemStack
import net.minecraft.server.network.ServerPlayerEntity
import net.minecraft.util.TypedActionResult
import net.minecraft.util.math.Box
/**
* Interface to make it easier to define items that will, upon use, prompt you to
* select a Pokémon for it to be used on. This can be by interacting with the Pokémon
* directly (which will skip the Pokémon selection screen) or by interacting with air
* which will first show a Pokémon selection screen.
*
* Works for battle items too.
*
* @author Hiroku
* @since July 29th, 2023
*/
interface PokemonSelectingItem {
fun use(player: ServerPlayerEntity, stack: ItemStack): TypedActionResult<ItemStack> {
val entity = player.world
.getOtherEntities(player, Box.of(player.pos, 16.0, 16.0, 16.0))
.filter { player.isLookingAt(it, stepDistance = 0.1F) }
.minByOrNull { it.distanceTo(player) } as? PokemonEntity?
player.getBattleState()?.let { (_, actor) ->
if (bagItem == null) return TypedActionResult.fail(stack)
val battlePokemon = actor.pokemonList.find { it.effectedPokemon == entity?.pokemon }
if (!actor.canFitForcedAction()) {
player.sendMessage(battleLang("bagitem.cannot").red())
return TypedActionResult.fail(stack)
}
if (entity == null) {
return interactGeneralBattle(player, stack, actor)
} else if (battlePokemon != null) {
return interactWithSpecificBattle(player, stack, battlePokemon)
}
} ?: run {
if (entity != null) {
val pokemon = entity.pokemon
if (entity.ownerUuid == player.uuid) {
return applyToPokemon(player, stack, pokemon) ?: TypedActionResult.pass(stack)
} else {
return TypedActionResult.fail(stack)
}
} else {
return interactGeneral(player, stack)
}
}
return TypedActionResult.pass(stack)
}
val bagItem: BagItem?
fun applyToPokemon(player: ServerPlayerEntity, stack: ItemStack, pokemon: Pokemon): TypedActionResult<ItemStack>?
fun applyToBattlePokemon(player: ServerPlayerEntity, stack: ItemStack, battlePokemon: BattlePokemon) {
val battle = battlePokemon.actor.battle
val bagItem = bagItem
if (!battlePokemon.actor.canFitForcedAction()) {
player.sendMessage(battleLang("bagitem.cannot").red())
} else if (!bagItem!!.canUse(battle, battlePokemon)) {
player.sendMessage(battleLang("bagitem.invalid").red())
} else {
battlePokemon.actor.forceChoose(BagItemActionResponse(bagItem, battlePokemon))
if (!player.isCreative) {
stack.decrement(1)
}
}
}
fun canUseOnPokemon(pokemon: Pokemon): Boolean
fun canUseOnBattlePokemon(battlePokemon: BattlePokemon): Boolean = bagItem!!.canUse(battlePokemon.actor.battle, battlePokemon)
fun interactWithSpecificBattle(player: ServerPlayerEntity, stack: ItemStack, battlePokemon: BattlePokemon): TypedActionResult<ItemStack> {
return if (canUseOnBattlePokemon(battlePokemon)) {
applyToBattlePokemon(player, stack, battlePokemon)
TypedActionResult.success(stack)
} else {
player.sendMessage(battleLang("bagitem.invalid").red())
TypedActionResult.fail(stack)
}
}
fun interactGeneral(player: ServerPlayerEntity, stack: ItemStack): TypedActionResult<ItemStack> {
PartySelectCallbacks.createFromPokemon(
player = player,
pokemon = player.party().toList(),
canSelect = ::canUseOnPokemon,
handler = { pk ->
if (stack.isHeld(player)) {
applyToPokemon(player, stack, pk)
if (!player.isCreative) {
stack.decrement(1)
}
}
}
)
return TypedActionResult.success(stack)
}
fun interactGeneralBattle(player: ServerPlayerEntity, stack: ItemStack, actor: BattleActor): TypedActionResult<ItemStack> {
PartySelectCallbacks.createBattleSelect(
player = player,
pokemon = actor.pokemonList,
canSelect = { pk -> canUseOnBattlePokemon(actor.pokemonList.find { it.effectedPokemon == pk.effectedPokemon }!!) },
handler = { pk -> applyToBattlePokemon(player, stack, actor.pokemonList.find { it.effectedPokemon == pk.effectedPokemon }!!) }
)
return TypedActionResult.success(stack)
}
}
@@ -16,6 +16,7 @@ import com.cobblemon.mod.common.util.DataKeys
import com.cobblemon.mod.common.util.readSizedInt
import com.cobblemon.mod.common.util.writeSizedInt
import com.google.gson.JsonObject
import kotlin.math.ceil
import kotlin.properties.Delegates
import net.minecraft.nbt.NbtCompound
import net.minecraft.network.PacketByteBuf
@@ -29,17 +30,31 @@ open class Move(
currentPp: Int,
raisedPpStages: Int = 0
) {
private var emit = true
val observable = SimpleObservable<Move>()
var currentPp: Int by Delegates.observable(currentPp) { _, oldValue, newValue ->
if (oldValue != newValue) {
observable.emit(this)
update()
}
}
var raisedPpStages: Int by Delegates.observable(raisedPpStages) { _, oldValue, newValue ->
if (oldValue != newValue) {
update()
}
}
fun doThenUpdate(action: () -> Unit) {
val oldEmit = emit
emit = false
action()
emit = oldEmit
update()
}
fun update() {
if (emit) {
observable.emit(this)
}
}
@@ -71,6 +86,20 @@ open class Move(
val maxPp: Int
get() = template.pp + raisedPpStages * template.pp / 5
/** Raises the max PP and rescales the current PP value. Returns false if it was already maxed out. */
fun raiseMaxPP(amount: Int): Boolean {
val oldPp = maxPp
doThenUpdate {
val ppRatio = currentPp / maxPp.toFloat()
raisedPpStages += amount
if (raisedPpStages > 3) {
raisedPpStages = 3
}
currentPp = ceil(ppRatio * maxPp).toInt()
}
return oldPp != maxPp
}
fun saveToNBT(nbt: NbtCompound): NbtCompound {
nbt.putString(DataKeys.POKEMON_MOVESET_MOVENAME, name)
nbt.putInt(DataKeys.POKEMON_MOVESET_MOVEPP, currentPp)
@@ -128,6 +128,7 @@ class MoveSet : Iterable<Move> {
observable.emit(this)
}
}
fun doWithoutEmitting(action: () -> Unit) {
val previousEmit = emit
emit = false
@@ -38,7 +38,7 @@ object Moves : DataRegistry {
override fun reload(manager: ResourceManager) {
this.allMoves.clear()
this.idMapping.clear()
val movesJson = ShowdownService.get().getMoves()
val movesJson = ShowdownService.service.getMoves()
for (i in 0 until movesJson.size()) {
val jsMove = movesJson[i].asJsonObject
val id = jsMove.get("id").asString
@@ -34,7 +34,7 @@ object DamageCategories {
fun register(
name: String,
displayName: Text,
resourceLocation: Identifier = cobblemonResource("ui/categories.png"),
resourceLocation: Identifier = cobblemonResource("textures/gui/categories.png"),
textureXMultiplier: Int
): DamageCategory {
return DamageCategory(
@@ -23,6 +23,6 @@ class DamageCategory(
val name: String,
val displayName: Text,
val textureXMultiplier: Int,
val resourceLocation: Identifier = cobblemonResource("ui/categories.png")
val resourceLocation: Identifier = cobblemonResource("textures/gui/categories.png")
) {
}
@@ -0,0 +1,45 @@
/*
* 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.mulch
import com.cobblemon.mod.common.CobblemonItems
import com.cobblemon.mod.common.item.MulchItem
/**
* Represents the different types of Mulch implemented in the mod.
*
*/
enum class MulchVariant {
COARSE,
GROWTH,
HUMID,
LOAMY,
PEAT,
RICH,
SANDY,
SURPRISE;
/**
* Resolves the item version of the Mulch.
*
* @return The [MulchItem] equivalent.
*/
fun item(): MulchItem = when (this) {
COARSE -> CobblemonItems.COARSE_MULCH
GROWTH -> CobblemonItems.GROWTH_MULCH
HUMID -> CobblemonItems.HUMID_MULCH
LOAMY -> CobblemonItems.LOAMY_MULCH
PEAT -> CobblemonItems.PEAT_MULCH
RICH -> CobblemonItems.RICH_MULCH
SANDY -> CobblemonItems.SANDY_MULCH
SURPRISE -> CobblemonItems.SURPRISE_MULCH
}
}
@@ -0,0 +1,45 @@
/*
* 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.mulch
import net.minecraft.block.BlockState
import net.minecraft.server.world.ServerWorld
import net.minecraft.util.math.BlockPos
import net.minecraft.util.math.random.Random
/**
* Represents something that can have mulch applied to it.
* Typically, this will be a block implementation.
*/
interface Mulchable {
/**
* Checks if mulch can be applied to a specific spot in the world.
*
* @param world The affected [ServerWorld].
* @param pos The [BlockPos] being checked.
* @param state The [BlockState] of the block at the [pos] in the [world].
* @param variant The [MulchVariant] being applied.
* @return If the application is possible.
*/
fun canHaveMulchApplied(world: ServerWorld, pos: BlockPos, state: BlockState, variant: MulchVariant): Boolean
/**
* Applies the mulch to the specified spot.
* This is expected to be invoked if [canHaveMulchApplied] is true.
*
* @param world The affected [ServerWorld].
* @param random The [Random] instance being used in the interaction.
* @param pos The [BlockPos] being checked.
* @param state The [BlockState] of the block at the [pos] in the [world].
* @param variant The [MulchVariant] being applied.
*/
fun applyMulch(world: ServerWorld, random: Random, pos: BlockPos, state: BlockState, variant: MulchVariant)
}
@@ -0,0 +1,21 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.net
import net.minecraft.client.MinecraftClient
interface ClientNetworkPacketHandler<T: NetworkPacket<T>> {
fun handle(packet: T, client: MinecraftClient)
fun handleOnNettyThread(packet: T) {
val client = MinecraftClient.getInstance()
client.execute { handle(packet, client) }
}
}
@@ -9,33 +9,71 @@
package com.cobblemon.mod.common.api.net
import com.cobblemon.mod.common.CobblemonNetwork
import com.cobblemon.mod.common.util.getServer
import com.cobblemon.mod.common.util.server
import io.netty.buffer.Unpooled
import net.minecraft.network.PacketByteBuf
import net.minecraft.registry.RegistryKey
import net.minecraft.server.network.ServerPlayerEntity
import net.minecraft.util.registry.RegistryKey
import net.minecraft.util.Identifier
import net.minecraft.world.World
/*
* Simple packet interface to make a more traditional layout for netcode
/**
* Platform abstract blueprint of a packet being sent out.
* The handling of encoding, decoding and resolving the packet is done on the individual platform implementations.
*
* @author Hiroku
* @author Hiroku, Licious
* @since November 27th, 2021
*/
interface NetworkPacket {
fun encode(buffer: PacketByteBuf)
fun decode(buffer: PacketByteBuf)
interface NetworkPacket<T: NetworkPacket<T>> : Encodable {
fun sendToPlayer(player: ServerPlayerEntity) = CobblemonNetwork.sendToPlayer(player, this)
/**
*
*/
val id: Identifier
/**
* TODO
*
* @param player
*/
fun sendToPlayer(player: ServerPlayerEntity) = CobblemonNetwork.sendPacketToPlayer(player, this)
/**
* TODO
*
* @param players
*/
fun sendToPlayers(players: Iterable<ServerPlayerEntity>) {
if (players.any()) {
CobblemonNetwork.sendToPlayers(players, this)
CobblemonNetwork.sendPacketToPlayers(players, this)
}
}
/**
* TODO
*
*/
fun sendToAllPlayers() = CobblemonNetwork.sendToAllPlayers(this)
fun sendToServer() = CobblemonNetwork.sendToServer(this)
/**
* TODO
*
*/
fun sendToServer() = CobblemonNetwork.sendPacketToServer(this)
// A copy from PlayerManager#sendToAround to work with our packets
/**
* TODO
*
* @param x
* @param y
* @param z
* @param distance
* @param worldKey
* @param exclusionCondition
*/
fun sendToPlayersAround(x: Double, y: Double, z: Double, distance: Double, worldKey: RegistryKey<World>, exclusionCondition: (ServerPlayerEntity) -> Boolean = { false }) {
val server = getServer() ?: return
val server = server() ?: return
server.playerManager.playerList.filter { player ->
if (exclusionCondition.invoke(player))
return@filter false
@@ -44,6 +82,18 @@ interface NetworkPacket {
val zDiff = z - player.z
return@filter (xDiff * xDiff + yDiff * yDiff + zDiff) < distance * distance
}
.forEach { player -> CobblemonNetwork.sendToPlayer(player, this) }
.forEach { player -> CobblemonNetwork.sendPacketToPlayer(player, this) }
}
/**
* TODO
*
* @return
*/
fun toBuffer(): PacketByteBuf {
val buffer = PacketByteBuf(Unpooled.buffer())
this.encode(buffer)
return buffer
}
}
@@ -0,0 +1,21 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.net
import net.minecraft.server.MinecraftServer
import net.minecraft.server.network.ServerPlayerEntity
interface ServerNetworkPacketHandler<T: NetworkPacket<T>> {
fun handle(packet: T, server: MinecraftServer, player: ServerPlayerEntity)
fun handleOnNettyThread(packet: T, server: MinecraftServer, player: ServerPlayerEntity) {
server.execute { handle(packet, server, player) }
}
}
@@ -0,0 +1,18 @@
/*
* 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.pasture
import com.cobblemon.mod.common.Cobblemon
import java.util.UUID
import net.minecraft.util.Identifier
import net.minecraft.util.math.BlockPos
class PastureLink(val linkId: UUID, val pcId: UUID, val dimension: Identifier, val pos: BlockPos, val permissions: PasturePermissions) {
fun getPC() = Cobblemon.storage.getPC(pcId)
}
@@ -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.api.pasture
import com.cobblemon.mod.common.CobblemonNetwork.sendPacket
import com.cobblemon.mod.common.net.messages.client.pasture.ClosePasturePacket
import com.cobblemon.mod.common.util.getPlayer
import com.cobblemon.mod.common.util.removeIf
import java.util.UUID
import net.minecraft.server.network.ServerPlayerEntity
import net.minecraft.server.world.ServerWorld
import net.minecraft.util.math.BlockPos
// Need to use this in the interact with pasture block then use links when handling server-side packets
// to authenticate that they were able to interact.
object PastureLinkManager {
// Maps player UUID
val links = mutableMapOf<UUID, PastureLink>()
fun getLinkByPlayerId(playerId: UUID) = links[playerId]
fun createLink(playerId: UUID, link: PastureLink) {
links[playerId] = link
}
fun getLinkByPlayer(player: ServerPlayerEntity): PastureLink? {
val link = getLinkByPlayerId(player.uuid)
if (link != null) {
if (link.dimension != player.world.dimensionKey.value || !link.pos.isWithinDistance(player.pos, 10.0)) {
links.remove(player.uuid)
return null
}
}
return link
}
fun removeAt(world: ServerWorld, pos: BlockPos) {
links.removeIf { (uuid, pastureLink) ->
val shouldRemove = pastureLink.dimension == world.dimensionKey.value && pastureLink.pos == pos
uuid.getPlayer()?.sendPacket(ClosePasturePacket())
return@removeIf shouldRemove
}
}
}
@@ -0,0 +1,23 @@
/*
* 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.pasture
import com.cobblemon.mod.common.block.entity.PokemonPastureBlockEntity
import net.minecraft.server.network.ServerPlayerEntity
/**
* Interface for a route to which a player might be permitted to use a pasture block. This is registered
* in [PasturePermissionControllers] with a priority.
*
* @author Hiroku
* @since July 2nd, 2023
*/
fun interface PasturePermissionController {
fun permit(player: ServerPlayerEntity, pastureBlockEntity: PokemonPastureBlockEntity): PasturePermissions?
}

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