Compare commits

..
Author SHA1 Message Date
Waldleufer fde8a03c5f more cleanup [skip-ci] 2024-06-18 19:31:29 +02:00
Waldleufer df273a0075 cleanup [skip-ci] 2024-06-18 19:25:39 +02:00
Hiroku f6124d7474 Merge branch 'initiate_battle_while_recalling_bugfix' into 'main'
Fixes issue #872

Closes #872

See merge request cable-mc/cobblemon!1072
2024-06-16 08:07:16 +00:00
Notepadccino a0300ccd18 Update CHANGELOG.md 2024-06-16 08:05:22 +00:00
notepadccino 486056d7f0 Fixes issue #872 2024-06-14 16:52:12 +02:00
Hiroku 03ca6a4396 Merge branch 'tmetcalfe89/fix-energy-root-reviving' into 'main'
fixed energy root reviving

See merge request cable-mc/cobblemon!1065
2024-06-14 04:13:20 +00:00
Hiroku b2d26abc4b Merge branch 'Fixes901' into 'main'
Fix For 901

Closes #901

See merge request cable-mc/cobblemon!1069
2024-06-14 00:32:08 +00:00
JazzMcNade ebb677cc9c Don't read the current hp until you've fully calculated the max hp 2024-06-09 14:53:28 -05:00
Licious f181aabb3c Merge branch 'fix-898' into 'main'
Fix lack of side check when instancing Pokemon on PokemonEntity

Closes #898

See merge request cable-mc/cobblemon!1068
2024-06-09 17:43:34 +00:00
Licious 4df5e987c7 Fix lack of side check when instancing Pokemon on PokemonEntity 2024-06-09 17:43:33 +00:00
tmetcalfe89 3026e5c66f changelog 2024-06-09 10:39:43 -07:00
tmetcalfe89 f2310d8979 Merge branch 'main' of https://gitlab.com/cable-mc/cobblemon into tmetcalfe89/fix-energy-root-reviving 2024-06-09 10:39:22 -07:00
Hiroku 65971386f2 Merge branch 'Myslippy-main-patch-82434' into 'main'
Update CHANGELOG.md

See merge request cable-mc/cobblemon!1062
2024-06-08 21:27:17 +00:00
tmetcalfe89 5b52fe5479 fixed energy root reviving 2024-06-07 08:08:19 -07:00
Hiroku 13ca5871cb Merge branch 'corals_restoration_tank_bugfix' into 'main'
Fix issue #892

Closes #892

See merge request cable-mc/cobblemon!1064
2024-06-05 21:48:10 +00:00
notepadccino 54ba99a002 Fix issue #892
The #minecraft:corals tag seems to apply to blocks, not to items. For items you'd either need to trace back the tags of whichever block is placed by the item, or just specify the items one by one. I went with the simpler option, but if needed the former solution can always be implemented.
2024-06-05 19:11:08 +02:00
Myslippy b40f47b00d Update CHANGELOG.md 2024-06-03 03:00:34 +00:00
Hiroku 800d348611 Merge branch 'mushroom_restoration_fabric_fix' into 'main'
Fix #890

Closes #890

See merge request cable-mc/cobblemon!1059
2024-06-03 00:04:49 +00:00
Hiroku d4dd48b3ff Merge branch 'implement_pokemon' into 'main'
5 new cries + bugfix

See merge request cable-mc/cobblemon!1061
2024-06-02 23:31:48 +00:00
Sterrezo 89d6bb2356 Merge branch 'main' into implement_pokemon 2024-06-02 21:48:03 +02:00
notepadccino 3a65425015 Fix mushroom tag issue
the #minecraft:mushrooms tag is a forge thing, it doesn't exist in fabric.
However I've tested out corals as well and they don't work either which is odd, since they should have a #minecraft:corals tag
2024-06-02 18:21:47 +02:00
Apion fad10da89f Merge branch 'forcespawn_cmd_fix' into 'main'
Fixes #877

Closes #877

See merge request cable-mc/cobblemon!1056
2024-06-01 15:19:06 +00:00
notepadccino 055ce8168c Fixes #877 2024-06-01 15:42:21 +02:00
Hiroku e4da05fd50 we are snapshotting thx 2024-06-01 00:24:30 +00:00
Paul 3a17a88ea2 Changelog stuff [skip-ci] 2024-06-01 09:38:50 +10:00
Hiroku 09abf30421 Merge branch 'no-middle-stage-ha-fix' into 'main'
Hidden Ability slot for cocoons.

See merge request cable-mc/cobblemon!1020
2024-05-31 23:38:18 +00:00
Hiroku 06ea4b4cec Merge branch 'berry-changes' into 'main'
Berry changes

See merge request cable-mc/cobblemon!1030
2024-05-31 23:35:59 +00:00
Hiroku 8799308800 Merge branch 'Frank's-Coding-Farm' into 'main'
Enabled Seafloor spawns & Disabled spawning in slabs

See merge request cable-mc/cobblemon!1040
2024-05-31 23:35:24 +00:00
Frank The FarmerandHiroku d727fde5b3 Enabled Seafloor spawns & Disabled spawning in slabs 2024-05-31 23:35:24 +00:00
Hiroku ce5e93b552 Merge branch 'main' into 'main'
Fixes #878

Closes #878

See merge request cable-mc/cobblemon!1052
2024-05-31 23:34:39 +00:00
Hiroku 77c0138c09 Merge branch 'get-sticked' into 'main'
Leeks are Sticks (visually)

See merge request cable-mc/cobblemon!1054
2024-05-31 23:34:25 +00:00
Sterrezo 0ded29dcad Added cries to Timburr and Golett lines. Updated the changelog with a recent Cubone sound fix. 2024-05-31 14:06:02 +02:00
Sterrezo 62fae979eb Merge branch 'main' into implement_pokemon 2024-05-31 13:40:42 +02:00
dhi_holo dc727fe56d Leeks are Sticks (visually)
Medicinal and Roasted Leeks now reference a new display setting, making them held like sticks/rods.

That's it, that's the entire change, it's a small parity thing, this is what I like doing, okay.
2024-05-31 10:19:06 +10:00
Apion 4db36ef6fa Merge branch 'tmetcalfe89/abstract-shedding' into 'main'
abstracted shedinja logic for datapackability

See merge request cable-mc/cobblemon!1014
2024-05-30 04:02:21 +00:00
Timothy MetcalfeandApion e350d920b5 abstracted shedinja logic for datapackability 2024-05-30 04:02:21 +00:00
Apion 2a0ae1a466 Merge branch 'tumbled-bricks' into 'main'
Tumbled Blocks and Bricks

See merge request cable-mc/cobblemon!1051
2024-05-30 02:58:57 +00:00
dhi_holoandApion 3b8f7f23a3 Tumbled Blocks and Bricks 2024-05-30 02:58:57 +00:00
apion 72cf161f0d Merge branch 'refs/heads/main' into berry-changes
# Conflicts:
#	CHANGELOG.md
2024-05-29 22:24:12 -04:00
apion fe3d8d3185 Changed CHANGELOG.md merge strategy 2024-05-29 22:06:53 -04:00
apion d04ed7a519 Add empty headers to CHANGELOG.md 2024-05-29 21:51:57 -04:00
Apion e6e9137cb5 Merge branch 'AmauraFetusClippingFix' into 'main'
Amaura fetus clipping fix

Closes #873

See merge request cable-mc/cobblemon!1053
2024-05-30 00:49:20 +00:00
JazzMcNade 78f25b3f8b Corrected typo in changelog 2024-05-28 17:25:08 -05:00
JazzMcNade 631293e0cd UpdatedChangelog 2024-05-28 17:10:20 -05:00
JazzMcNade 2865b8140a Scaled down Amaura's fetus model to avoid clipping through the tank while animating 2024-05-28 17:07:46 -05:00
notepadccino be34bc4c74 Fixes #878 2024-05-28 19:12:21 +02:00
Sterrezo bae26162dd Update cubone.animation.json 2024-05-28 12:09:35 +02:00
Paul df8f078d13 Fixed Wooloo Dubwool issues and fixed sync issues with Gimmighoul 2024-05-27 15:39:21 +10:00
Paul 309b223da9 Changelog update 4 [skip-ci] 2024-05-27 11:53:03 +10:00
Paul 75f688fa30 Changelog update 3 [skip-ci] 2024-05-27 11:48:22 +10:00
Paul d7fadd58ed Changelog update 2 [skip-ci] 2024-05-27 11:42:56 +10:00
Paul 996c7189b6 Changelog update [skip-ci] 2024-05-27 11:31:38 +10:00
Paul e1d5f07aed Fixed root part animations on JSON posers, clean up changelog, no snapshot, remove bubblebeam effect for now 2024-05-27 11:14:05 +10:00
Paul 6afe77ef0c Fixed confusion particle timing 2024-05-27 10:23:00 +10:00
Hiroku bf54f28b58 Merge branch 'move-effects' into 'main'
A bunch of particles, now with sound!

See merge request cable-mc/cobblemon!1049
2024-05-27 00:08:36 +00:00
Paul aac10e967f Reverted protect change to camera mode 2024-05-27 10:06:39 +10:00
Sterrezo 0cd9da80d7 Update sounds.json 2024-05-27 02:06:27 +02:00
Sterrezo d33f1150d2 Adjusted assets for powder moves, protect, swords dance and thunder wave. Rebalanced volumes of all moves. 2024-05-27 01:39:41 +02:00
Hiroku 216ed85da1 Merge branch 'IllusionThrownPokeballRevealFix' into 'main'
IllusionThrownPokeballRevealFix

See merge request cable-mc/cobblemon!1046
2024-05-26 23:35:07 +00:00
Paul 4b70b20ab7 Fixed using confusion breaking battles lol 2024-05-27 09:26:40 +10:00
Segfault Guy 125e193b81 Broadcast messages with CLIENT species on pokeball hit. 2024-05-26 19:17:16 -04:00
Paul 1ebd249351 Fixed sleeppowder effect, added redundancy to action effects in case they run into an exception 2024-05-27 09:08:22 +10:00
Segfault Guy 74727cda48 Merge branch 'main' into IllusionThrownPokeballRevealFix 2024-05-26 18:47:53 -04:00
Paul 6a8a2489d1 Fixed structure reference to cave_support not working 2024-05-27 08:27:59 +10:00
Paul 3524931596 Fixed dyeable Pokemon not being dyeable away from white unless spawned via command, fixed creative mode players still losing the dye 2024-05-27 07:06:57 +10:00
Paul 43d9347c9c Updated zh and es_es translations 2024-05-27 06:47:56 +10:00
Tyzillion 60303504cd Changelog update. 2024-05-26 11:52:30 -04:00
Tyzillion 63db0066d3 more sounds! 2024-05-26 11:49:50 -04:00
apion 6e0270ac80 Fully moved mulch into block entity 2024-05-26 11:31:21 -04:00
apion 30070d35f6 Fully moved mulch into block entity 2024-05-26 11:23:47 -04:00
apion 8e3435479a Start trying to move mulch into block entity 2024-05-26 09:39:57 -04:00
Tyzillion 333e1fe9ae Merge branch 'main' of https://gitlab.com/cable-mc/cobblemon into move-effects 2024-05-26 09:35:42 -04:00
Tyzillion c0c8c103f4 Updated changelog 2024-05-26 09:11:47 -04:00
Tyzillion a414784cca Added sounds to sand attack and the spore mushrooms, implemented confusion cuz I forgot to last night. 2024-05-26 09:10:41 -04:00
Apion b4b01ef0b6 Merge branch 'sound' into 'main'
Updated all generic impact assets

See merge request cable-mc/cobblemon!1048
2024-05-26 12:45:16 +00:00
SterrezoandApion 04f725d72e Updated all generic impact assets 2024-05-26 12:45:16 +00:00
Hiroku 0257f591de Merge branch 'implement_pokemon' into 'main'
Shedinja T Pose & Little guys sliding

See merge request cable-mc/cobblemon!1047
2024-05-26 11:40:35 +00:00
Frank The FarmerandHiroku dfeeed8796 Shedinja T Pose & Little guys sliding 2024-05-26 11:40:35 +00:00
Paul 0e304a81e8 Changelog, deleted unneeded caves template pool, licenses 2024-05-26 21:33:57 +10:00
Hiroku 03acc21af1 Merge branch 'move-effects' into 'main'
Implemented Action Effects

Closes #814, #773, #840, and #841

See merge request cable-mc/cobblemon!1045
2024-05-26 11:31:20 +00:00
Hiroku 2233e6903b Merge branch '1.5-structure-fixes' into 'main'
added loot to the trapped chest in unstable caves so you can't tell which one...

See merge request cable-mc/cobblemon!1042
2024-05-26 11:25:36 +00:00
Hiroku ac281faa3b Merge branch 'main' into 'move-effects'
# Conflicts:
#   CHANGELOG.md
2024-05-26 11:07:24 +00:00
FrankTheFarmer ad7a881fdc Changelog 2024-05-26 20:20:36 +10:00
FrankTheFarmer f9a2b5cc9c Fixed Budew and Lechonk sliding if they walked for too long 2024-05-26 20:17:47 +10:00
FrankTheFarmer e2cc006c7c Fixed Shedinja T posing in battle 2024-05-26 20:17:20 +10:00
FrankTheFarmer 13240d28ea Merge branch 'main' into implement_pokemon 2024-05-26 20:00:04 +10:00
JazzMcNade 6891272516 Throwing a ball at a player owned pokemon no longer reveals Illusion 2024-05-26 03:02:49 -05:00
Hiroku eba784071a Merge branch 'Primary-Quirks-for-JSON' into 'main'
Primary quirks for json

See merge request cable-mc/cobblemon!1044
2024-05-26 04:10:33 +00:00
Hiroku a4435af9c0 Merge branch 'GildedChestLockAnimFix' into 'main'
GildedChestLockAnimFix

Closes #811

See merge request cable-mc/cobblemon!1043
2024-05-26 04:08:22 +00:00
JazzMcNade 4b0b0f813e Merge branch 'main' into GildedChestLockAnimFix 2024-05-25 22:59:01 -05:00
JazzMcNade c32da0825c Updated Changelog 2024-05-25 22:47:39 -05:00
Tyzillion 803703b6a6 Updated changelog 2024-05-25 23:43:50 -04:00
Tyzillion 668914275e Added sounds to all the powder attacks. Tweaks and fixes. 2024-05-25 23:42:02 -04:00
FrankTheFarmer af90ff6733 Added excludedLabels 2024-05-26 13:07:16 +10:00
FrankTheFarmer c657c2ea68 CHANGELOG with example. 2024-05-26 11:27:58 +10:00
FrankTheFarmer 2f567830d4 Temporary function for bedrock quirks intended for 1.5.1 2024-05-26 11:07:14 +10:00
Tyzillion 569f3c624e Implemented Cotton guard. 2024-05-25 20:38:31 -04:00
Tyzillion f30be418f9 Merge branch 'main' of https://gitlab.com/cable-mc/cobblemon into move-effects
# Conflicts:
#	CHANGELOG.md
2024-05-25 20:38:13 -04:00
Tyzillion 2c50dc2d0c Implemented Ember, Powder moves, and updated other particles. Implemented Infatuation 2024-05-25 20:34:07 -04:00
Hiroku dde2e9f52a Merge branch 'fix/form-sync' into 'main'
Form Sync on Form Change Fix

See merge request cable-mc/cobblemon!1041
2024-05-26 00:02:40 +00:00
NickandHiroku 50a21d91e8 Form Sync on Form Change Fix 2024-05-26 00:02:40 +00:00
Tyzillion 58f3de13fa Implemented Ember, Powder moves, and updated other particles. 2024-05-25 13:55:44 -04:00
Tyzillion 8d67a3a909 Merge branch 'main' of https://gitlab.com/cable-mc/cobblemon into move-effects
# Conflicts:
#	CHANGELOG.md
2024-05-25 10:54:51 -04:00
JazzMcNade ad4cb8a290 Gilded Chest no longer animates to the open state on the client when the client fails to open a locked chest 2024-05-24 21:30:54 -05:00
Hiroku d9e5de5f97 Fixed pluralize usage for pose conditions 2024-05-24 22:35:48 +00:00
Hiroku e4a47af06d Merge branch 'sendout-bug' into 'main'
Fixed tiny bug, fixes #867

Closes #867

See merge request cable-mc/cobblemon!1037
2024-05-24 22:03:50 +00:00
Apion cc741c0478 Merge branch 'remulched' into 'main'
Cheap Mulch!

See merge request cable-mc/cobblemon!1039
2024-05-24 12:28:03 +00:00
dhi_holo 6887887d6b Cheap Mulch!
Made Mulch cheaper, as outlined by #866
2024-05-24 20:28:45 +10:00
Hiroku cf1100a20e Merge branch 'implement_pokemon' into 'main'
Wailord, Seedot line, and apostrophes in the changelog

See merge request cable-mc/cobblemon!1038
2024-05-24 09:46:27 +00:00
Frank The FarmerandHiroku ebc7b97e4f Wailord, Seedot line, and apostrophes in the changelog 2024-05-24 09:46:26 +00:00
FrankTheFarmer 5324b7b19e Merge branch 'main' into implement_pokemon
# Conflicts:
#	CHANGELOG.md
#	common/src/main/kotlin/com/cobblemon/mod/common/client/render/models/blockbench/pokemon/gen3/WailordModel.kt
2024-05-24 19:37:33 +10:00
FrankTheFarmer 5bddc31cbf Seedot line hitbox fixes 2024-05-24 19:30:11 +10:00
apion d65ce9222a Fixed tiny bug, fixes #867 2024-05-24 05:04:36 -04:00
FrankTheFarmer 72bc2221af Actually stopped Wailord in the chatbox for real this time 2024-05-24 18:56:27 +10:00
Apion 706221aead Merge branch 'LangFixes' into 'main'
A Couple of Lang Fixes

See merge request cable-mc/cobblemon!1035
2024-05-24 08:15:24 +00:00
Apion 26bfca893b Merge branch 'main' into 'LangFixes'
# Conflicts:
#   CHANGELOG.md
2024-05-24 07:01:46 +00:00
JazzMcNade 5f65f3c20c Updated Changelog 2024-05-24 01:47:23 -05:00
JazzMcNade 1e5239da10 Added English language keys for Rough Skin and Iron Barbs 2024-05-24 01:26:30 -05:00
JazzMcNade 7d8ec3470b Fix for Hyper Cutter / Big Pecks incorrectly stating they prevented accuracy from being lowered 2024-05-24 01:25:58 -05:00
Apion 389d2a0adc Merge branch '1.5-fixes-112313' into 'main'
1.5 fixes 112313

See merge request cable-mc/cobblemon!1034
2024-05-24 04:45:10 +00:00
apion 37433aa0c5 CHANGELOG.md 2024-05-24 00:34:04 -04:00
Paul 7fa0022095 Fixed species sync failing when madmen give pokemon more than 255 level up moves on the same level 2024-05-24 14:21:03 +10:00
Paul 9fde7a7618 Merge remote-tracking branch 'origin/main' into 1.5-fixes-112313 2024-05-24 14:18:04 +10:00
Paul 6c1f7ddd70 Putted the AttackDefenceRatioRequirement back for backcompat 2024-05-24 14:15:45 +10:00
apion 1a1cedb3aa Regenned berry data, added bone meal chance 2024-05-23 23:53:42 -04:00
Hiroku 241b83cec9 Merge branch 'implement_pokemon' into 'main'
Implementation Stuff

See merge request cable-mc/cobblemon!1027
2024-05-23 21:57:39 +00:00
Frank The FarmerandHiroku f0feb81a16 Implementation Stuff 2024-05-23 21:57:38 +00:00
apion b82287f258 Vera berry changes 2024-05-23 09:02:24 -04:00
FrankTheFarmer 9099cb4b5d Merge branch 'main' into implement_pokemon 2024-05-23 22:37:47 +10:00
FrankTheFarmer 99e0b7d995 Smeargle Mentioned 2024-05-23 22:34:58 +10:00
Hiroku 00f4052b75 Merge branch 'MoreFossilMachineFixes' into 'main'
Many Fossil Machine Fixes

See merge request cable-mc/cobblemon!1033
2024-05-23 11:02:07 +00:00
Hiroku 407c24b7c5 Merge branch 'asset-updates' into 'main'
Updated wooloo/dubwool textures and passho berry stuff

Closes #854

See merge request cable-mc/cobblemon!1031
2024-05-23 10:56:56 +00:00
FrankTheFarmer 372f44538b Smeagol 2024-05-23 15:47:13 +10:00
JazzMcNade c8904c3e38 Removed commented code, updated changelog 2024-05-23 00:24:22 -05:00
JazzMcNade 6bfc711129 Update FossilMultiblockStructure.kt 2024-05-22 23:25:46 -05:00
JazzMcNade 3d914f47ee Merge branch 'main' into MoreFossilMachineFixes 2024-05-22 23:25:26 -05:00
JazzMcNade 61891d8fe4 Refactored blockState check to for the blockstate property (credit to Charzard4261) , fixed typo 2024-05-22 21:26:49 -05:00
FrankTheFarmer 0bec3ac851 Merge branch 'main' into implement_pokemon 2024-05-23 07:21:49 +10:00
apion 1b66ee8ce3 Updated wooloo/dubwool textures and passho berry stuff 2024-05-22 03:57:34 -04:00
apion c884c556cb Remove binding soil 2024-05-22 03:37:04 -04:00
Apion 5e6091c782 Merge branch 'tmetcalfe89/revive-event' into 'main'
added fossil revived event

See merge request cable-mc/cobblemon!1029
2024-05-22 07:26:52 +00:00
Timothy MetcalfeandApion 5a2e5479e0 added fossil revived event 2024-05-22 07:26:52 +00:00
apion 9a8b481fa2 Changed berry grow timers per Vera request 2024-05-22 03:26:09 -04:00
apion e2fb31fad3 Merge branch 'refs/heads/main' into berry-changes 2024-05-22 02:39:51 -04:00
Tyzillion fc03682140 Implemented quick attack 2024-05-21 22:30:41 -04:00
JazzMcNade 07fbffaa71 Fixed refactor mistake in previous commit. 2024-05-21 20:45:54 -05:00
FrankTheFarmer 17b8dd3532 Wailord will now stop forcing its head into the chatbox 2024-05-22 09:53:31 +10:00
Tyzillion 5e2f5dadb4 Fixed some errors I ran into. 2024-05-21 19:36:11 -04:00
FrankTheFarmer 4cf8a19d43 Tyrantrum will now stop forcing its head into the chatbox 2024-05-22 09:34:12 +10:00
Tyzillion fc682d1cd1 Implemented action effects for Sand Attack, Protect, Minimize, and Swords Dance. 2024-05-21 19:13:06 -04:00
Tyzillion 7759c91f3b Merge branch 'main' of https://gitlab.com/cable-mc/cobblemon into move-effects
# Conflicts:
#	common/src/main/kotlin/com/cobblemon/mod/common/api/pokemon/evolution/Evolution.kt
2024-05-21 19:11:04 -04:00
JazzMcNade c13654f60c FossilMultiblockStructure no longer stores a created pokemon, instead the pokemon is created when the pokemon is retrieved from the machine 2024-05-21 02:36:39 -05:00
JazzMcNade 289e9df52b Fixed Restoration Tank over consuming items when interacting with Create blocks 2024-05-20 21:23:13 -05:00
FrankTheFarmer f205e7f29e CHANGELOG 2024-05-21 10:18:44 +10:00
FrankTheFarmer cec031595f Merge branch 'main' into implement_pokemon 2024-05-21 10:14:21 +10:00
FrankTheFarmer af007dad17 Added missing Chingling and Chimecho spawns near bells 2024-05-21 09:54:39 +10:00
Tyzillion 5dca5a1579 Merge remote-tracking branch 'origin/move-effects' into move-effects 2024-05-20 15:57:38 -04:00
JazzMcNade 3ebad9dc9d Fixed a Create crash when a chute attempts to access the inventory of the top half of the Restoration Tank when the bottom half has been destoryed 2024-05-19 21:27:03 -05:00
apion c93fa02616 Fixed dispatch timeline 2024-05-19 21:13:58 -04:00
Hiroku 4e1b82917b Merge branch 'Roaming-Gholdengo-Request' into 'main'
Lets Gholdengo maintain its roaming aspect

See merge request cable-mc/cobblemon!1025
2024-05-20 00:11:17 +00:00
Frank The FarmerandHiroku 3b1d257241 Lets Gholdengo maintain its roaming aspect 2024-05-20 00:11:16 +00:00
Hiroku 0b8f916648 Merge branch 'dimension-condition-uses-id-not-effects' into 'main'
Change dimension spawn condition to check with IDs not effects

See merge request cable-mc/cobblemon!1026
2024-05-20 00:11:02 +00:00
FrankTheFarmer 8490f3a923 Fixed Cyndaquil's flame clipping when it wasn't ignited 2024-05-20 08:17:02 +10:00
FrankTheFarmer 9bf6200163 Merge branch 'main' into implement_pokemon 2024-05-20 08:11:19 +10:00
apion 5897fff954 Added boost/unboost general particles, removed the particle from growl 2024-05-19 18:05:11 -04:00
apion 2fd2137d78 Added poison (this particle is BROKEN) 2024-05-19 17:22:09 -04:00
apion 42c4d6625e Added poison (this particle is BROKEN) 2024-05-19 17:21:52 -04:00
apion b0381d1685 We do a little refactoring 2024-05-19 16:23:41 -04:00
David Sadler 5ad7d5406a Change dimension spawn condition to check with IDs not effects 2024-05-19 18:45:34 +01:00
apion 3b00043b13 Got confusion kinda working, needs tweaks 2024-05-19 02:44:05 -04:00
JazzMcNade 2b403df6ef Removed client side mutations in FossilMultiblockStructure's onUse and enabled the client to enter the function 2024-05-19 01:37:04 -05:00
apion f0d5622bab Added volatile status stuff 2024-05-19 02:20:12 -04:00
apion ec28ca0c45 Added action effect for paralysis + action effect triggers for the cant command 2024-05-19 01:11:41 -04:00
Tyzillion 0d68eedc74 Merge remote-tracking branch 'origin/move-effects' into move-effects 2024-05-18 22:24:56 -04:00
Paul 6ec008ee83 Merge remote-tracking branch 'origin/main' into 1.5-fixy
# Conflicts:
#	CHANGELOG.md
2024-05-19 11:19:13 +10:00
Paul c969e1731b Merge remote-tracking branch 'origin/move-effects' into move-effects 2024-05-19 09:13:29 +10:00
Paul bb77c6d4a9 Fixed particle velocity not respecting drag as much as it should oops sorry 2024-05-19 09:13:17 +10:00
Tyzillion 5dfc90c0bd Merge remote-tracking branch 'origin/move-effects' into move-effects 2024-05-18 18:52:14 -04:00
apion 26a72fe6a9 I hope this works (pt. 2) 2024-05-18 18:46:58 -04:00
apion 4bb9547822 I hope this works 2024-05-18 17:08:09 -04:00
Tyzillion ffe88d75b5 Merge remote-tracking branch 'origin/move-effects' into move-effects 2024-05-18 16:08:32 -04:00
apion d8980fabbe Fix entity_scale var 2024-05-18 14:56:47 -04:00
apion 7598413e93 Merge branch 'refs/heads/particle-rave' into move-effects 2024-05-18 13:55:24 -04:00
apion b0cc4714fc Merge branch 'refs/heads/main' into move-effects
# Conflicts:
#	CHANGELOG.md
2024-05-18 13:53:45 -04:00
JazzMcNade 5aa3f34880 Added block type checks before attempting to update the blockstate from the fossilmultiblockstructure 2024-05-18 12:15:50 -05:00
Slippy 21363405fc console log spam fix for real this time 2024-05-18 12:00:11 -05:00
JazzMcNade 340be0b2a1 Fixed an issue where the lights on the restoration tank would not animate if it was facing east 2024-05-18 11:57:16 -05:00
JazzMcNade 933e29b134 Fix for TankEntityRenderer desync 2024-05-18 11:52:54 -05:00
Tyzillion 41b27e5d75 Merge branch 'main' of https://gitlab.com/cable-mc/cobblemon into move-effects
# Conflicts:
#	CHANGELOG.md
2024-05-18 10:55:29 -04:00
Tyzillion e80bf0e331 Merge remote-tracking branch 'origin/move-effects' into move-effects 2024-05-18 10:54:32 -04:00
Hiroku f4d2226ec2 Merge branch '1.5.1' into 'main'
Moar 🐛🔫

Closes #847 and #799

See merge request cable-mc/cobblemon!1023
2024-05-18 01:50:12 +00:00
apion 0fc5d5e9d7 Fixed bad null handling 2024-05-17 21:41:58 -04:00
Hiroku 972c0f6430 Merge branch 'dubwool-dye' into 'main'
Make wooloos dyable

Closes #824

See merge request cable-mc/cobblemon!1021
2024-05-18 01:40:13 +00:00
ApionandHiroku 86db95a7dc Make wooloos dyable 2024-05-18 01:40:13 +00:00
apion be95b79e4d Removed unnecessary override 2024-05-17 21:20:20 -04:00
Paul 683aa354ed Fixed particle event triggers spawning particles on the emitter, fixes #814 2024-05-18 11:10:48 +10:00
apion aa19ff2c95 Added entity scale as a particle param 2024-05-17 20:57:10 -04:00
Paul 7d5e790f75 Fixed particle rotations being inverted 2024-05-18 10:55:28 +10:00
apion 5753443ab2 Optimized a player lookup 2024-05-17 20:39:27 -04:00
apion c6b7186032 Merge branch 'refs/heads/main' into 1.5.1
# Conflicts:
#	CHANGELOG.md
2024-05-17 20:35:50 -04:00
apion 32f3be2687 Changelog 2024-05-17 20:33:24 -04:00
apion 9012d78806 Apparently Kotlin uses .equals when using ==, === is Java == behavior 2024-05-17 20:30:18 -04:00
apion fffdfb7654 Fixes bug with InvMove, closes #847 2024-05-17 20:28:57 -04:00
Tyzillion 76f17c9760 Merge remote-tracking branch 'origin/move-effects' into move-effects 2024-05-17 18:33:17 -04:00
Hiroku b314733f0b Merge branch 'Frank's-Bug-Fixing-Farm' into 'main'
Frank's bug fixing farm

See merge request cable-mc/cobblemon!1019
2024-05-17 10:44:01 +00:00
Frank The FarmerandHiroku d5aa07fe91 Frank's bug fixing farm 2024-05-17 10:44:00 +00:00
Paul 3b0d2cd980 Added parametric particle support (motion and rotation), closes #773 2024-05-17 16:43:35 +10:00
Ludichat 7e43a7424e Updated CHANGELOG.md. 2024-05-17 08:26:51 +02:00
apion 27bedc2d2c Closes #799 2024-05-16 21:59:36 -04:00
Hiroku 86744c23a5 Merge branch '1.5.1' into 'main'
Fix recoil evo bug

Closes #844

See merge request cable-mc/cobblemon!1022
2024-05-17 01:41:41 +00:00
Tyzillion f5a3c93039 Merge remote-tracking branch 'origin/move-effects' into move-effects 2024-05-16 21:35:16 -04:00
Paul 00dc501df7 Fixed timed particle ages being a tick too long, fixes #840 2024-05-17 11:28:49 +10:00
apion 8d1a64136f Fix recoil evo bug 2024-05-16 20:33:19 -04:00
Paul 39fee0bcea Fixed particle effects generated from molang not having access to entity_radius and stuff. Fixes #841 2024-05-17 10:26:18 +10:00
Tyzillion 1162689172 Merge remote-tracking branch 'origin/move-effects' into move-effects 2024-05-16 20:08:03 -04:00
Paul bc550dd32c Fixed unlocked evolutions getting re-checked and eating held items, fixes #843 2024-05-17 10:04:54 +10:00
Paul b295644070 Cleaned imports 2024-05-17 09:37:29 +10:00
Paul 21df0085e2 Merge remote-tracking branch 'origin/main' into move-effects 2024-05-17 09:08:19 +10:00
Paul 3009af8c42 Fixed missing cant.nopp lang key, fixes #842 2024-05-17 08:52:23 +10:00
Hiroku bfd34eb621 Merge branch '1.5.1' into 'main'
Fixes a few issues

Closes #827, #828, #826, and #832

See merge request cable-mc/cobblemon!1012
2024-05-16 22:46:10 +00:00
Hiroku 2dc2c96176 Update CHANGELOG.md [skip-ci] 2024-05-16 22:44:00 +00:00
Hiroku df4db17cfd Removed println 2024-05-16 22:40:56 +00:00
Ludichat b718daf0f1 Gives a Hidden Ability slot to middle stage evolution and Ferroseed with a single ability. 2024-05-16 21:49:34 +02:00
Slippy 08c4f4a0ff added loot to the trapped chest in unstable caves so you can't tell which one is trapped if you're using lootr muwahahahaha 2024-05-16 01:57:41 -05:00
Slippy c4a1704a8b unstable cave loot table fixes 2024-05-15 20:35:24 -05:00
apion 45bec488f1 Fixed bug with pasture block 2024-05-15 20:41:32 -04:00
apion 9287374504 Merge branch 'refs/heads/main' into 1.5.1 2024-05-15 18:24:56 -04:00
Tyzillion 51af37b37a Merge branch 'main' of https://gitlab.com/cable-mc/cobblemon into move-effects 2024-05-15 18:09:53 -04:00
apion f2a36cd74a Merge branch 'refs/heads/main' into 1.5.1
# Conflicts:
#	CHANGELOG.md
2024-05-15 14:51:45 -04:00
apion a3122812e4 Added color to all sprouts 2024-05-15 07:47:43 -04:00
Slippy 837aa5acf5 missing loot table in deserted tower 2024-05-14 16:58:55 -05:00
apion 19698fc0ff Merge branch 'refs/heads/main' into berry-changes 2024-05-14 16:36:34 -04:00
apion 7ab3951613 Fix gilded chest item drops 2024-05-14 11:16:33 -04:00
apion e6d51c4d56 A little more fossil machine clean up 2024-05-14 10:26:25 -04:00
apion b9364304ca Changelog teehee 2024-05-14 09:47:35 -04:00
apion 8236c6fb11 Merge branch 'refs/heads/main' into 1.5.1 2024-05-14 04:13:40 -04:00
apion 2041d43db4 Hopefully fixed some other bugs 2024-05-14 03:53:35 -04:00
JazzMcNade 94d92b6fc0 Fixes #827
Jade can now view the contents of the analyzer block
2024-05-14 01:53:56 -05:00
apion 4a4d292228 Fixes #828 2024-05-13 17:01:38 -04:00
apion 0fef9eec3d Fixes #826 2024-05-13 17:01:27 -04:00
apion 5f3dc395ec Fixes #832 2024-05-13 12:17:47 -04:00
Slippy 969d6ac7fc console spam fix 2024-05-12 09:23:39 -05:00
Slippy 46bb9e1aec console fix 2024-05-11 21:58:50 -05:00
Slippy 9792ff3392 console spam fix 2024-05-11 21:36:29 -05:00
FrankTheFarmer 4482a4f072 Forgot to add Mismagius to model updates 2024-05-09 10:00:05 +10:00
FrankTheFarmer a92f37c740 Added Krabby's missing temporary-cry animation 2024-05-09 09:57:26 +10:00
FrankTheFarmer 4677dda922 Limited Mismagius' yaw range to prevent some clipping 2024-05-09 09:56:29 +10:00
FrankTheFarmer 81f7320e4a Mismagius asset updates 2024-05-09 09:56:01 +10:00
FrankTheFarmer 3c9cf42da4 Fixed Flabebe's broken species name. Apparently its Flabébé and not Flabébé??? 2024-05-06 08:39:34 +10:00
FrankTheFarmer 620ed73fe9 Fixed Klefki t pose when sleeping 2024-05-06 08:38:23 +10:00
Tyzillion 978d9e76a1 Merge branch 'main' of https://gitlab.com/cable-mc/cobblemon into move-effects 2024-05-04 17:48:57 -04:00
FrankTheFarmer 7d09b7e2fe Fixed a broken texture on Elgyem 2024-05-04 18:48:08 +10:00
FrankTheFarmer 656cff2ab3 Made Galarian Zigzagoon use Hoenn Zigzagoon's shoulder animation 2024-05-04 18:16:59 +10:00
Tyzillion 1d8462fd63 Implemented better Krabby bubble blowing quirk animation. 2024-05-03 18:34:23 -04:00
Tyzillion e417db6a8d Merge branch 'main' of https://gitlab.com/cable-mc/cobblemon into implement_pokemon 2024-05-03 16:39:08 -04:00
MoeBoy76 16d0d3b7e1 Merge branch 'main' of https://gitlab.com/cable-mc/cobblemon into implement_pokemon
# Conflicts:
#	CHANGELOG.md
#	common/src/main/resources/data/cobblemon/species/generation1/exeggcute.json
#	common/src/main/resources/data/cobblemon/species/generation1/pikachu.json
#	common/src/main/resources/data/cobblemon/species/generation2/cyndaquil.json
#	common/src/main/resources/data/cobblemon/species/generation2/quilava.json
#	common/src/main/resources/data/cobblemon/species/generation5/dewott.json
#	common/src/main/resources/data/cobblemon/species/generation5/oshawott.json
#	common/src/main/resources/data/cobblemon/species/generation7/dartrix.json
#	common/src/main/resources/data/cobblemon/species/generation7/rowlet.json
2024-05-02 15:49:13 +10:00
MoeBoy76 dbedc58dd9 changelog conflict fix [skip-ci] 2024-05-02 15:43:54 +10:00
FrankTheFarmer c0ea565967 Updated Changelog with recent changes 2024-05-02 14:26:10 +10:00
FrankTheFarmer 7e92f5f314 Updated Spewpa evolution and Vivillon spawn biome tags 2024-05-02 14:25:21 +10:00
FrankTheFarmer df3ed93032 Added anticondition structure requirements to evolutions 2024-05-02 14:24:45 +10:00
FrankTheFarmer 2335fd388e Updated and added time ranges 2024-05-02 14:22:26 +10:00
FrankTheFarmer e152cc9fd0 Updated Changelog with recent work 2024-05-01 21:31:00 +10:00
FrankTheFarmer 3f7e2bef40 Updated Spewpa evolutions and made sure they work. I hate evolution™ 2024-05-01 21:30:16 +10:00
FrankTheFarmer 25927c6ebe Updated Vivillon biome tags to new format and added 2 more 2024-05-01 21:28:40 +10:00
FrankTheFarmer 2f18d6b05f Created new folder for all regional evolution biome tags and moved region bias ones there 2024-05-01 20:34:48 +10:00
FrankTheFarmer 2600e23233 Removed sliggoos cross region evolutions 2024-05-01 20:33:26 +10:00
FrankTheFarmer 5c5c72d800 Updated Goomy to use new evolution biome tags for evolution 2024-05-01 20:32:15 +10:00
FrankTheFarmer 2c812344f9 Updated Petilil evo biomes and added priority evos to save a sun stone hopefully 2024-05-01 20:24:33 +10:00
FrankTheFarmer 37b4577230 Updated Hisui Starter evos to use the updated evolution biome tags 2024-05-01 19:50:51 +10:00
FrankTheFarmer fcf64b00bf Updated Pikachu and Exeggcute evolutions to prioritize cross region evos if applicable 2024-05-01 19:40:48 +10:00
FrankTheFarmer 02b8cd81a0 Updated Conkeldurr with the correct animation files 2024-04-30 21:38:54 +10:00
FrankTheFarmer def1b44f08 Fixed Conkeldurr holding too much concrete during sleep animation 2024-04-30 17:02:01 +10:00
FrankTheFarmer b28f915af9 Selected Hisui starters will now come in ancient poke balls 2024-04-30 15:07:59 +10:00
FrankTheFarmer 29ce8b584a Stopped the zoroarks cry animations from looping 2024-04-29 19:22:18 +10:00
FrankTheFarmer 84f3a44109 Found Sudowoodo and Bonsly. Hiding since July 2023 2024-04-29 15:35:20 +10:00
FrankTheFarmer 08a58eee8a Prevented and preserved Cubone's evolution to Alolan Marowak 2024-04-29 08:55:05 +10:00
Tyzillion 1e067cb7e4 Implemented simple elemental punches. Implemented sweetscent effects, and stat increase and decrease particles. 2024-04-27 22:00:56 -04:00
FrankTheFarmer c10f48090c Added dried kelp blocks, melon, vines, and sea pickles to list of organic materials for the fossil machine 2024-04-28 11:07:16 +10:00
Tyzillion 2f464f82b1 Merge branch 'main' of https://gitlab.com/cable-mc/cobblemon into move-effects 2024-04-26 21:01:38 -04:00
FrankTheFarmer 9c0e5e487a Reverted Snorlax's resize 2024-04-26 20:57:20 +10:00
FrankTheFarmer 95f2bbbf15 If for some reason you are above an Aurorus, it will no longer break its neck trying to look at you. 2024-04-26 20:37:53 +10:00
FrankTheFarmer 864d184cd9 Scaled drifloon down a bit 2024-04-26 17:53:56 +10:00
FrankTheFarmer a2256f6208 Lurantis animation file update 2024-04-26 16:44:14 +10:00
FrankTheFarmer 945d556b43 Fixed Cubone holding its bone humerusly 2024-04-26 16:18:14 +10:00
FrankTheFarmer f0def2e883 Fixed zubat's shoulder animations 2024-04-26 13:42:21 +10:00
FrankTheFarmer 79c644dad0 So the 10 and 11 bug can be fixed with underscores 👀 2024-04-26 13:37:39 +10:00
Tyzillion 28c0e17a48 Merge branch 'main' of https://gitlab.com/cable-mc/cobblemon into move-effects 2024-04-25 18:21:18 -04:00
FrankTheFarmer 87e41bdb89 Fixed Kabuto animation but on implementation branch 2024-04-25 22:22:18 +10:00
FrankTheFarmer 8a8505d816 3/4 of the Galar fossils can now look at the player. 2024-04-25 21:04:04 +10:00
FrankTheFarmer 1a19c51748 Fixed Slowpoke spawning everywhere 2024-04-25 17:16:37 +10:00
FrankTheFarmer 8a66ab9235 Removed unimplemented cries from sounds json 2024-04-25 16:41:11 +10:00
Paul ee50361555 Merge remote-tracking branch 'origin/main' into implement_pokemon
# Conflicts:
#	CHANGELOG.md
2024-04-25 11:47:23 +10:00
Paul d3631f1436 Merge remote-tracking branch 'origin/implement_pokemon' into implement_pokemon 2024-04-25 10:28:21 +10:00
Paul 31136435fe Fixed autogeneration of target and special_attack locators 2024-04-25 10:20:19 +10:00
Paul bdeb83c62c Fixed entity_particles parsing of the effect ID when it's a simple string 2024-04-25 10:20:01 +10:00
FrankTheFarmer 79e1f9143c Fixed Wooloo's blink and leg but in game 2024-04-25 10:07:09 +10:00
Paul 15bf726421 Merge remote-tracking branch 'origin/main' into move-effects 2024-04-24 15:13:23 +10:00
DoctorWafflePhD 7f1889db7b bubblebeam VFX uploaded for review by hiroku (thanks oomfie) 2024-04-23 21:42:16 -05:00
DoctorWafflePhD 548c18bea4 hit particle fix(?) 2024-04-23 21:41:46 -05:00
DoctorWafflePhD d9203bef2a hit particle fix(?) 2024-04-23 21:06:57 -05:00
FrankTheFarmer bef0b2fb87 Updated regional bias evolution data to hopefully work as intended. I hate evolution. 2024-04-23 20:49:22 +10:00
FrankTheFarmer d7bbc05af8 Created biome tags for the regional bias evolutions. They're specific to each form's spawn data 2024-04-23 20:47:27 +10:00
FrankTheFarmer 7ca3ab5e30 Updated portrait data for the Samurotts 2024-04-23 20:43:44 +10:00
FrankTheFarmer 1bbb1201c8 Chansey animation fixes. Cry implemented but no sound file yet 2024-04-23 18:20:26 +10:00
FrankTheFarmer 8ed4fee8af Added more visual distinction for Hisui Bias Quilava in the evolution menu. Plus Cyndaquil textures 2024-04-23 17:18:07 +10:00
FrankTheFarmer a3dacc2c3d Forgot about the changelog lol 2024-04-22 20:50:03 +10:00
FrankTheFarmer c265f73308 Fixed eyes on the faints of Hitmonlee and Phantump 2024-04-22 20:40:12 +10:00
FrankTheFarmer 670dedc0e2 Grovyle shiny texture fixes 2024-04-22 14:01:59 +10:00
Tyzillion 5e24799295 move effects are in the works now. :) 2024-04-21 23:05:41 -04:00
Tyzillion a7243102d5 Evolution particle tweaks and Pokemon now stop moving if evolution is started. 2024-04-21 21:06:47 -04:00
Tyzillion de6a84a75b Merge branch 'main' of https://gitlab.com/cable-mc/cobblemon into evolution-effect 2024-04-21 19:37:16 -04:00
FrankTheFarmer 6e19ee6059 Tricko remodel 2024-04-22 09:05:52 +10:00
Tyzillion be3c35eb43 Merge branch 'main' of https://gitlab.com/cable-mc/cobblemon into evolution-effect 2024-04-21 11:21:57 -04:00
FrankTheFarmer a865d59b99 changelog update 2024-04-21 17:27:38 +10:00
FrankTheFarmer 8896440451 Merge remote-tracking branch 'origin/implement_pokemon' into implement_pokemon 2024-04-21 17:09:04 +10:00
FrankTheFarmer 39b27a8c17 Quick and dirty fixes for Pikachu and Exeggcute evolution data. Added new biome tag for their evolution requirements. 2024-04-21 16:41:50 +10:00
Sterrezo a0eb614f2a Kabuto now does the funny noise. Fixed Lucario's cry missing
I didn't know what to do with Kabuto's animation, ended up using a placeholder. Lucario had an incorrectly named keyframe.
2024-04-15 23:26:44 +02:00
FrankTheFarmer a6e4aeb321 The Doduo line will now bite less 2024-04-15 15:57:48 +10:00
FrankTheFarmer bb796921b5 Changelog updates. Removed duplicates and added list of new shoulder mounts 2024-04-15 10:30:11 +10:00
FrankTheFarmer 9f6f764aa1 Merge remote-tracking branch 'origin/implement_pokemon' into implement_pokemon 2024-04-15 07:59:57 +10:00
FrankTheFarmer f115a87b66 Roaming Gimmighoul can now evolve 2024-04-15 07:59:31 +10:00
Waldleufer 77c880ff2d fix: cry script - relaxing handling of all Forms, skipping non-regional forms [skip-ci] 2024-04-14 09:29:01 +02:00
FrankTheFarmer 16c64b9d8e Updated behaviour for Armaldo, Carracosta, Tirtouga, and Wimpod 2024-04-14 12:26:45 +10:00
FrankTheFarmer caeb45e9e1 Tyrantrum line kotlin poser placed in the proper generation. 2024-04-14 12:23:03 +10:00
FrankTheFarmer 6e341438e9 Goomy line updates and Steenee scale update 2024-04-14 11:38:17 +10:00
Tyzillion 7407483498 Updated Branch with latest main. Added Lucario aura in battle. 2024-04-13 16:34:44 -04:00
Tyzillion 020c728004 Merge remote-tracking branch 'origin/implement_pokemon' into implement_pokemon 2024-04-13 14:55:15 -04:00
Sterrezo 7125987c98 Fixed Hisuian Lilligant's cry missing
Asset was incorrectly named
2024-04-13 20:33:25 +02:00
Waldleufer 6448c4472e fix: cry script - handling all Forms, skipping non-regional forms [skip-ci] 2024-04-13 20:11:26 +02:00
Waldleufer eedac70d13 fix: cry script - sprinkling in some magic [skip-ci] 2024-04-13 19:07:48 +02:00
Sterrezo 025e09cd12 Couple cry fixes
Updated KrabbyModel.kt. Fixed missing or incorrect sound effect keyframes in animation.json files.
2024-04-13 18:54:55 +02:00
Waldleufer 4d2cfb63ea fix: cry script - warn about files not in the right locations [skip-ci] 2024-04-13 18:52:27 +02:00
Waldleufer 40794acdd5 fix: cry script - properly check elaborate cries [skip-ci] 2024-04-13 18:25:25 +02:00
Sterrezo 82f8855725 Fixed missing Grovyle and Sceptile cries missing 2024-04-13 17:57:21 +02:00
Waldleufer 5abcdbb837 fix: cry script - new way to implement cries does not require an import [skip-ci] 2024-04-13 17:48:01 +02:00
Waldleufer 2f817a7f9a fix: cry script - ignore commented out lines [skip-ci] 2024-04-13 17:33:35 +02:00
Waldleufer 67767fc53a fix: cry script - only log warnings for pokemon marked as "In-Game" [skip-ci] 2024-04-13 17:16:34 +02:00
Tyzillion 43cd4b8403 Merge branch 'main' of https://gitlab.com/cable-mc/cobblemon into implement_pokemon 2024-04-13 02:50:14 -04:00
Tyzillion 2660d73bb6 Merge remote-tracking branch 'origin/implement_pokemon' into implement_pokemon 2024-04-13 02:49:33 -04:00
FrankTheFarmerReal faa7ca5d19 Revoking Hisuian Visas 2024-04-13 11:48:17 +10:00
Tyzillion 0fcbe51d97 Merge branch 'main' of https://gitlab.com/cable-mc/cobblemon into implement_pokemon 2024-04-12 11:16:59 -04:00
Tyzillion b23ad62f99 Merge remote-tracking branch 'origin/implement_pokemon' into implement_pokemon 2024-04-12 11:16:44 -04:00
Sterrezo 3ca4ce8f80 Implemented 13 new cries, more changelog updates with previously undocumented cries 2024-04-12 16:47:25 +02:00
Sterrezo 446a994195 Fixed a typo in komala.animation.json 2024-04-12 16:14:12 +02:00
Sterrezo 60e7ac828d Implemented more cries, updated changelog
Added cries for Goomy, Sliggoo, Goodra, Hisui Bias Goomy, Hisuian Sliggoo, Hisuian Goodra, Klefki. Fixed Arcanine's cry misisng. Updated changelog with previously undocumented cries.
2024-04-12 13:10:18 +02:00
Sterrezo a870effd3b Added a keyframe with a cry for Lapras 2024-04-12 10:27:53 +02:00
FrankTheFarmerReal 236237a170 The simple blink of a Bouffalant shall no longer crash your game 2024-04-12 17:00:37 +10:00
FrankTheFarmerReal 0fc67ba042 Updated Goomy's hisui bias assets and added missing oinkologne cry files. 2024-04-12 13:32:48 +10:00
FrankTheFarmerReal 997ab29d91 Added a couple cries 2024-04-12 11:29:01 +10:00
FrankTheFarmerReal e74f54f1d0 Implemented Kotlin posers for Hisuian starters unique cries
Deleted Datrix
2024-04-12 00:05:12 +10:00
Sterrezo 081e368551 Merge branch 'implement_pokemon' of https://gitlab.com/cable-mc/cobblemon into implement_pokemon 2024-04-11 14:04:44 +02:00
Sterrezo 1538f58a4a Added audio assets for previously added cries 2024-04-11 14:04:16 +02:00
FrankTheFarmerReal e5103e5d03 Separated Oinkologne models to allow for separate cries 2024-04-11 21:54:01 +10:00
FrankTheFarmerReal 1cea15c9e5 Fixed Milcery being unable to evolve properly 2024-04-11 21:49:58 +10:00
FrankTheFarmerReal 3395fe0140 Hisuian Samurott texture fixed 2024-04-11 21:49:58 +10:00
FrankTheFarmerReal 2eff8d14eb Fixed Happiny being unable to evolve 2024-04-11 21:49:58 +10:00
FrankTheFarmerReal ed3cdf9b75 Limited the Typhlosions and Cyndaquils ability to look up to prevent bone dislocation in certain scenarios 2024-04-11 21:49:58 +10:00
FrankTheFarmerReal 6e1ba0599f Corrected egg groups for Toedscool line 2024-04-11 21:49:58 +10:00
FrankTheFarmerReal 497d5ce39b Basculegion behaviour updated. Should stop drowning. 2024-04-11 21:49:58 +10:00
FrankTheFarmerReal 660de3ea03 Dusknoir animations updated 2024-04-11 21:49:58 +10:00
FrankTheFarmerReal 5ab3d7b493 Updated Ekans texture 2024-04-11 21:49:57 +10:00
FrankTheFarmerReal 2ce0069484 Closed Scyther's mouth after it cries 2024-04-11 21:49:57 +10:00
Sterrezo d87fa57c95 Implemented a bunch of cries
Woobat, Swoobat, Lilligant, Hisuian Lilligant, Basculin, Klink (Deleted a redundant animation file as well), Klang, Klinklang, Litwick, Lampent, Chandelure, Cubchoo, Bouffalant, Larvesta, Volcarona, Fomanting, Lurantis, Gossifleur, Eldegoss, Stonjourner, Basculegion, Sneasler, Overqwil, Oinkologne
2024-04-11 13:40:36 +02:00
FrankTheFarmerReal 69947b0b32 Fixed Flabebe line T pose when sleeping 2024-04-11 09:01:02 +10:00
Tyzillion f4c3f9ae04 Merge branch 'main' of https://gitlab.com/cable-mc/cobblemon into implement_pokemon 2024-04-10 09:34:02 -04:00
FrankTheFarmerReal 04e1a6b41c Removed duplicate entry from changelog 2024-04-10 18:13:26 +10:00
FrankTheFarmerReal 6ae2adb2d0 Stopped Pumpkaboo's cry from looping 2024-04-10 17:12:44 +10:00
FrankTheFarmerReal 0bf6932fe5 Dusknoir's animations are now about 20 degrees cooler™ 2024-04-10 09:59:27 +10:00
FrankTheFarmerReal 71382a3bd1 Merge remote-tracking branch 'origin/implement_pokemon' into implement_pokemon 2024-04-09 10:27:14 +10:00
FrankTheFarmerReal 0f4f29518b Placeholder Volcarona animations 2024-04-09 10:26:37 +10:00
Sterrezo 8aeeece0a3 Fixed missing cries, updated the changelog.
Fixed missing audio files, sound effect keyframes and model.kt files. Partially updated the changelog.
2024-04-08 18:55:58 +02:00
Paul 850b418c80 Improve surface-swimmers behaviour when submerged 2024-04-08 22:51:04 +10:00
FrankTheFarmerReal 42af2898b2 Hitbox fixes and Lapras placeholder swim animation 2024-04-08 18:23:01 +10:00
Tyzillion b4508bf87e More tweaks to evolution particles. 2024-03-10 06:29:27 -04:00
Tyzillion dcb4f52cdb Added sounds to evolution. 2024-03-10 00:32:08 -05:00
Tyzillion 1e9b390f38 Merge branch 'main' of https://gitlab.com/cable-mc/cobblemon into evolution-effect 2024-03-09 23:34:36 -05:00
Tyzillion 7edd47f995 Evolution tweaks. 2024-03-08 19:12:46 -05:00
Tyzillion dd220c5c85 Merge remote-tracking branch 'origin/evolution-effect' into evolution-effect 2024-03-07 22:02:04 -05:00
Paul bea84a37d4 Fixed a bunch of evolution animation locator issues 2024-03-08 13:01:42 +10:00
Tyzillion ac30da3c15 Merge remote-tracking branch 'origin/evolution-effect' into evolution-effect 2024-03-07 20:58:08 -05:00
Paul 3861835d47 Test command spawns bedrock entity for evo 2024-03-06 21:06:38 +10:00
Tyzillion d62fb5c4c7 Merge remote-tracking branch 'origin/evolution-effect' into evolution-effect 2024-03-03 20:58:44 -05:00
Paul ca9dde92cd Merge remote-tracking branch 'origin/main' into evolution-effect 2024-03-04 11:32:33 +10:00
Tyzillion 6ba264ddcb Merge branch 'main' of https://gitlab.com/cable-mc/cobblemon into evolution-effect 2024-03-03 20:26:59 -05:00
Tyzillion ab6c088ddf Evolution particle edits. 2024-03-03 17:56:50 -05:00
Tyzillion 18105a8b3f Merge branch 'main' of https://gitlab.com/cable-mc/cobblemon into evolution-effect 2024-03-03 17:56:44 -05:00
Tyzillion acb5984a9e Evolution particles electric boogaloo. 2024-03-03 03:50:33 -05:00
Paul 0a3ba8d4fa Fixed generic bedrock animations not being loaded 2024-03-03 17:37:43 +10:00
Paul 15259f0a95 Merge remote-tracking branch 'origin/main' into evolution-effect 2024-03-03 17:32:04 +10:00
Tyzillion 9f66c053e1 Evolution Particles BB. 2024-03-03 02:25:10 -05:00
apion 743da2817b Added rooted soil 2024-02-27 06:07:24 -05:00
apion ebdf69f496 Rebuilt blockstate jsons 2024-02-27 05:57:41 -05:00
apion 995364c960 Texture updates 2024-02-23 19:53:27 -05:00
apion 289b2ddc7b Berries now stick out of the ground when initially planted 2024-02-23 19:08:03 -05:00
1926 changed files with 39502 additions and 16450 deletions
+1
View File
@@ -3,3 +3,4 @@
# are changed when only line endings change.
src/generated/**/.cache/cache text eol=lf
src/generated/**/*.json text eol=lf
CHANGELOG.md merge=union
+119 -14
View File
@@ -1,39 +1,144 @@
# Changelog
## [1.6.0 - The Bass Pro Fishing Update (Month Xth, 2024)](#1-6-0)
#### "Now that there's a fishing mechanic, the mod is actually good!"
## [1.5.3](#1-5-3)
### Fixes
- Scaled down Amaura's fetus model to avoid clipping through the tank while animating
- Added Polished Tumblestone and Tumblestone Brick block sets from Tumblestone, Black Tumblestone, and Sky Tumblestone.
- Fixed Cubone's cry not having a sound.
- Fixed the Seafloor spawning context not being a usable context.
- Fixed Pokemon spawning in non-full blocks like slabs.
- Fixed Gilded Chests not dropping the chest itself when broken, only the contents.
- Fixed Pokémon losing their Hidden Ability through evolution if the middle stage did not have a Hidden Ability.
- Fixed Crumbling Arch not blending in with the world.
- Fixed Energy Root applying being usable on a fainted Pokemon.
- Fixed Pokémon entity not spawning when starting a battle while recalling said Pokémon
### Additions
- Added Pokémon (and item) fishing using modified fishing rods - Poké Rods! You'll need a Poké Rod smithing template, a fishing rod, and some type of Poké Ball. Each Poké Ball makes a differently themed rod. Why not?
- Added Lure Ball functionality, increasing the catch rate of Pokémon that were caught on a fishing rod.
- Added property chaining support for duplicate CustomPokemonPropertyType elements.
- Added aspect and unaspect PokemonProperty arguments (which also includes commands such as /pokemonedit, /spawnpokemon, and /givepokemon) to allow forcing or un-forcing an aspect on a Pokémon.
- Added extra visuals to early berry growth stages
### Added cries to the following Pokémon
- Timburr, Gurdurr, Conkeldurr
- Golett, Golurk
### Changes
- Altered the item model for Medicinal Leeks and Roasted Leeks to be held like sticks and other rod items.
- Adjusted some berry balance values like yield and growth times
- Changes to mulch buffs/durations
### Developer
- SpawnCause is now an implementation of SpawningInfluence.
- Added "forcedAspects" to Pokemon to make it easier to easily add basic aspects to a Pokémon in a way that persists. We already know that everyone is going to overuse this.
- Made the Pokemon.aspects setter private. This could technically break sidemods but if you are affected by this then you were using it wrong! Use Pokemon.forcedAspects to fix it.
## [1.5.1](#1-5-1)
### Data Pack & Resource Pack Creators
- Added support for "shedders" similar to Shedinja's evolution logic.
## [1.5.2 (May 27th, 2024)](#1-5-2)
### Fixes
- Fixed Wooloo and Dubwool dyeing making your game start dying. Only if you do it on a server.
- Fixed Gimmighoul causing PCs and parties to look glitched out, also only in a server.
- Fixed players being able to dye other people's sheep Pokémon.
## [1.5.1 (May 27th, 2024)](#1-5-1)
### Additions
- Added unique send out particles for Cherish, Dream, Beast, and Ancient Origin balls.
- Made Wooloo and Dubwool dye-able like sheep. So cute!
- Added stat up and down particles.
- Most status effects now have particles! These include: Paralysis, Poison, Sleep, Confusion, Infatuation.
#### Move Particle Effects
- Confusion
- Cotton Guard
- Growl
- Ice Punch
- Fire Punch
- Thunder Punch
- Minimize
- Quick Attack
- Protect
- Swords Dance
- Sand Attack
- Poison Powder
- Sleep Powder
- Stun Spore
- Powder
- Rage Powder
- Spore
- Thunder Wave
### Changes
- Sounds for Relic Coin Sacks have been correctly renamed. Relic Coin Pouches received new sounds for breaking and placing.
- Readjusted Petilil portraits so they fit a bit better.
- Improved handling of Pokémon taken from the Restoration Tank block to be a bit more stable.
- Made Mulch cheaper to craft.
### Fixes
- Fixed a bug in which adding organic material to the fossil tank via right click was adding the full count of the stack currently in hand
- Fixed a bug in which adding organic material to the restoration tank via right click was adding the full count of the stack currently in hand - but only taking 1 of the item.
- Fixed a niche issue where some properties of entities were not initialized correctly, causing Pokémon that appeared to be level 1 until you battle them.
- Fixed Fossilized Drake being missing from the Fossils item tag.
- Fixed PCStore#resize not allowing PC boxes size reduction.
- Fixed Gilded Chest block entity not being cleared on block break, creating spooky ghost blocks. Old ones can be fixed by placing something like a furnace where it was, then breaking the furnace.
- Fixed sherd brokenness on Forge.
- Fixed Supplementaries incompatibility.
- Fixed Fossil Compartment crash with Jade / WAILA forks.
- Fixed pasture block PC lookups when the player is offline.
- Fixed an untranslated battle message that occurs when using a move that just ran out of PP (e.g. Fire Blast that just got spited mid-turn).
- Fixed held items being eaten even when the held item evolutions are already unlocked.
- Fixed Hisuian Decidueye not being Grass/Fighting.
- Fixed both Decidueye forms learning both Triple Arrows and Spirit Shackle.
- Fixed Pineco being unable to evolve into Shulker Forretress.
- Fixed Kabutops T-posing when underwater. It doesn't have proper swimming animations yet, though.
- Fixed Pidgey's missing walk animation.
- Fixed Cyndaquil's hidden flames clipping if it was swimming.
- Fixed Chimecho and Chingling being unable to spawn near bells. They are meant to!
- Fixed Tyrantrum and Wailord Party Overlay models peeking through the chat box. It was kinda funny though.
- Fixed hitbox sizes for Seedot, Nuzleaf, and Shiftry.
- Fixed Budew and Lechonk sliding if they walked for too long.
- Fixed Shedinja T-posing in battle.
- Fixed recoil evolution condition not working, making things like Basculegion unobtainable.
- Fixed issue where poser debug tools didn't work on JSON posers.
- Fixed issue where gilded chests don't close when going far away.
- Fixed issue where the restoration tank's renderer was reading old data, making it appear wrong.
- Fixed issue where the lights on the restoration tank would not animate if it was facing east. Very specific.
- Fixed client crash with the fossil machine when updating block state on a chunk that is unloaded in the client. I don't understand this but the devs are sure that all of those are real words.
- Fixed Restoration Tank crash with Create upon the tank block's destruction.
- Fixed Restoration Tank over consuming items when interacting with Create blocks.
- Fixed addons that add very many moves to a learn-set causing disappearing Pokémon (visually) issues on servers.
- Fixed Hyper Cutter and Big Pecks incorrectly stating that it prevented accuracy from being lowered in battle.
- Fixed missing messages for Rough Skin and Iron Barbs in battle.
- Fixed a bug where sometimes Pokémon sendouts wouldn't create an entity, or the entity would spawn at 0 0 0 which is not a good place for a Pokémon to be. Or any of us, really.
- Fixed issue in which a locked gilded chest would animate to the open state when the client fails to open it, such as when it is locked.
- Fixed a bug where aspects of a form would not be properly reflected on form changes (eg. Normal -> Hisui).
- Fixed generic battle effect sounds not sounding the way they were intended to.
- Fixed particle effects often not having access to some specific entity functions from MoLang.
- Fixed particles sometimes lasting a single tick too long, causing (very quick) visual glitches.
- Fixed particle rotations being inverted.
- Fixed particle events not spawning at the instigating particle's location.
- Fixed a bunch of spam during world generation.
- Fixed a bug in which throwing a Poké Ball at a player owned Pokémon with the ability Illusion would reveal its true species. Hilarious meta strategy.
- Fixed root-part animations not working for JSON posed Pokémon. You didn't notice this but if we didn't fix this in this update then if you use Quick Attack a lot you'd have seen a whole lot of [this](https://cdn.discordapp.com/attachments/1076993968803434627/1242660506783715369/Minecraft__1.20.1_-_Singleplayer_2024-05-21_22-08-17.mp4?ex=66549408&is=66534288&hm=ff95ee293eb15634fd63e6546534ea279540a1c892605e8d561593ca2c5600c5&) which is damn funny but very unintended.
### Developer
- Changed SpawnAction#complete to return a nullable generic R (the spawn action result) instead of a boolean. More information this way.
- Changed SpawnAction#complete to return a nullable generic R (the spawn action result) instead of a boolean. Provides more information this way.
- Added an event that fires when a fossil is revived, with or without a player.
- Added IVS and EVS property extractors.
- Fixed PCStore#resize not allowing PC boxes size reduction.
### Data Pack & Resource Pack Creators
- Added support for MoLang conditions for quirks and poses.
- Changed the AttackDefenceRatio requirement to StatCompare and StatEqual.
- Changed the AttackDefenceRatio requirement to StatCompare and StatEqual. There is some backwards compatibility for AttackDefenceRatio, though.
- Changed "dimensions" spawn condition to check with dimension IDs instead of effects, so custom dimension IDs can be used.
- Added parametric motion and rotation support to particle effects.
- Added entity_scale as a molang var for particles (likely only applicable to Pokemon)
- Added support for primary quirk animations using the following format:
```JSON
{
"quirks": [
"q.bedrock_primary_quirk('<pokemon>', '<animation>', <minSeconds>, <maxSeconds>, <loopTimes>, '<excludedLabels>', q.curve('<waveFunction>'))"
]
}
```
### Localization
- Updated translations for:
- Simplified and Traditional Chinese.
- Spanish.
## [1.5.0 - The Ruins and Revival Update (May 12th, 2024)](#1-5-0)
#### "You're telling me that Mojang has added archaeology to the game? Hmm... that gives me an idea."
@@ -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;
import com.cobblemon.mod.common.entity.npc.NPCEntity;
import net.minecraft.entity.ai.brain.Brain;
import net.minecraft.entity.ai.brain.MemoryModuleType;
import net.minecraft.entity.ai.brain.sensor.Sensor;
import net.minecraft.entity.ai.brain.sensor.SensorType;
import java.util.Collection;
public class GenericsCheatClass {
// For some reason, doing this in the NPCEntity class in Kotlin gives confusing generic errors I could not resolve.
public static Brain.Profile<NPCEntity> createNPCBrain(Collection<MemoryModuleType<?>> memories, Collection<SensorType<? extends Sensor<? super NPCEntity>>> sensors) {
return Brain.createProfile(memories, sensors);
}
}
@@ -27,7 +27,6 @@ import com.cobblemon.mod.common.api.events.CobblemonEvents.TRADE_COMPLETED
import com.cobblemon.mod.common.api.net.serializers.IdentifierDataSerializer
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.UUIDSetDataSerializer
import com.cobblemon.mod.common.api.net.serializers.Vec3DataSerializer
import com.cobblemon.mod.common.api.permission.PermissionValidator
import com.cobblemon.mod.common.api.pokeball.catching.calculators.CaptureCalculator
@@ -50,13 +49,8 @@ import com.cobblemon.mod.common.api.scheduling.ServerRealTimeTaskTracker
import com.cobblemon.mod.common.api.scheduling.ServerTaskTracker
import com.cobblemon.mod.common.api.spawning.BestSpawner
import com.cobblemon.mod.common.api.spawning.CobblemonSpawningProspector
import com.cobblemon.mod.common.api.spawning.WorldSlice
import com.cobblemon.mod.common.api.spawning.context.AreaContextResolver
import com.cobblemon.mod.common.api.spawning.context.AreaSpawningContext
import com.cobblemon.mod.common.api.spawning.context.calculators.AreaSpawningContextCalculator
import com.cobblemon.mod.common.api.spawning.context.calculators.AreaSpawningInput
import com.cobblemon.mod.common.api.spawning.prospecting.SpawningProspector
import com.cobblemon.mod.common.api.spawning.spawner.Spawner
import com.cobblemon.mod.common.api.starter.StarterHandler
import com.cobblemon.mod.common.api.storage.PokemonStoreManager
import com.cobblemon.mod.common.api.storage.adapter.conversions.ReforgedConversion
@@ -93,7 +87,6 @@ import com.cobblemon.mod.common.config.constraint.IntConstraint
import com.cobblemon.mod.common.config.starter.StarterConfig
import com.cobblemon.mod.common.data.CobblemonDataProvider
import com.cobblemon.mod.common.events.AdvancementHandler
import com.cobblemon.mod.common.events.FlowHandler
import com.cobblemon.mod.common.events.ServerTickHandler
import com.cobblemon.mod.common.item.PokeBallItem
import com.cobblemon.mod.common.net.messages.client.settings.ServerSettingsPacket
@@ -105,16 +98,19 @@ 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.TagSeasonResolver
import com.cobblemon.mod.common.pokemon.helditem.CobblemonHeldItemManager
import com.cobblemon.mod.common.pokemon.properties.AspectPropertyType
import com.cobblemon.mod.common.pokemon.properties.HiddenAbilityPropertyType
import com.cobblemon.mod.common.pokemon.properties.UnaspectPropertyType
import com.cobblemon.mod.common.pokemon.properties.UncatchableProperty
import com.cobblemon.mod.common.pokemon.properties.tags.PokemonFlagProperty
import com.cobblemon.mod.common.pokemon.stat.CobblemonStatProvider
import com.cobblemon.mod.common.sherds.CobblemonSherds
import com.cobblemon.mod.common.starter.CobblemonStarterHandler
import com.cobblemon.mod.common.trade.TradeManager
import com.cobblemon.mod.common.util.*
import com.cobblemon.mod.common.util.DataKeys
import com.cobblemon.mod.common.util.cobblemonResource
import com.cobblemon.mod.common.util.ifDedicatedServer
import com.cobblemon.mod.common.util.isLaterVersion
import com.cobblemon.mod.common.util.party
import com.cobblemon.mod.common.util.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
@@ -129,7 +125,6 @@ import net.minecraft.item.Items
import net.minecraft.item.NameTagItem
import net.minecraft.registry.RegistryKey
import net.minecraft.util.WorldSavePath
import net.minecraft.util.math.BlockPos
import net.minecraft.world.World
import org.apache.logging.log4j.LogManager
import org.apache.logging.log4j.Logger
@@ -239,7 +234,7 @@ object Cobblemon {
val player = event.player
val block = player.world.getBlockState(event.pos).block
player.party().forEach { pokemon ->
pokemon.evolutions
pokemon.lockedEvolutions
.filterIsInstance<BlockClickEvolution>()
.forEach { evolution ->
evolution.attemptEvolution(pokemon, BlockClickEvolution.BlockInteractionContext(block, player.world))
@@ -258,8 +253,6 @@ object Cobblemon {
TrackedDataHandlerRegistry.register(StringSetDataSerializer)
TrackedDataHandlerRegistry.register(PoseTypeDataSerializer)
TrackedDataHandlerRegistry.register(IdentifierDataSerializer)
TrackedDataHandlerRegistry.register(IdentifierDataSerializer)
TrackedDataHandlerRegistry.register(UUIDSetDataSerializer)
// Lowest priority because this applies after luxury ball bonus as of gen 4
CobblemonEvents.FRIENDSHIP_UPDATED.subscribe(Priority.LOWEST) { event ->
@@ -297,10 +290,6 @@ object Cobblemon {
CustomPokemonProperty.register(UncatchableProperty)
CustomPokemonProperty.register(PokemonFlagProperty)
CustomPokemonProperty.register(HiddenAbilityPropertyType)
CustomPokemonProperty.register(AspectPropertyType)
CustomPokemonProperty.register(UnaspectPropertyType)
FlowHandler.setup()
ifDedicatedServer {
isDedicatedServer = true
@@ -382,36 +371,6 @@ object Cobblemon {
BATTLE_VICTORY.subscribe { AdvancementHandler.onWinBattle(it) }
EVOLUTION_COMPLETE.subscribe(Priority.LOWEST) { event ->
AdvancementHandler.onEvolve(event)
val pokemon = event.pokemon
val ninjaskIdentifier = cobblemonResource("ninjask")
// Ensure the config option is enabled and that the result was a ninjask and that shedinja exists
if (this.config.ninjaskCreatesShedinja && pokemon.species.resourceIdentifier == ninjaskIdentifier && PokemonSpecies.getByIdentifier(Pokemon.SHEDINJA) != null) {
val player = pokemon.getOwnerPlayer() ?: return@subscribe
if (player.isCreative || 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
}
}
}
if (!player.isCreative) {
player.inventory.removeAmountIf(1) { it.item is PokeBallItem }
}
if (pokeball == Items.AIR) {
pokeball = CobblemonItems.POKE_BALL
}
val properties = event.evolution.result.copy()
properties.species = Pokemon.SHEDINJA.toString()
val product = pokemon.clone()
product.removeHeldItem()
properties.apply(product)
product.caughtBall = (pokeball as PokeBallItem).pokeBall
pokemon.storeCoordinates.get()?.store?.add(product)
CobblemonCriteria.EVOLVE_POKEMON.trigger(player, EvolvePokemonContext(event.pokemon.preEvolution!!.species.resourceIdentifier, product.species.resourceIdentifier, playerData.get(player).advancementData.totalEvolvedCount))
}
}
}
LEVEL_UP_EVENT.subscribe { AdvancementHandler.onLevelUp(it) }
TRADE_COMPLETED.subscribe { AdvancementHandler.onTradeCompleted(it) }
@@ -426,7 +385,6 @@ object Cobblemon {
).ifSuccessful { it.mute = true }
}
CobblemonSherds.registerSherds()
}
fun getLevel(dimension: RegistryKey<World>): World? {
@@ -13,7 +13,6 @@ import net.minecraft.entity.ai.brain.Activity
object CobblemonActivities {
val activities = mutableListOf<Activity>()
val BATTLING_ACTIVITY = Activity("pokemon_battling")
val NPC_BATTLING = Activity("npc_battling")
fun register(activity: Activity): Activity {
activities.add(activity)
@@ -214,6 +214,213 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, RegistryKey<Registry<
.instrument(Instrument.BASEDRUM)
))
@JvmField
val POLISHED_TUMBLESTONE = this.create("polished_tumblestone", Block(AbstractBlock.Settings.create()
.mapColor(MapColor.TERRACOTTA_ORANGE)
.strength(1.0F)
.sounds(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS)
.requiresTool()
.instrument(Instrument.BASEDRUM)
))
@JvmField
val POLISHED_TUMBLESTONE_STAIRS = this.create("polished_tumblestone_stairs", StairsBlockInvoker.`cobblemon$create`(POLISHED_TUMBLESTONE.defaultState, AbstractBlock.Settings.copy(POLISHED_TUMBLESTONE)))
@JvmField
val POLISHED_TUMBLESTONE_SLAB = this.create("polished_tumblestone_slab", SlabBlock(AbstractBlock.Settings.create()
.mapColor(MapColor.TERRACOTTA_ORANGE)
.strength(1.0F)
.sounds(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS)
.requiresTool()
.instrument(Instrument.BASEDRUM)
))
@JvmField
val POLISHED_TUMBLESTONE_WALL = this.create("polished_tumblestone_wall", WallBlock(AbstractBlock.Settings.create()
.mapColor(MapColor.TERRACOTTA_ORANGE)
.strength(1.0F)
.sounds(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS)
.requiresTool()
.instrument(Instrument.BASEDRUM)
))
@JvmField
val CHISELED_POLISHED_TUMBLESTONE = this.create("chiseled_polished_tumblestone", Block(AbstractBlock.Settings.create()
.mapColor(MapColor.TERRACOTTA_ORANGE)
.strength(1.0F)
.sounds(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS)
.requiresTool()
.instrument(Instrument.BASEDRUM)
))
@JvmField
val TUMBLESTONE_BRICKS = this.create("tumblestone_bricks", Block(AbstractBlock.Settings.create()
.mapColor(MapColor.TERRACOTTA_ORANGE)
.strength(1.0F)
.sounds(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS)
.requiresTool()
.instrument(Instrument.BASEDRUM)
))
@JvmField
val TUMBLESTONE_BRICK_STAIRS = this.create("tumblestone_brick_stairs", StairsBlockInvoker.`cobblemon$create`(TUMBLESTONE_BRICKS.defaultState, AbstractBlock.Settings.copy(TUMBLESTONE_BRICKS)))
@JvmField
val TUMBLESTONE_BRICK_SLAB = this.create("tumblestone_brick_slab", SlabBlock(AbstractBlock.Settings.create()
.mapColor(MapColor.TERRACOTTA_ORANGE)
.strength(1.0F)
.sounds(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS)
.requiresTool()
.instrument(Instrument.BASEDRUM)
))
@JvmField
val TUMBLESTONE_BRICK_WALL = this.create("tumblestone_brick_wall", WallBlock(AbstractBlock.Settings.create()
.mapColor(MapColor.TERRACOTTA_ORANGE)
.strength(1.0F)
.sounds(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS)
.requiresTool()
.instrument(Instrument.BASEDRUM)
))
@JvmField
val CHISELED_TUMBLESTONE_BRICKS = this.create("chiseled_tumblestone_bricks", Block(AbstractBlock.Settings.create()
.mapColor(MapColor.TERRACOTTA_ORANGE)
.strength(1.0F)
.sounds(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS)
.requiresTool()
.instrument(Instrument.BASEDRUM)
))
@JvmField
val POLISHED_SKY_TUMBLESTONE = this.create("polished_sky_tumblestone", Block(AbstractBlock.Settings.create()
.mapColor(MapColor.LIGHT_BLUE)
.strength(1.0F)
.sounds(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS)
.requiresTool()
.instrument(Instrument.BASEDRUM)
))
@JvmField
val POLISHED_SKY_TUMBLESTONE_STAIRS = this.create("polished_sky_tumblestone_stairs", StairsBlockInvoker.`cobblemon$create`(POLISHED_SKY_TUMBLESTONE.defaultState, AbstractBlock.Settings.copy(POLISHED_SKY_TUMBLESTONE)))
@JvmField
val POLISHED_SKY_TUMBLESTONE_SLAB = this.create("polished_sky_tumblestone_slab", SlabBlock(AbstractBlock.Settings.create()
.mapColor(MapColor.LIGHT_BLUE)
.strength(1.0F)
.sounds(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS)
.requiresTool()
.instrument(Instrument.BASEDRUM)
))
@JvmField
val POLISHED_SKY_TUMBLESTONE_WALL = this.create("polished_sky_tumblestone_wall", WallBlock(AbstractBlock.Settings.create()
.mapColor(MapColor.LIGHT_BLUE)
.strength(1.0F)
.sounds(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS)
.requiresTool()
.instrument(Instrument.BASEDRUM)
))
@JvmField
val CHISELED_POLISHED_SKY_TUMBLESTONE = this.create("chiseled_polished_sky_tumblestone", Block(AbstractBlock.Settings.create()
.mapColor(MapColor.LIGHT_BLUE)
.strength(1.0F)
.sounds(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS)
.requiresTool()
.instrument(Instrument.BASEDRUM)
))
@JvmField
val SKY_TUMBLESTONE_BRICKS = this.create("sky_tumblestone_bricks", Block(AbstractBlock.Settings.create()
.mapColor(MapColor.LIGHT_BLUE)
.strength(1.0F)
.sounds(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS)
.requiresTool()
.instrument(Instrument.BASEDRUM)
))
@JvmField
val SKY_TUMBLESTONE_BRICK_STAIRS = this.create("sky_tumblestone_brick_stairs", StairsBlockInvoker.`cobblemon$create`(
SKY_TUMBLESTONE_BRICKS.defaultState, AbstractBlock.Settings.copy(SKY_TUMBLESTONE_BRICKS)))
@JvmField
val SKY_TUMBLESTONE_BRICK_SLAB = this.create("sky_tumblestone_brick_slab", SlabBlock(AbstractBlock.Settings.create()
.mapColor(MapColor.LIGHT_BLUE)
.strength(1.0F)
.sounds(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS)
.requiresTool()
.instrument(Instrument.BASEDRUM)
))
@JvmField
val SKY_TUMBLESTONE_BRICK_WALL = this.create("sky_tumblestone_brick_wall", WallBlock(AbstractBlock.Settings.create()
.mapColor(MapColor.LIGHT_BLUE)
.strength(1.0F)
.sounds(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS)
.requiresTool()
.instrument(Instrument.BASEDRUM)
))
@JvmField
val CHISELED_SKY_TUMBLESTONE_BRICKS = this.create("chiseled_sky_tumblestone_bricks", Block(AbstractBlock.Settings.create()
.mapColor(MapColor.LIGHT_BLUE)
.strength(1.0F)
.sounds(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS)
.requiresTool()
.instrument(Instrument.BASEDRUM)
))
@JvmField
val POLISHED_BLACK_TUMBLESTONE = this.create("polished_black_tumblestone", Block(AbstractBlock.Settings.create()
.mapColor(MapColor.TERRACOTTA_BLACK)
.strength(1.0F)
.sounds(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS)
.requiresTool()
.instrument(Instrument.BASEDRUM)
))
@JvmField
val POLISHED_BLACK_TUMBLESTONE_STAIRS = this.create("polished_black_tumblestone_stairs", StairsBlockInvoker.`cobblemon$create`(POLISHED_BLACK_TUMBLESTONE.defaultState, AbstractBlock.Settings.copy(POLISHED_BLACK_TUMBLESTONE)))
@JvmField
val POLISHED_BLACK_TUMBLESTONE_SLAB = this.create("polished_black_tumblestone_slab", SlabBlock(AbstractBlock.Settings.create()
.mapColor(MapColor.TERRACOTTA_BLACK)
.strength(1.0F)
.sounds(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS)
.requiresTool()
.instrument(Instrument.BASEDRUM)
))
@JvmField
val POLISHED_BLACK_TUMBLESTONE_WALL = this.create("polished_black_tumblestone_wall", WallBlock(AbstractBlock.Settings.create()
.mapColor(MapColor.TERRACOTTA_BLACK)
.strength(1.0F)
.sounds(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS)
.requiresTool()
.instrument(Instrument.BASEDRUM)
))
@JvmField
val CHISELED_POLISHED_BLACK_TUMBLESTONE = this.create("chiseled_polished_black_tumblestone", Block(AbstractBlock.Settings.create()
.mapColor(MapColor.TERRACOTTA_BLACK)
.strength(1.0F)
.sounds(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS)
.requiresTool()
.instrument(Instrument.BASEDRUM)
))
@JvmField
val BLACK_TUMBLESTONE_BRICKS = this.create("black_tumblestone_bricks", Block(AbstractBlock.Settings.create()
.mapColor(MapColor.TERRACOTTA_BLACK)
.strength(1.0F)
.sounds(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS)
.requiresTool()
.instrument(Instrument.BASEDRUM)
))
@JvmField
val BLACK_TUMBLESTONE_BRICK_STAIRS = this.create("black_tumblestone_brick_stairs", StairsBlockInvoker.`cobblemon$create`(
BLACK_TUMBLESTONE_BRICKS.defaultState, AbstractBlock.Settings.copy(BLACK_TUMBLESTONE_BRICKS)))
@JvmField
val BLACK_TUMBLESTONE_BRICK_SLAB = this.create("black_tumblestone_brick_slab", SlabBlock(AbstractBlock.Settings.create()
.mapColor(MapColor.TERRACOTTA_BLACK)
.strength(1.0F)
.sounds(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS)
.requiresTool()
.instrument(Instrument.BASEDRUM)
))
@JvmField
val BLACK_TUMBLESTONE_BRICK_WALL = this.create("black_tumblestone_brick_wall", WallBlock(AbstractBlock.Settings.create()
.mapColor(MapColor.TERRACOTTA_BLACK)
.strength(1.0F)
.sounds(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS)
.requiresTool()
.instrument(Instrument.BASEDRUM)
))
@JvmField
val CHISELED_BLACK_TUMBLESTONE_BRICKS = this.create("chiseled_black_tumblestone_bricks", Block(AbstractBlock.Settings.create()
.mapColor(MapColor.TERRACOTTA_BLACK)
.strength(1.0F)
.sounds(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS)
.requiresTool()
.instrument(Instrument.BASEDRUM)
))
@JvmField
val BLACK_APRICORN = apricornBlock("black_apricorn", Apricorn.BLACK)
@JvmField
@@ -528,6 +735,7 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, RegistryKey<Registry<
val WEPEAR_BERRY = this.berryBlock("wepear")
val WIKI_BERRY = this.berryBlock("wiki")
val YACHE_BERRY = this.berryBlock("yache")
//val BINDING_SOIL = this.create("binding_soil", BindingSoilBlock(AbstractBlock.Settings.create()))
init {
/**
@@ -48,7 +48,6 @@ object CobblemonCommands {
PokemonRestartCommand.register(dispatcher)
BedrockParticleCommand.register(dispatcher)
OpenDialogueCommand.register(dispatcher)
NPCEditCommand.register(dispatcher)
// Possibly lock down registration if and only if under dev environment or running in an environment
// with a certain system environment variable set
@@ -11,8 +11,6 @@ package com.cobblemon.mod.common
import com.cobblemon.mod.common.api.pokeball.PokeBalls
import com.cobblemon.mod.common.entity.boat.CobblemonBoatEntity
import com.cobblemon.mod.common.entity.boat.CobblemonChestBoatEntity
import com.cobblemon.mod.common.entity.fishing.PokeRodFishingBobberEntity
import com.cobblemon.mod.common.entity.npc.NPCEntity
import com.cobblemon.mod.common.entity.generic.GenericBedrockEntity
import com.cobblemon.mod.common.entity.pokeball.EmptyPokeBallEntity
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
@@ -68,15 +66,6 @@ object CobblemonEntities : PlatformRegistry<Registry<EntityType<*>>, RegistryKey
.build(CHEST_BOAT_KEY.toString())
)
@JvmField
val POKE_BOBBER_KEY = cobblemonResource("poke_bobber")
@JvmField
val POKE_BOBBER: EntityType<PokeRodFishingBobberEntity> = this.create(
POKE_BOBBER_KEY.path,
EntityType.Builder.create(::PokeRodFishingBobberEntity, SpawnGroup.MISC).setDimensions(0.5F, 0.5F).maxTrackingRange(10)
.build(POKE_BOBBER_KEY.toString())
)
@JvmField
val GENERIC_BEDROCK_ENTITY_KEY = cobblemonResource("generic_bedrock")
@JvmField
@@ -86,16 +75,8 @@ object CobblemonEntities : PlatformRegistry<Registry<EntityType<*>>, RegistryKey
.build(GENERIC_BEDROCK_ENTITY_KEY.toString())
)
@JvmField
val NPC_KEY = cobblemonResource("npc")
@JvmField
val NPC: EntityType<NPCEntity> = create(
NPC_KEY.path,
EntityType.Builder.create({ _, world -> NPCEntity(world) }, SpawnGroup.CREATURE).build("$NPC_KEY")
)
fun registerAttributes(consumer: (EntityType<out LivingEntity>, DefaultAttributeContainer.Builder) -> Unit) {
consumer(POKEMON, PokemonEntity.createAttributes())
consumer(NPC, NPCEntity.createAttributes())
}
}
@@ -1,74 +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.bedrockk.molang.runtime.MoLangRuntime
import com.bedrockk.molang.runtime.value.MoValue
import com.cobblemon.mod.common.api.data.DataRegistry
import com.cobblemon.mod.common.api.molang.ExpressionLike
import com.cobblemon.mod.common.api.molang.MoLangFunctions.setup
import com.cobblemon.mod.common.api.reactive.SimpleObservable
import com.cobblemon.mod.common.api.scripting.CobblemonScripts
import com.cobblemon.mod.common.util.asExpressionLike
import com.cobblemon.mod.common.util.cobblemonResource
import com.cobblemon.mod.common.util.endsWith
import java.util.concurrent.ExecutionException
import net.minecraft.resource.ResourceManager
import net.minecraft.resource.ResourceType
import net.minecraft.server.network.ServerPlayerEntity
import net.minecraft.util.Identifier
/**
* Holds all the flows that are loaded from the server's data packs. A flow is foldered under the event identifier,
* which can be cobblemon's namespace but can also be minecraft or any other namespace someone has added hooks for.
* The value of the map is a list of MoLang scripts that will execute when that event occurs.
*
* @author Hiroku
* @since February 24th, 2024
*/
object CobblemonFlows : DataRegistry {
override val id = cobblemonResource("flows")
override val observable = SimpleObservable<CobblemonFlows>()
override val type = ResourceType.SERVER_DATA
override fun sync(player: ServerPlayerEntity) {}
val runtime by lazy { MoLangRuntime().setup() }
val clientFlows = hashMapOf<Identifier, MutableList<ExpressionLike>>()
val flows = hashMapOf<Identifier, MutableList<ExpressionLike>>()
override fun reload(manager: ResourceManager) {
val folderBeforeNameRegex = ".*\\/([^\\/]+)\\/[^\\/]+\$".toRegex()
manager.findResources("flows") { path -> path.endsWith(CobblemonScripts.MOLANG_EXTENSION) }.forEach { (identifier, resource) ->
resource.inputStream.use { stream ->
stream.bufferedReader().use { reader ->
try {
val expression = reader.readText().asExpressionLike()
val event = folderBeforeNameRegex.find(identifier.path)?.groupValues?.get(1)
?: throw IllegalArgumentException("Invalid flow path: $identifier. Should have a folder structure that includes the name of the event being flowed.")
if (identifier.path.startsWith("flows/client/")) {
clientFlows.getOrPut(Identifier(identifier.namespace, event)) { mutableListOf() }.add(expression)
} else {
flows.getOrPut(Identifier(identifier.namespace, event)) { mutableListOf() }.add(expression)
}
} catch (exception: Exception) {
throw ExecutionException("Error loading MoLang script for flow: $identifier", exception)
}
}
}
}
Cobblemon.LOGGER.info("Loaded ${CobblemonScripts.scripts.size} flows and ${CobblemonScripts.clientScripts.size} client flows")
observable.emit(this)
}
fun run(eventIdentifier: Identifier, context: Map<String, MoValue>) {
flows[eventIdentifier]?.forEach { it.resolve(runtime, context) }
}
}
@@ -14,8 +14,6 @@ import com.cobblemon.mod.common.api.pokeball.PokeBalls
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.api.text.blue
import com.cobblemon.mod.common.api.text.gray
import com.cobblemon.mod.common.block.BerryBlock
import com.cobblemon.mod.common.block.MintBlock
import com.cobblemon.mod.common.block.MintBlock.MintType
@@ -25,6 +23,7 @@ import com.cobblemon.mod.common.item.armor.CobblemonArmorTrims
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.berry.BerryItem
import com.cobblemon.mod.common.item.berry.FriendshipRaisingBerryItem
import com.cobblemon.mod.common.item.berry.HealingBerryItem
import com.cobblemon.mod.common.item.berry.PPRestoringBerryItem
@@ -47,7 +46,6 @@ import net.minecraft.registry.Registries
import net.minecraft.registry.Registry
import net.minecraft.registry.RegistryKey
import net.minecraft.registry.RegistryKeys
import net.minecraft.text.Text
import net.minecraft.util.Identifier
import net.minecraft.world.World
@@ -936,15 +934,65 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, RegistryKey<Registry<It
val BLACK_TUMBLESTONE_BLOCK = blockItem("black_tumblestone_block", CobblemonBlocks.BLACK_TUMBLESTONE_BLOCK)
@JvmField
val POKEROD_SMITHING_TEMPLATE = create("pokerod_smithing_template", SmithingTemplateItem(
Text.translatable("item.minecraft.fishing_rod").blue(),
Text.translatable("item.cobblemon.smithing_template.pokerod.ingredients").blue(),
Text.translatable("upgrade.cobblemon.pokerod").gray(),
Text.translatable("item.cobblemon.smithing_template.pokerod.base_slot_description"),
Text.translatable("item.cobblemon.smithing_template.pokerod.additions_slot_description"),
listOf(cobblemonResource("item/empty_slot_fishing_rod")),
listOf(cobblemonResource("item/empty_slot_pokeball"))
))
val POLISHED_TUMBLESTONE = blockItem("polished_tumblestone", CobblemonBlocks.POLISHED_TUMBLESTONE)
@JvmField
val POLISHED_TUMBLESTONE_STAIRS = blockItem("polished_tumblestone_stairs", CobblemonBlocks.POLISHED_TUMBLESTONE_STAIRS)
@JvmField
val POLISHED_TUMBLESTONE_SLAB = blockItem("polished_tumblestone_slab", CobblemonBlocks.POLISHED_TUMBLESTONE_SLAB)
@JvmField
val POLISHED_TUMBLESTONE_WALL = blockItem("polished_tumblestone_wall", CobblemonBlocks.POLISHED_TUMBLESTONE_WALL)
@JvmField
val CHISELED_POLISHED_TUMBLESTONE = blockItem("chiseled_polished_tumblestone", CobblemonBlocks.CHISELED_POLISHED_TUMBLESTONE)
@JvmField
val TUMBLESTONE_BRICKS = blockItem("tumblestone_bricks", CobblemonBlocks.TUMBLESTONE_BRICKS)
@JvmField
val TUMBLESTONE_BRICK_STAIRS = blockItem("tumblestone_brick_stairs", CobblemonBlocks.TUMBLESTONE_BRICK_STAIRS)
@JvmField
val TUMBLESTONE_BRICK_SLAB = blockItem("tumblestone_brick_slab", CobblemonBlocks.TUMBLESTONE_BRICK_SLAB)
@JvmField
val TUMBLESTONE_BRICK_WALL = blockItem("tumblestone_brick_wall", CobblemonBlocks.TUMBLESTONE_BRICK_WALL)
@JvmField
val CHISELED_TUMBLESTONE_BRICKS = blockItem("chiseled_tumblestone_bricks", CobblemonBlocks.CHISELED_TUMBLESTONE_BRICKS)
@JvmField
val POLISHED_SKY_TUMBLESTONE = blockItem("polished_sky_tumblestone", CobblemonBlocks.POLISHED_SKY_TUMBLESTONE)
@JvmField
val POLISHED_SKY_TUMBLESTONE_STAIRS = blockItem("polished_sky_tumblestone_stairs", CobblemonBlocks.POLISHED_SKY_TUMBLESTONE_STAIRS)
@JvmField
val POLISHED_SKY_TUMBLESTONE_SLAB = blockItem("polished_sky_tumblestone_slab", CobblemonBlocks.POLISHED_SKY_TUMBLESTONE_SLAB)
@JvmField
val POLISHED_SKY_TUMBLESTONE_WALL = blockItem("polished_sky_tumblestone_wall", CobblemonBlocks.POLISHED_SKY_TUMBLESTONE_WALL)
@JvmField
val CHISELED_POLISHED_SKY_TUMBLESTONE = blockItem("chiseled_polished_sky_tumblestone", CobblemonBlocks.CHISELED_POLISHED_SKY_TUMBLESTONE)
@JvmField
val SKY_TUMBLESTONE_BRICKS = blockItem("sky_tumblestone_bricks", CobblemonBlocks.SKY_TUMBLESTONE_BRICKS)
@JvmField
val SKY_TUMBLESTONE_BRICK_STAIRS = blockItem("sky_tumblestone_brick_stairs", CobblemonBlocks.SKY_TUMBLESTONE_BRICK_STAIRS)
@JvmField
val SKY_TUMBLESTONE_BRICK_SLAB = blockItem("sky_tumblestone_brick_slab", CobblemonBlocks.SKY_TUMBLESTONE_BRICK_SLAB)
@JvmField
val SKY_TUMBLESTONE_BRICK_WALL = blockItem("sky_tumblestone_brick_wall", CobblemonBlocks.SKY_TUMBLESTONE_BRICK_WALL)
@JvmField
val CHISELED_SKY_TUMBLESTONE_BRICKS = blockItem("chiseled_sky_tumblestone_bricks", CobblemonBlocks.CHISELED_SKY_TUMBLESTONE_BRICKS)
@JvmField
val POLISHED_BLACK_TUMBLESTONE = blockItem("polished_black_tumblestone", CobblemonBlocks.POLISHED_BLACK_TUMBLESTONE)
@JvmField
val POLISHED_BLACK_TUMBLESTONE_STAIRS = blockItem("polished_black_tumblestone_stairs", CobblemonBlocks.POLISHED_BLACK_TUMBLESTONE_STAIRS)
@JvmField
val POLISHED_BLACK_TUMBLESTONE_SLAB = blockItem("polished_black_tumblestone_slab", CobblemonBlocks.POLISHED_BLACK_TUMBLESTONE_SLAB)
@JvmField
val POLISHED_BLACK_TUMBLESTONE_WALL = blockItem("polished_black_tumblestone_wall", CobblemonBlocks.POLISHED_BLACK_TUMBLESTONE_WALL)
@JvmField
val CHISELED_POLISHED_BLACK_TUMBLESTONE = blockItem("chiseled_polished_black_tumblestone", CobblemonBlocks.CHISELED_POLISHED_BLACK_TUMBLESTONE)
@JvmField
val BLACK_TUMBLESTONE_BRICKS = blockItem("black_tumblestone_bricks", CobblemonBlocks.BLACK_TUMBLESTONE_BRICKS)
@JvmField
val BLACK_TUMBLESTONE_BRICK_STAIRS = blockItem("black_tumblestone_brick_stairs", CobblemonBlocks.BLACK_TUMBLESTONE_BRICK_STAIRS)
@JvmField
val BLACK_TUMBLESTONE_BRICK_SLAB = blockItem("black_tumblestone_brick_slab", CobblemonBlocks.BLACK_TUMBLESTONE_BRICK_SLAB)
@JvmField
val BLACK_TUMBLESTONE_BRICK_WALL = blockItem("black_tumblestone_brick_wall", CobblemonBlocks.BLACK_TUMBLESTONE_BRICK_WALL)
@JvmField
val CHISELED_BLACK_TUMBLESTONE_BRICKS = blockItem("chiseled_black_tumblestone_bricks", CobblemonBlocks.CHISELED_BLACK_TUMBLESTONE_BRICKS)
@JvmField
val AUTOMATON_ARMOR_TRIM_SMITHING_TEMPLATE: SmithingTemplateItem = this.create(
@@ -952,104 +1000,6 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, RegistryKey<Registry<It
SmithingTemplateItem.of(CobblemonArmorTrims.AUTOMATON)
)
val pokeRods = mutableListOf<PokerodItem>()
@JvmField
val POKE_ROD = pokerodItem(cobblemonResource("poke_rod"))
@JvmField
val CITRINE_ROD = pokerodItem(cobblemonResource("citrine_rod"))
@JvmField
val VERDANT_ROD = pokerodItem(cobblemonResource("verdant_rod"))
@JvmField
val AZURE_ROD = pokerodItem(cobblemonResource("azure_rod"))
@JvmField
val ROSEATE_ROD = pokerodItem(cobblemonResource("roseate_rod"))
@JvmField
val SLATE_ROD = pokerodItem(cobblemonResource("slate_rod"))
@JvmField
val PREMIER_ROD = pokerodItem(cobblemonResource("premier_rod"))
@JvmField
val GREAT_ROD = pokerodItem(cobblemonResource("great_rod"))
@JvmField
val ULTRA_ROD = pokerodItem(cobblemonResource("ultra_rod"))
@JvmField
val SAFARI_ROD = pokerodItem(cobblemonResource("safari_rod"))
@JvmField
val FAST_ROD = pokerodItem(cobblemonResource("fast_rod"))
@JvmField
val LEVEL_ROD = pokerodItem(cobblemonResource("level_rod"))
@JvmField
val LURE_ROD = pokerodItem(cobblemonResource("lure_rod"))
@JvmField
val HEAVY_ROD = pokerodItem(cobblemonResource("heavy_rod"))
@JvmField
val LOVE_ROD = pokerodItem(cobblemonResource("love_rod"))
@JvmField
val FRIEND_ROD = pokerodItem(cobblemonResource("friend_rod"))
@JvmField
val MOON_ROD = pokerodItem(cobblemonResource("moon_rod"))
@JvmField
val SPORT_ROD = pokerodItem(cobblemonResource("sport_rod"))
@JvmField
val PARK_ROD = pokerodItem(cobblemonResource("park_rod"))
@JvmField
val NET_ROD = pokerodItem(cobblemonResource("net_rod"))
@JvmField
val DIVE_ROD = pokerodItem(cobblemonResource("dive_rod"))
@JvmField
val NEST_ROD = pokerodItem(cobblemonResource("nest_rod"))
@JvmField
val REPEAT_ROD = pokerodItem(cobblemonResource("repeat_rod"))
@JvmField
val TIMER_ROD = pokerodItem(cobblemonResource("timer_rod"))
@JvmField
val LUXURY_ROD = pokerodItem(cobblemonResource("luxury_rod"))
@JvmField
val DUSK_ROD = pokerodItem(cobblemonResource("dusk_rod"))
@JvmField
val HEAL_ROD = pokerodItem(cobblemonResource("heal_rod"))
@JvmField
val QUICK_ROD = pokerodItem(cobblemonResource("quick_rod"))
@JvmField
val DREAM_ROD = pokerodItem(cobblemonResource("dream_rod"))
@JvmField
val BEAST_ROD = pokerodItem(cobblemonResource("beast_rod"))
@JvmField
val MASTER_ROD = pokerodItem(cobblemonResource("master_rod"))
@JvmField
val CHERISH_ROD = pokerodItem(cobblemonResource("cherish_rod"))
@JvmField
val ANCIENT_POKE_ROD = pokerodItem(cobblemonResource("ancient_poke_rod"))
@JvmField
val ANCIENT_CITRINE_ROD = pokerodItem(cobblemonResource("ancient_citrine_rod"))
@JvmField
val ANCIENT_VERDANT_ROD = pokerodItem(cobblemonResource("ancient_verdant_rod"))
@JvmField
val ANCIENT_AZURE_ROD = pokerodItem(cobblemonResource("ancient_azure_rod"))
@JvmField
val ANCIENT_ROSEATE_ROD = pokerodItem(cobblemonResource("ancient_roseate_rod"))
@JvmField
val ANCIENT_SLATE_ROD = pokerodItem(cobblemonResource("ancient_slate_rod"))
@JvmField
val ANCIENT_IVORY_ROD = pokerodItem(cobblemonResource("ancient_ivory_rod"))
@JvmField
val ANCIENT_GREAT_ROD = pokerodItem(cobblemonResource("ancient_great_rod"))
@JvmField
val ANCIENT_ULTRA_ROD = pokerodItem(cobblemonResource("ancient_ultra_rod"))
@JvmField
val ANCIENT_FEATHER_ROD = pokerodItem(cobblemonResource("ancient_feather_rod"))
@JvmField
val ANCIENT_WING_ROD = pokerodItem(cobblemonResource("ancient_wing_rod"))
@JvmField
val ANCIENT_JET_ROD = pokerodItem(cobblemonResource("ancient_jet_rod"))
@JvmField
val ANCIENT_HEAVY_ROD = pokerodItem(cobblemonResource("ancient_heavy_rod"))
@JvmField
val ANCIENT_LEADEN_ROD = pokerodItem(cobblemonResource("ancient_leaden_rod"))
@JvmField
val ANCIENT_GIGATON_ROD = pokerodItem(cobblemonResource("ancient_gigaton_rod"))
@JvmField
val ANCIENT_ORIGIN_ROD = pokerodItem(cobblemonResource("ancient_origin_rod"))
// Misc
@JvmField
val POKEMON_MODEL = this.create("pokemon_model", PokemonItem())
@@ -1097,6 +1047,8 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, RegistryKey<Registry<It
val STEEL_GEM = noSettingsItem("steel_gem")
@JvmField
val FAIRY_GEM = noSettingsItem("fairy_gem")
//@JvmField
//val BINDING_SOIL = blockItem("binding_soil", CobblemonBlocks.BINDING_SOIL)
private fun blockItem(name: String, block: Block): BlockItem = this.create(name, BlockItem(block, Item.Settings()))
@@ -1115,13 +1067,6 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, RegistryKey<Registry<It
private fun candyItem(name: String, calculator: CandyItem.Calculator): CandyItem = this.create(name, CandyItem(calculator))
private fun pokerodItem(pokeRodId: Identifier): PokerodItem {
val settings = Item.Settings().maxCount(1).maxDamage(Items.FISHING_ROD.maxDamage)
val item = create(pokeRodId.path, PokerodItem(pokeRodId, settings))
pokeRods.add(item)
return item
}
private fun heldItem(name: String, remappedName: String? = null): CobblemonItem = create(
name,
CobblemonItem(Item.Settings()).also {
@@ -10,13 +10,11 @@ package com.cobblemon.mod.common
import com.bedrockk.molang.Expression
import com.cobblemon.mod.common.api.data.DataRegistry
import com.cobblemon.mod.common.api.molang.ExpressionLike
import com.cobblemon.mod.common.api.reactive.SimpleObservable
import com.cobblemon.mod.common.mechanics.BerriesMechanic
import com.cobblemon.mod.common.mechanics.PotionsMechanic
import com.cobblemon.mod.common.mechanics.RemediesMechanic
import com.cobblemon.mod.common.util.adapters.ExpressionAdapter
import com.cobblemon.mod.common.util.adapters.ExpressionLikeAdapter
import com.cobblemon.mod.common.util.cobblemonResource
import com.google.gson.GsonBuilder
import net.minecraft.resource.ResourceManager
@@ -31,7 +29,6 @@ object CobblemonMechanics : DataRegistry {
val gson = GsonBuilder()
.setPrettyPrinting()
.registerTypeAdapter(Expression::class.java, ExpressionAdapter)
.registerTypeAdapter(ExpressionLike::class.java, ExpressionLikeAdapter)
.create()
var remedies = RemediesMechanic()
@@ -1,35 +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.mojang.serialization.Codec
import com.mojang.serialization.codecs.ListCodec
import com.mojang.serialization.codecs.PrimitiveCodec
import java.util.Optional
import net.minecraft.entity.ai.brain.MemoryModuleType
import net.minecraft.util.Uuids
object CobblemonMemories {
val memories = mutableMapOf<String, MemoryModuleType<*>>()
val BATTLING_POKEMON = register("battling_pokemon", ListCodec(Uuids.INT_STREAM_CODEC))
val NPC_BATTLING = register("npc_battling", PrimitiveCodec.BOOL)
fun <U> register(id: String, codec: Codec<U>): MemoryModuleType<U> {
val memoryModule = MemoryModuleType(Optional.of(codec))
memories[id] = memoryModule
return memoryModule
}
fun <U> register(id: String): MemoryModuleType<U> {
val memoryModule = MemoryModuleType<U>(Optional.empty())
memories[id] = memoryModule
return memoryModule
}
}
@@ -20,15 +20,13 @@ import com.cobblemon.mod.common.client.net.callback.party.OpenPartyCallbackHandl
import com.cobblemon.mod.common.client.net.callback.partymove.OpenPartyMoveCallbackHandler
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.RunPosableMoLangHandler
import com.cobblemon.mod.common.client.net.dialogue.DialogueClosedHandler
import com.cobblemon.mod.common.client.net.dialogue.DialogueOpenedHandler
import com.cobblemon.mod.common.client.net.effect.RunPosableMoLangHandler
import com.cobblemon.mod.common.client.net.effect.SpawnSnowstormEntityParticleHandler
import com.cobblemon.mod.common.client.net.effect.SpawnSnowstormParticleHandler
import com.cobblemon.mod.common.client.net.gui.InteractPokemonUIPacketHandler
import com.cobblemon.mod.common.client.net.gui.SummaryUIPacketHandler
import com.cobblemon.mod.common.client.net.npc.CloseNPCEditorHandler
import com.cobblemon.mod.common.client.net.npc.OpenNPCEditorHandler
import com.cobblemon.mod.common.client.net.pasture.ClosePastureHandler
import com.cobblemon.mod.common.client.net.pasture.OpenPastureHandler
import com.cobblemon.mod.common.client.net.pasture.PokemonPasturedHandler
@@ -66,16 +64,13 @@ import com.cobblemon.mod.common.net.messages.client.callback.OpenPartyCallbackPa
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.BerryRegistrySyncPacket
import com.cobblemon.mod.common.net.messages.client.data.FlowRegistrySyncPacket
import com.cobblemon.mod.common.net.messages.client.data.GlobalSpeciesFeatureSyncPacket
import com.cobblemon.mod.common.net.messages.client.data.MovesRegistrySyncPacket
import com.cobblemon.mod.common.net.messages.client.data.NPCRegistrySyncPacket
import com.cobblemon.mod.common.net.messages.client.data.PropertiesCompletionRegistrySyncPacket
import com.cobblemon.mod.common.net.messages.client.data.SpeciesFeatureAssignmentSyncPacket
import com.cobblemon.mod.common.net.messages.client.data.SpeciesRegistrySyncPacket
import com.cobblemon.mod.common.net.messages.client.data.StandardSpeciesFeatureSyncPacket
import com.cobblemon.mod.common.net.messages.client.data.UnlockReloadPacket
import com.cobblemon.mod.common.net.messages.client.data.*
import com.cobblemon.mod.common.net.messages.client.dialogue.DialogueClosedPacket
import com.cobblemon.mod.common.net.messages.client.dialogue.DialogueOpenedPacket
import com.cobblemon.mod.common.net.messages.client.effect.RunPosableMoLangPacket
@@ -83,8 +78,6 @@ import com.cobblemon.mod.common.net.messages.client.effect.SpawnSnowstormEntityP
import com.cobblemon.mod.common.net.messages.client.effect.SpawnSnowstormParticlePacket
import com.cobblemon.mod.common.net.messages.client.fossil.FossilRegistrySyncPacket
import com.cobblemon.mod.common.net.messages.client.fossil.NaturalMaterialRegistrySyncPacket
import com.cobblemon.mod.common.net.messages.client.npc.CloseNPCEditorPacket
import com.cobblemon.mod.common.net.messages.client.npc.OpenNPCEditorPacket
import com.cobblemon.mod.common.net.messages.client.pasture.ClosePasturePacket
import com.cobblemon.mod.common.net.messages.client.pasture.OpenPasturePacket
import com.cobblemon.mod.common.net.messages.client.pasture.PokemonPasturedPacket
@@ -122,12 +115,7 @@ import com.cobblemon.mod.common.net.messages.client.trade.TradeStartedPacket
import com.cobblemon.mod.common.net.messages.client.trade.TradeUpdatedPacket
import com.cobblemon.mod.common.net.messages.client.ui.InteractPokemonUIPacket
import com.cobblemon.mod.common.net.messages.client.ui.SummaryUIPacket
import com.cobblemon.mod.common.net.messages.server.BattleChallengePacket
import com.cobblemon.mod.common.net.messages.server.BenchMovePacket
import com.cobblemon.mod.common.net.messages.server.RequestMoveSwapPacket
import com.cobblemon.mod.common.net.messages.server.RequestPlayerInteractionsPacket
import com.cobblemon.mod.common.net.messages.server.SelectStarterPacket
import com.cobblemon.mod.common.net.messages.server.SendOutPokemonPacket
import com.cobblemon.mod.common.net.messages.server.*
import com.cobblemon.mod.common.net.messages.server.battle.BattleSelectActionsPacket
import com.cobblemon.mod.common.net.messages.server.battle.RemoveSpectatorPacket
import com.cobblemon.mod.common.net.messages.server.battle.SpectateBattlePacket
@@ -139,7 +127,6 @@ import com.cobblemon.mod.common.net.messages.server.callback.partymove.PartyMove
import com.cobblemon.mod.common.net.messages.server.callback.partymove.PartyPokemonMoveSelectedPacket
import com.cobblemon.mod.common.net.messages.server.dialogue.EscapeDialoguePacket
import com.cobblemon.mod.common.net.messages.server.dialogue.InputToDialoguePacket
import com.cobblemon.mod.common.net.messages.server.npc.SaveNPCPacket
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
@@ -176,7 +163,6 @@ import com.cobblemon.mod.common.net.serverhandling.callback.partymove.PartyPokem
import com.cobblemon.mod.common.net.serverhandling.dialogue.EscapeDialogueHandler
import com.cobblemon.mod.common.net.serverhandling.dialogue.InputToDialogueHandler
import com.cobblemon.mod.common.net.serverhandling.evolution.AcceptEvolutionHandler
import com.cobblemon.mod.common.net.serverhandling.npc.SaveNPCHandler
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
@@ -203,12 +189,12 @@ import com.cobblemon.mod.common.net.serverhandling.trade.ChangeTradeAcceptanceHa
import com.cobblemon.mod.common.net.serverhandling.trade.OfferTradeHandler
import com.cobblemon.mod.common.net.serverhandling.trade.UpdateTradeOfferHandler
import com.cobblemon.mod.common.util.server
import kotlin.reflect.KClass
import net.minecraft.network.PacketByteBuf
import net.minecraft.network.listener.ClientPlayPacketListener
import net.minecraft.network.packet.Packet
import net.minecraft.server.network.ServerPlayerEntity
import net.minecraft.util.Identifier
import kotlin.reflect.KClass
/**
* Registers Cobblemon network packets.
@@ -249,6 +235,7 @@ object CobblemonNetwork : NetworkManager {
this.createClientBound(TradeableUpdatePacket.ID, TradeableUpdatePacket::decode, PokemonUpdatePacketHandler())
this.createClientBound(SpeciesFeatureUpdatePacket.ID, SpeciesFeatureUpdatePacket::decode, PokemonUpdatePacketHandler())
this.createClientBound(OriginalTrainerUpdatePacket.ID, OriginalTrainerUpdatePacket::decode, PokemonUpdatePacketHandler())
this.createClientBound(FormUpdatePacket.ID, FormUpdatePacket::decode, PokemonUpdatePacketHandler())
// Evolution start
this.createClientBound(AddEvolutionPacket.ID, AddEvolutionPacket::decode, PokemonUpdatePacketHandler())
@@ -314,7 +301,6 @@ object CobblemonNetwork : NetworkManager {
this.createClientBound(MovesRegistrySyncPacket.ID, MovesRegistrySyncPacket::decode, DataRegistrySyncPacketHandler())
this.createClientBound(SpeciesRegistrySyncPacket.ID, SpeciesRegistrySyncPacket::decode, DataRegistrySyncPacketHandler())
this.createClientBound(PropertiesCompletionRegistrySyncPacket.ID, PropertiesCompletionRegistrySyncPacket::decode, DataRegistrySyncPacketHandler())
this.createClientBound(NPCRegistrySyncPacket.ID, NPCRegistrySyncPacket::decode, DataRegistrySyncPacketHandler())
this.createClientBound(UnlockReloadPacket.ID, UnlockReloadPacket::decode, UnlockReloadPacketHandler)
this.createClientBound(BerryRegistrySyncPacket.ID, BerryRegistrySyncPacket::decode, DataRegistrySyncPacketHandler())
this.createClientBound(StandardSpeciesFeatureSyncPacket.ID, StandardSpeciesFeatureSyncPacket::decode, DataRegistrySyncPacketHandler())
@@ -322,8 +308,6 @@ object CobblemonNetwork : NetworkManager {
this.createClientBound(SpeciesFeatureAssignmentSyncPacket.ID, SpeciesFeatureAssignmentSyncPacket::decode, DataRegistrySyncPacketHandler())
this.createClientBound(NaturalMaterialRegistrySyncPacket.ID, NaturalMaterialRegistrySyncPacket::decode, DataRegistrySyncPacketHandler())
this.createClientBound(FossilRegistrySyncPacket.ID, FossilRegistrySyncPacket::decode, DataRegistrySyncPacketHandler())
this.createClientBound(PokeRodRegistrySyncPacket.ID, PokeRodRegistrySyncPacket::decode, DataRegistrySyncPacketHandler())
this.createClientBound(FlowRegistrySyncPacket.ID, FlowRegistrySyncPacket::decode, DataRegistrySyncPacketHandler())
// Effects
this.createClientBound(SpawnSnowstormParticlePacket.ID, SpawnSnowstormParticlePacket::decode, SpawnSnowstormParticleHandler)
@@ -367,10 +351,6 @@ object CobblemonNetwork : NetworkManager {
// Dialogue packets
this.createClientBound(DialogueClosedPacket.ID, DialogueClosedPacket::decode, DialogueClosedHandler)
this.createClientBound(DialogueOpenedPacket.ID, DialogueOpenedPacket::decode, DialogueOpenedHandler)
// NPCs
this.createClientBound(CloseNPCEditorPacket.ID, CloseNPCEditorPacket::decode, CloseNPCEditorHandler)
this.createClientBound(OpenNPCEditorPacket.ID, OpenNPCEditorPacket::decode, OpenNPCEditorHandler)
}
override fun registerServerBound() {
@@ -440,9 +420,6 @@ object CobblemonNetwork : NetworkManager {
// Dialogue packets
this.createServerBound(EscapeDialoguePacket.ID, EscapeDialoguePacket::decode, EscapeDialogueHandler)
this.createServerBound(InputToDialoguePacket.ID, InputToDialoguePacket::decode, InputToDialogueHandler)
// NPC packets
this.createServerBound(SaveNPCPacket.ID, SaveNPCPacket::decode, SaveNPCHandler)
}
private inline fun <reified T : NetworkPacket<T>> createClientBound(identifier: Identifier, noinline decoder: (PacketByteBuf) -> T, handler: ClientNetworkPacketHandler<T>) {
@@ -1,29 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common
import com.cobblemon.mod.common.entity.sensor.BattlingPokemonSensor
import com.cobblemon.mod.common.entity.sensor.NPCBattlingSensor
import java.util.function.Supplier
import net.minecraft.entity.Entity
import net.minecraft.entity.ai.brain.sensor.Sensor
import net.minecraft.entity.ai.brain.sensor.SensorType
object CobblemonSensors {
val sensors = mutableMapOf<String, SensorType<*>>()
val NPC_BATTLING = register("npc_battling", ::NPCBattlingSensor)
val BATTLING_POKEMON = register("battling_pokemon", ::BattlingPokemonSensor)
fun <E : Entity, U : Sensor<E>> register(id: String, supplier: Supplier<U>): SensorType<U> {
val sensor = SensorType(supplier)
sensors[id] = sensor
return sensor
}
}
@@ -134,14 +134,6 @@ object CobblemonSounds : PlatformRegistry<Registry<SoundEvent>, RegistryKey<Regi
@JvmField
val RELIC_COIN_POUCH_PLACE = this.create("relic_coin_pouch.place")
@JvmField
val FISHING_NOTIFICATION = this.create("fishing.notification")
@JvmField
val FISHING_SPLASH_BIG = this.create("fishing.splash_big")
@JvmField
val FISHING_SPLASH_SMALL = this.create("fishing.splash_small")
@JvmField
val FISHING_BOBBER_LAND = this.create("fishing.bobber_land")
@JvmField
val TUMBLESTONE_BREAK = this.create("tumblestone.break")
@JvmField
@@ -32,14 +32,7 @@ object CobblemonTradeOffers {
* @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, 24, 1, 1, 6)))
)
VillagerProfession.FISHERMAN -> listOf(
VillagerTradeOffer(VillagerProfession.FISHERMAN, 5, listOf(
TradeOffers.SellItemFactory(CobblemonItems.POKEROD_SMITHING_TEMPLATE, 12, 3, 30)
))
)
VillagerProfession.FARMER -> listOf(VillagerTradeOffer(VillagerProfession.FARMER, 3, listOf(TradeOffers.SellItemFactory(CobblemonItems.VIVICHOKE_SEEDS, 24, 1, 1, 6))))
else -> emptyList()
}
@@ -113,13 +113,6 @@ object CobblemonCriteria {
)
)
val CAST_POKE_ROD = this.create(
SimpleCriterionTrigger(
cobblemonResource("cast_poke_rod"),
CastPokeRodCriterionCondition::class.java
)
)
// Advancement criteria for [grow_tumblestone.json]
val PLANT_TUMBLESTONE = this.create(
SimpleCriterionTrigger(
@@ -1,30 +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.advancement.criterion
import com.google.gson.JsonObject
import net.minecraft.predicate.entity.LootContextPredicate
import net.minecraft.server.network.ServerPlayerEntity
import net.minecraft.util.Identifier
class CastPokeRodCriterionCondition(id: Identifier, predicate: LootContextPredicate): SimpleCriterionCondition<Boolean>(id, predicate) {
var hasBait: Boolean = false
override fun toJson(json: JsonObject) {
json.addProperty("hasBait", hasBait)
}
override fun fromJson(json: JsonObject) {
hasBait = json.get("hasBait").asBoolean
}
override fun matches(player: ServerPlayerEntity, context: Boolean): Boolean {
return hasBait == context
}
}
@@ -8,7 +8,6 @@
package com.cobblemon.mod.common.api.battles.model
import com.bedrockk.molang.runtime.MoLangRuntime
import com.bedrockk.molang.runtime.struct.QueryStruct
import com.bedrockk.molang.runtime.value.DoubleValue
import com.cobblemon.mod.common.Cobblemon
@@ -21,8 +20,6 @@ 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.molang.MoLangFunctions.asMoLangValue
import com.cobblemon.mod.common.api.molang.MoLangFunctions.getQueryStruct
import com.cobblemon.mod.common.api.net.NetworkPacket
import com.cobblemon.mod.common.api.tags.CobblemonItemTags
import com.cobblemon.mod.common.api.text.red
@@ -49,10 +46,8 @@ import com.cobblemon.mod.common.pokemon.evolution.progress.LastBattleCriticalHit
import com.cobblemon.mod.common.pokemon.evolution.requirements.DefeatRequirement
import com.cobblemon.mod.common.util.battleLang
import com.cobblemon.mod.common.util.getPlayer
import com.cobblemon.mod.common.util.withQueryValue
import java.io.File
import java.util.UUID
import java.util.concurrent.CompletableFuture
import net.minecraft.server.network.ServerPlayerEntity
import net.minecraft.text.Text
import java.util.concurrent.ConcurrentLinkedDeque
@@ -71,10 +66,6 @@ open class PokemonBattle(
) {
/** Whether logging will be silenced for this battle. */
var mute = true
val struct = this.asMoLangValue()
val runtime = MoLangRuntime().also { it.environment.structs["query"] = struct }
val onEndHandlers: MutableList<(PokemonBattle) -> Unit> = mutableListOf()
init {
side1.battle = this
@@ -106,8 +97,6 @@ open class PokemonBattle(
val battleLog = mutableListOf<String>()
val chatLog = mutableListOf<Text>()
var started = false
var winners = listOf<BattleActor>()
var losers = listOf<BattleActor>()
var ended = false
// TEMP battle showcase stuff
var announcingRules = false
@@ -237,7 +226,7 @@ open class PokemonBattle(
val facedFainted = opponentPokemon.facedOpponents.contains(faintedPokemon)
val pokemon = opponentPokemon.effectedPokemon
if (facedFainted) {
pokemon.evolutions.forEach { evolution ->
pokemon.lockedEvolutions.forEach { evolution ->
evolution.requirements.filterIsInstance<DefeatRequirement>().forEach { defeatRequirement ->
if (defeatRequirement.target.matches(faintedPokemon.effectedPokemon)) {
val progress = pokemon.evolutionProxy.current().progressFirstOrCreate({ it is DefeatEvolutionProgress && it.currentProgress().target == defeatRequirement.target }) { DefeatEvolutionProgress() }
@@ -277,7 +266,6 @@ open class PokemonBattle(
}
sendUpdate(BattleEndPacket())
BattleRegistry.closeBattle(this)
onEndHandlers.forEach { it(this) }
}
fun finishCaptureAction(captureAction: BattleCaptureAction) {
@@ -365,14 +353,6 @@ open class PokemonBattle(
}
}
fun dispatchFuture(future: () -> CompletableFuture<*>) {
val dispatch = BattleDispatch {
val generatedFuture = future()
return@BattleDispatch DispatchResult { generatedFuture.isDone }
}
dispatches.add(dispatch)
}
fun dispatchInsert(dispatcher: () -> Iterable<BattleDispatch>) {
dispatch {
val newDispatches = dispatcher()
@@ -145,7 +145,4 @@ abstract class BattleActor(
}
open fun awardExperience(battlePokemon: BattlePokemon, experience: Int) {}
open fun sendUpdate(packet: NetworkPacket<*>) {}
open fun win(otherWinners: List<BattleActor>, losers: List<BattleActor>) {}
open fun lose(winners: List<BattleActor>, otherLosers: List<BattleActor>) {}
}
@@ -16,7 +16,7 @@ import com.cobblemon.mod.common.api.events.berry.BerryYieldCalculationEvent
import com.cobblemon.mod.common.api.mulch.MulchVariant
import com.cobblemon.mod.common.block.BerryBlock
import com.cobblemon.mod.common.block.entity.BerryBlockEntity
import com.cobblemon.mod.common.item.BerryItem
import com.cobblemon.mod.common.item.berry.BerryItem
import com.cobblemon.mod.common.pokemon.Nature
import com.cobblemon.mod.common.util.readBox
import com.cobblemon.mod.common.util.writeBox
@@ -45,9 +45,8 @@ import net.minecraft.world.biome.Biome
* @property identifier The [Identifier] of this berry.
* @property baseYield The [IntRange] possible for the berry tree before [bonusYield] is calculated.
* @property preferredBiomeTags The [TagKey]s of the berries preffered biomes. Determines spawning and yield
* @property growthTime The [IntRange] possible in minutes for how long the berry tree takes to grow.
* @property refreshRate The [IntRange] possible in minutes for how long the berry tree takes to regrow its berries once it has been harvested.
* @depreciated @property lifeCycles The [IntRange] possible for the berry to live for between harvests.
* @property growthTime The [IntRange] possible in minutes for how long the berry tree takes to grow frome age 0 to age 3
* @property refreshRate The [IntRange] possible in minutes for how long the berry tree takes to grow from age 3 to age 5
* @property favoriteMulches The types of mulches that benefit this berries yield
* @property growthFactors An array of [GrowthFactor]s that will affect this berry. The client is not aware of these.
* @property mutations A map of the partner berry as the key and the value as the resulting mutation with this berry.
@@ -60,6 +59,7 @@ import net.minecraft.world.biome.Biome
* @property flowerTexture The [Identifier] for the texture of the berry in flower form. This is resolved into a [ModelPart] on the client.
* @property fruitModelIdentifier The [Identifier] for the model of the berry in flower form. This is resolved into a [ModelPart] on the client.
* @property fruitTexture The [Identifier] for the texture of the berry in flower form.
* @property stageOnePositioning Transformation of the berry model for age 0
*
* @throws IllegalArgumentException if the any yield range argument is not a positive range.
*/
@@ -69,7 +69,6 @@ class Berry(
val preferredBiomeTags: List<TagKey<Biome>>,
val growthTime: IntRange,
val refreshRate: IntRange,
//val lifeCycles: IntRange,
val favoriteMulches: EnumSet<MulchVariant>,
val growthFactors: Collection<GrowthFactor>,
val spawnConditions: List<BerrySpawnCondition>,
@@ -88,7 +87,9 @@ class Berry(
@SerializedName("fruitModel")
val fruitModelIdentifier: Identifier,
val fruitTexture: Identifier,
val weight: Float
val stageOnePositioning: GrowthPoint,
val weight: Float,
val boneMealChance: Float
) {
@Transient
@@ -161,8 +162,9 @@ class Berry(
val bonus = this.bonusYield(world, state, pos)
var yield = base + bonus.first
val treeEntity = world.getBlockEntity(pos) as BerryBlockEntity
if (BerryBlock.getMulch(state) == MulchVariant.RICH) {
yield = min(yield + 1, maxYield())
if (BerryBlock.getMulch(treeEntity) == MulchVariant.RICH) {
//I hope the upper bound isnt exclusive, especially when there's a method called nextBetweenExclusive
yield += world.random.nextBetween(1, 3)
treeEntity.decrementMulchDuration(world, pos, state)
}
val event = BerryYieldCalculationEvent(this, world, state, pos, placer, yield, bonus.second)
@@ -279,6 +281,13 @@ class Berry(
buffer.writeIdentifier(this.flowerTexture)
buffer.writeIdentifier(this.fruitModelIdentifier)
buffer.writeIdentifier(this.fruitTexture)
buffer.writeDouble(stageOnePositioning.position.x)
buffer.writeDouble(stageOnePositioning.position.y)
buffer.writeDouble(stageOnePositioning.position.z)
buffer.writeDouble(stageOnePositioning.rotation.x)
buffer.writeDouble(stageOnePositioning.rotation.y)
buffer.writeDouble(stageOnePositioning.rotation.z)
buffer.writeFloat(boneMealChance)
}
/**
@@ -292,7 +301,8 @@ class Berry(
private fun bonusYield(world: World, state: BlockState, pos: BlockPos): Pair<Int, Collection<GrowthFactor>> {
var bonus = 0
val passed = arrayListOf<GrowthFactor>()
val mulchVariant = BerryBlock.getMulch(state)
val treeEntity = world.getBlockEntity(pos) as? BerryBlockEntity ?: return 0 to passed
val mulchVariant = BerryBlock.getMulch(treeEntity)
val hasBiomeMulch = mulchVariant in favoriteMulches
this.growthFactors.forEach { factor ->
if (factor.isValid(world, state, pos)) {
@@ -339,7 +349,9 @@ class Berry(
val flowerTexture = buffer.readIdentifier()
val fruitModelIdentifier = buffer.readIdentifier()
val fruitTexture = buffer.readIdentifier()
return Berry(identifier, baseYield, emptyList(), growthTime, refreshRate, favMulchs, emptySet(), emptyList(), growthPoints, randomizedGrowthPoints, mutations, sproutShapeBoxes, matureShapeBoxes, flavors, tintIndexes, flowerModelIdentifier, flowerTexture, fruitModelIdentifier, fruitTexture, 0F)
val stageOneYPos = GrowthPoint(Vec3d(buffer.readDouble(), buffer.readDouble(), buffer.readDouble()), Vec3d(buffer.readDouble(), buffer.readDouble(), buffer.readDouble()))
val boneMealChance = buffer.readFloat()
return Berry(identifier, baseYield, emptyList(), growthTime, refreshRate, favMulchs, emptySet(), emptyList(), growthPoints, randomizedGrowthPoints, mutations, sproutShapeBoxes, matureShapeBoxes, flavors, tintIndexes, flowerModelIdentifier, flowerTexture, fruitModelIdentifier, fruitTexture, stageOneYPos, 0F, boneMealChance)
}
}
@@ -27,13 +27,10 @@ object DialogueManager {
val activeDialogues = mutableMapOf<UUID, ActiveDialogue>()
fun startDialogue(playerEntity: ServerPlayerEntity, dialogue: Dialogue) {
startDialogue(ActiveDialogue(playerEntity, dialogue))
}
fun startDialogue(activeDialogue: ActiveDialogue) {
activeDialogues[activeDialogue.playerEntity.uuid] = activeDialogue
val packet = DialogueOpenedPacket(activeDialogue, true)
activeDialogue.playerEntity.sendPacket(packet)
val activeDialogue = ActiveDialogue(playerEntity, dialogue)
activeDialogues[playerEntity.uuid] = activeDialogue
val packet = DialogueOpenedPacket(activeDialogue, includeFaces = true)
playerEntity.sendPacket(packet)
}
fun stopDialogue(playerEntity: ServerPlayerEntity) {
@@ -12,7 +12,6 @@ import com.google.gson.JsonDeserializationContext
import com.google.gson.JsonDeserializer
import com.google.gson.JsonElement
import com.google.gson.JsonObject
import com.google.gson.JsonPrimitive
import com.google.gson.JsonSerializationContext
import com.google.gson.JsonSerializer
import java.lang.reflect.Type
@@ -29,10 +28,6 @@ object EntityDimensionsAdapter : JsonSerializer<EntityDimensions>, JsonDeseriali
const val WIDTH = "width"
const val HEIGHT = "height"
val templates = mutableMapOf(
"player" to { EntityDimensions(0.6F, 1.8F, false) }
)
override fun serialize(dimensions: EntityDimensions, type: Type, ctx: JsonSerializationContext): JsonElement {
val json = JsonObject()
json.addProperty(WIDTH, dimensions.width)
@@ -41,9 +36,6 @@ object EntityDimensionsAdapter : JsonSerializer<EntityDimensions>, JsonDeseriali
}
override fun deserialize(json: JsonElement, type: Type, ctx: JsonDeserializationContext): EntityDimensions {
if (json is JsonPrimitive) {
return templates[json.asString]?.invoke() ?: throw IllegalStateException("Dimensions provided by template name $json but no such template is set.")
}
json as JsonObject
return EntityDimensions(json.get(WIDTH).asFloat, json.get(HEIGHT).asFloat, false)
}
@@ -8,7 +8,6 @@
package com.cobblemon.mod.common.api.entity
import com.bedrockk.molang.runtime.struct.QueryStruct
import net.minecraft.entity.Entity
import net.minecraft.entity.data.TrackedData
@@ -19,5 +18,4 @@ interface EntitySideDelegate<T : Entity> {
fun initialize(entity: T) {}
fun tick(entity: T) {}
fun onTrackedDataSet(data: TrackedData<*>) {}
fun addToStruct(struct: QueryStruct) {}
}
@@ -1,19 +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.entity
import com.cobblemon.mod.common.entity.npc.NPCEntity
/**
* A delegate for some actions that can be different for an NPC on client versus server.
*
* @author Hiroku
* @since August 25th, 2023
*/
interface NPCSideDelegate : EntitySideDelegate<NPCEntity>
@@ -1,25 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.entity
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import java.util.concurrent.CompletableFuture
/**
* Interface for custom entities that can send out and recall Pokémon. They get notified
* when either of those actions are occurring.
*
* @author Hiroku
* @since August 25th, 2023
*
*/
interface PokemonSender {
fun sendingOut(): CompletableFuture<Unit>
fun recalling(pokemonEntity: PokemonEntity): CompletableFuture<Unit>
}
@@ -78,6 +78,8 @@ object CobblemonEvents {
val POKE_BALL_CAPTURE_CALCULATED = EventObservable<PokeBallCaptureCalculatedEvent>()
@JvmField
val POKEMON_CAPTURED = EventObservable<PokemonCapturedEvent>()
@JvmField
val FOSSIL_REVIVED = EventObservable<FossilRevivedEvent>()
// @JvmField
// val EGG_HATCH = EventObservable<HatchEggEvent>()
@JvmField
@@ -6,17 +6,12 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.npc.configuration
package com.cobblemon.mod.common.api.events.pokemon
import com.cobblemon.mod.common.pokemon.Pokemon
import net.minecraft.server.network.ServerPlayerEntity
/**
* A type of interaction handler for when a player right clicks the NPC.
*
* @author Hiroku
* @since August 19th, 2023
*/
interface NPCInteractConfiguration {
val type: String
fun interact(player: ServerPlayerEntity): Boolean
}
data class FossilRevivedEvent (
val pokemon: Pokemon,
val player: ServerPlayerEntity?
)
@@ -8,23 +8,12 @@
package com.cobblemon.mod.common.api.events.pokemon
import com.bedrockk.molang.runtime.value.MoValue
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMoLangValue
import com.cobblemon.mod.common.entity.pokeball.EmptyPokeBallEntity
import com.cobblemon.mod.common.pokemon.Pokemon
import com.cobblemon.mod.common.util.itemRegistry
import net.minecraft.registry.RegistryKeys
import net.minecraft.server.network.ServerPlayerEntity
data class PokemonCapturedEvent (
val pokemon: Pokemon,
val player: ServerPlayerEntity,
val pokeBallEntity: EmptyPokeBallEntity
) {
val context = mapOf<String, MoValue>(
"pokemon" to pokemon.struct,
"player" to player.asMoLangValue(),
"poke_ball" to pokeBallEntity.struct,
"item" to player.world.itemRegistry.getEntry(pokeBallEntity.pokeBall.item).asMoLangValue(RegistryKeys.ITEM)
)
}
)
@@ -1,84 +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.fishing
import com.cobblemon.mod.common.util.cobblemonResource
import net.minecraft.util.Identifier
import net.minecraft.nbt.NbtCompound
import net.minecraft.nbt.NbtList
import net.minecraft.nbt.NbtString
data class FishingBait(
val item: Identifier,
val effects: List<Effect>,
) {
data class Effect(
val type: Identifier,
val subcategory: Identifier?,
val chance: Double = 0.0,
val value: Double = 0.0
) {
fun toNbt(): NbtCompound {
val nbt = NbtCompound()
nbt.putString("Type", type.toString())
subcategory?.let { nbt.putString("Subcategory", it.toString()) }
nbt.putDouble("Chance", chance)
nbt.putDouble("Value", value)
return nbt
}
companion object {
fun fromNbt(nbt: NbtCompound): Effect {
val type = Identifier(nbt.getString("Type"))
val subcategory = if (nbt.contains("Subcategory")) Identifier(nbt.getString("Subcategory")) else null
val chance = nbt.getDouble("Chance")
val value = nbt.getDouble("Value")
return Effect(type, subcategory, chance, value)
}
}
}
fun toNbt(): NbtCompound {
val nbt = NbtCompound()
nbt.putString("Item", item.toString())
val effectsList = NbtList()
effects.forEach { effectsList.add(it.toNbt()) }
nbt.put("Effects", effectsList)
return nbt
}
companion object {
fun fromNbt(nbt: NbtCompound): FishingBait {
val item = Identifier(nbt.getString("Item"))
val effectsList = nbt.getList("Effects", 10) // 10 is the type for NbtCompound
val effects = mutableListOf<Effect>()
for (i in 0 until effectsList.size) {
effects.add(Effect.fromNbt(effectsList.getCompound(i)))
}
return FishingBait(item, effects)
}
}
object Effects {
val NATURE = cobblemonResource("nature")
val IV = cobblemonResource("iv")
val EV = cobblemonResource("ev")
val BITE_TIME = cobblemonResource("bite_time")
val GENDER_CHANCE = cobblemonResource("gender_chance")
val LEVEL_RAISE = cobblemonResource("level_raise")
val TERA = cobblemonResource("tera")
val SHINY_REROLL = cobblemonResource("shiny_reroll")
val HIDDEN_ABILITY_CHANCE = cobblemonResource("ha_chance")
val POKEMON_CHANCE = cobblemonResource("pokemon_chance")
val FRIENDSHIP = cobblemonResource("friendship")
val INERT = cobblemonResource("inert")
}
}
@@ -1,105 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.fishing
import com.cobblemon.mod.common.api.data.JsonDataRegistry
import com.cobblemon.mod.common.api.reactive.SimpleObservable
import com.cobblemon.mod.common.net.messages.client.fishing.FishingBaitRegistrySyncPacket
import com.cobblemon.mod.common.util.adapters.IdentifierAdapter
import com.cobblemon.mod.common.util.cobblemonResource
import com.google.gson.Gson
import com.google.gson.GsonBuilder
import com.google.gson.reflect.TypeToken
import net.minecraft.item.ItemStack
import net.minecraft.registry.Registries
import net.minecraft.resource.ResourceType
import net.minecraft.server.network.ServerPlayerEntity
import net.minecraft.util.Identifier
object FishingBaits : JsonDataRegistry<FishingBait>{
override val id = cobblemonResource("fishing_baits")
override val type = ResourceType.SERVER_DATA
override val observable = SimpleObservable<FishingBaits>()
override val typeToken: TypeToken<FishingBait> = TypeToken.get(FishingBait::class.java)
override val resourcePath = "fishing_baits"
override val gson: Gson = GsonBuilder()
.registerTypeAdapter(Identifier::class.java, IdentifierAdapter)
.setPrettyPrinting()
.create()
private val itemMap = mutableMapOf<Identifier, FishingBait>()
override fun sync(player: ServerPlayerEntity) {
FishingBaitRegistrySyncPacket(this.itemMap.values.toList()).sendToPlayer(player)
}
override fun reload(data: Map<Identifier, FishingBait>) {
itemMap.clear()
data.forEach { id, bait ->
itemMap[bait.item] = bait
}
}
fun getFromItemStack(stack: ItemStack): FishingBait? {
return itemMap[Registries.ITEM.getId(stack.item)]
}
fun isFishingBait(stack: ItemStack) = itemMap.containsKey(Registries.ITEM.getId(stack.item))
//
//
// fun getBaitSubcategory(item: ItemStack): String? {
// val itemId = Registries.ITEM.getId(item.item)
// if (itemId in itemMap.keys) {
// return itemMap[itemId]?.subcategory
// }
// val tag = tagMap.keys.firstOrNull { it.fits(item.item, Registries.ITEM) }
// if (tag != null) {
// return tagMap[tag]?.subcategory
// }
// return null
// }
//
// fun getBaitSuccessChance(item: ItemStack): Double? {
// val itemId = Registries.ITEM.getId(item.item)
// if (itemId in itemMap.keys) {
// return itemMap[itemId]?.chance
// }
// val tag = tagMap.keys.firstOrNull { it.fits(item.item, Registries.ITEM) }
// if (tag != null) {
// return tagMap[tag]?.chance
// }
// return null
// }
//
// fun getBaitEffectValue(item: ItemStack): Double? {
// val itemId = Registries.ITEM.getId(item.item)
// if (itemId in itemMap.keys) {
// return itemMap[itemId]?.value
// }
// val tag = tagMap.keys.firstOrNull { it.fits(item.item, Registries.ITEM) }
// if (tag != null) {
// return tagMap[tag]?.value
// }
// return null
// }
//
//
// fun getBaitNote(item: ItemStack): String? {
// val itemId = Registries.ITEM.getId(item.item)
// if (itemId in itemMap.keys) {
// return itemMap[itemId]?.note
// }
// val tag = tagMap.keys.firstOrNull { it.fits(item.item, Registries.ITEM) }
// if (tag != null) {
// return tagMap[tag]?.note
// }
// return null
// }
}
@@ -1,48 +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.fishing
import com.cobblemon.mod.common.api.pokeball.PokeBalls
import com.cobblemon.mod.common.pokeball.PokeBall
import net.minecraft.network.PacketByteBuf
import net.minecraft.util.Identifier
/**
* Base poke rod object
* It is intended that there is one poke rod object initialized for a given poke rod type.
*
* @property name the poke rod registry name
* @property pokeBallId The [Identifier] of the pokeball that is used as the bobber for this rod
* @property lineColor list of [RGB] values that apply to the fishing line of the Pokérod
*/
data class PokeRod(
val pokeBallId: Identifier,
//Hex string of color
val lineColor: String,
var name: Identifier?
) {
internal fun encode(buffer: PacketByteBuf) {
buffer.writeIdentifier(name)
buffer.writeIdentifier(pokeBallId)
buffer.writeString(lineColor)
}
companion object {
internal fun decode(buffer: PacketByteBuf): PokeRod {
val name = buffer.readIdentifier()
val pokeBallId = buffer.readIdentifier()
val lineColor = buffer.readString()
return PokeRod(pokeBallId, lineColor, name)
}
}
fun getPokeBall(): PokeBall? {
return PokeBalls.getPokeBall(pokeBallId)
}
}
@@ -1,62 +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.fishing
import com.cobblemon.mod.common.api.data.JsonDataRegistry
import com.cobblemon.mod.common.api.reactive.SimpleObservable
import com.cobblemon.mod.common.net.messages.client.data.PokeRodRegistrySyncPacket
import com.cobblemon.mod.common.util.adapters.IdentifierAdapter
import com.cobblemon.mod.common.util.cobblemonResource
import com.google.gson.Gson
import com.google.gson.GsonBuilder
import com.google.gson.reflect.TypeToken
import net.minecraft.resource.ResourceType
import net.minecraft.server.network.ServerPlayerEntity
import net.minecraft.util.Identifier
/**
* The data registry for [PokeRod]s.
* All the pokerod fields are guaranteed to exist
*/
object PokeRods : JsonDataRegistry<PokeRod> {
override val id = cobblemonResource("pokerods")
override val type = ResourceType.SERVER_DATA
override val observable = SimpleObservable<PokeRods>()
// ToDo once datapack pokerod is implemented add required adapters here
override val gson: Gson = GsonBuilder()
.disableHtmlEscaping()
.registerTypeAdapter(Identifier::class.java, IdentifierAdapter)
.setPrettyPrinting()
.create()
override val typeToken: TypeToken<PokeRod> = TypeToken.get(PokeRod::class.java)
override val resourcePath = "pokerods"
private val rods = mutableMapOf<Identifier, PokeRod>()
override fun reload(data: Map<Identifier, PokeRod>) {
data.forEach {
it.value.name = it.key
rods[it.key] = it.value
}
this.observable.emit(this)
}
override fun sync(player: ServerPlayerEntity) {
PokeRodRegistrySyncPacket(rods.values).sendToPlayer(player)
}
/**
* Gets a Pokerod from registry name.
* @return the pokerod object if found otherwise null.
*/
fun getPokeRod(name : Identifier): PokeRod? = rods[name]
}
@@ -10,11 +10,12 @@ package com.cobblemon.mod.common.api.gui
import com.cobblemon.mod.common.api.text.font
import com.cobblemon.mod.common.client.gui.battle.BattleOverlay.Companion.PORTRAIT_DIAMETER
import com.cobblemon.mod.common.client.render.models.blockbench.PoseableEntityModel
import com.cobblemon.mod.common.client.render.models.blockbench.PoseableEntityState
import com.cobblemon.mod.common.client.render.models.blockbench.repository.PokemonModelRepository
import com.cobblemon.mod.common.client.render.models.blockbench.repository.RenderContext
import com.cobblemon.mod.common.client.render.models.blockbench.repository.VaryingModelRepository
import com.cobblemon.mod.common.entity.PoseType
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import com.cobblemon.mod.common.pokemon.Species
import com.mojang.blaze3d.platform.GlStateManager
import com.mojang.blaze3d.systems.RenderSystem
import net.minecraft.client.MinecraftClient
@@ -28,17 +29,14 @@ import net.minecraft.client.render.Tessellator
import net.minecraft.client.render.VertexFormat
import net.minecraft.client.render.VertexFormats
import net.minecraft.client.util.math.MatrixStack
import net.minecraft.entity.Entity
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.RotationAxis
import org.joml.Matrix4f
import org.joml.Quaternionf
import org.joml.Vector3f
@JvmOverloads
fun blitk(
matrixStack: MatrixStack,
texture: Identifier? = null,
@@ -102,7 +100,6 @@ fun drawRectangle(
BufferRenderer.drawWithGlobalProgram(bufferbuilder.end())
}
@JvmOverloads
fun drawCenteredText(
context: DrawContext,
font: Identifier? = null,
@@ -117,7 +114,6 @@ fun drawCenteredText(
context.drawText(textRenderer, comp, x.toInt() - textRenderer.getWidth(comp) / 2, y.toInt(), colour, shadow)
}
@JvmOverloads
fun drawText(
context: DrawContext,
font: Identifier? = null,
@@ -149,7 +145,6 @@ fun drawText(
return isHovered
}
@JvmOverloads
fun drawText(
context: DrawContext,
text: OrderedText,
@@ -168,7 +163,6 @@ fun drawText(
context.drawText(textRenderer, text, tweakedX.toInt(), y.toInt(), colour, shadow)
}
@JvmOverloads
fun drawString(
context: DrawContext,
text: String,
@@ -187,30 +181,22 @@ fun drawString(
context.drawText(textRenderer, comp, x.toInt(), y.toInt(), colour, shadow)
}
@JvmOverloads
fun <T : Entity, M : PoseableEntityModel<T>> drawPoseablePortrait(
identifier: Identifier,
fun drawPortraitPokemon(
species: Species,
aspects: Set<String>,
matrixStack: MatrixStack,
scale: Float = 13F,
contextScale: Float = 1F,
reversed: Boolean = false,
state: PoseableEntityState<T>? = null,
repository: VaryingModelRepository<T, M>,
partialTicks: Float,
limbSwing: Float = 0F,
limbSwingAmount: Float = 0F,
ageInTicks: Float = 0F,
headYaw: Float = 0F,
headPitch: Float = 0F
state: PoseableEntityState<PokemonEntity>? = null,
partialTicks: Float
) {
val model = repository.getPoser(identifier, aspects)
val texture = repository.getTexture(identifier, aspects, state?.animationSeconds ?: 0F)
val model = PokemonModelRepository.getPoser(species.resourceIdentifier, aspects)
val texture = PokemonModelRepository.getTexture(species.resourceIdentifier, aspects, state?.animationSeconds ?: 0F)
val context = RenderContext()
repository.getTextureNoSubstitute(identifier, aspects, 0f).let { context.put(RenderContext.TEXTURE, it) }
context.put(RenderContext.SCALE, contextScale)
context.put(RenderContext.SPECIES, identifier)
PokemonModelRepository.getTextureNoSubstitute(species.resourceIdentifier, aspects, 0f).let { it -> context.put(RenderContext.TEXTURE, it) }
context.put(RenderContext.SCALE, species.getForm(aspects).baseScale)
context.put(RenderContext.SPECIES, species.resourceIdentifier)
context.put(RenderContext.ASPECTS, aspects)
val renderType = model.getLayer(texture)
@@ -226,7 +212,7 @@ fun <T : Entity, M : PoseableEntityModel<T>> drawPoseablePortrait(
model.getPose(PoseType.PORTRAIT)?.let { state.setPose(it.poseName) }
state.timeEnteredPose = 0F
state.updatePartialTicks(partialTicks)
model.setupAnimStateful(null, state, limbSwing, limbSwingAmount, ageInTicks, headYaw, headPitch)
model.setupAnimStateful(null, state, 0F, 0F, 0F, 0F, 0F)
originalPose?.let { state.setPose(it) }
}
@@ -248,7 +234,7 @@ fun <T : Entity, M : PoseableEntityModel<T>> drawPoseablePortrait(
val buffer = immediate.getBuffer(renderType)
val packedLight = LightmapTextureManager.pack(11, 7)
model.withLayerContext(immediate, state, repository.getLayers(identifier, aspects)) {
model.withLayerContext(immediate, state, PokemonModelRepository.getLayers(species.resourceIdentifier, aspects)) {
model.render(context, matrixStack, buffer, packedLight, OverlayTexture.DEFAULT_UV, 1F, 1F, 1F, 1F)
immediate.draw()
}
@@ -256,58 +242,5 @@ fun <T : Entity, M : PoseableEntityModel<T>> drawPoseablePortrait(
matrixStack.pop()
model.setDefault()
DiffuseLighting.enableGuiDepthLighting()
}
fun <E : Entity, M : PoseableEntityModel<E>> drawProfile(
repository: VaryingModelRepository<E, M>,
resourceIdentifier: Identifier,
aspects: Set<String>,
matrixStack: MatrixStack,
state: PoseableEntityState<E>,
partialTicks: Float,
scale: Float = 20F
) {
val model = repository.getPoser(resourceIdentifier, aspects)
val texture = repository.getTexture(resourceIdentifier, aspects, state.animationSeconds)
val context = RenderContext()
repository.getTextureNoSubstitute(resourceIdentifier, aspects, 0f).let { context.put(RenderContext.TEXTURE, it) }
context.put(RenderContext.SCALE, 1F)
context.put(RenderContext.SPECIES, resourceIdentifier)
context.put(RenderContext.ASPECTS, aspects)
val renderType = model.getLayer(texture)
RenderSystem.applyModelViewMatrix()
matrixStack.scale(scale, scale, -scale)
model.getPose(PoseType.PROFILE)?.let { state.setPose(it.poseName) }
state.timeEnteredPose = 0F
state.updatePartialTicks(partialTicks)
model.setupAnimStateful(null, state, 0F, 0F, 0F, 0F, 0F)
matrixStack.translate(model.profileTranslation.x, model.profileTranslation.y, model.profileTranslation.z - 4.0)
matrixStack.scale(model.profileScale, model.profileScale, 1 / model.profileScale)
// matrixStack.multiply(rotation)
val quaternion1 = RotationAxis.POSITIVE_Y.rotationDegrees(-32F * if (false) -1F else 1F)
val quaternion2 = RotationAxis.POSITIVE_X.rotationDegrees(5F)
matrixStack.multiply(quaternion1)
matrixStack.multiply(quaternion2)
DiffuseLighting.method_34742()
val entityRenderDispatcher = MinecraftClient.getInstance().entityRenderDispatcher
entityRenderDispatcher.setRenderShadows(true)
val bufferSource = MinecraftClient.getInstance().bufferBuilders.entityVertexConsumers
val buffer = bufferSource.getBuffer(renderType)
val light1 = Vector3f(-1F, 1F, 1.0F)
val light2 = Vector3f(1.3F, -1F, 1.0F)
RenderSystem.setShaderLights(light1, light2)
val packedLight = LightmapTextureManager.pack(11, 7)
model.withLayerContext(bufferSource, state, repository.getLayers(resourceIdentifier, aspects)) {
model.render(context, matrixStack, buffer, packedLight, OverlayTexture.DEFAULT_UV, 1F, 1F, 1F, 1F)
bufferSource.draw()
}
model.setDefault()
entityRenderDispatcher.setRenderShadows(true)
DiffuseLighting.enableGuiDepthLighting()
}
@@ -19,10 +19,8 @@ import com.bedrockk.molang.runtime.value.MoValue
* @since October 22nd, 2023
*/
interface ExpressionLike {
override fun toString(): String
/** Produces a [MoValue] for a [MoLangRuntime] to supply an environment. */
fun resolve(runtime: MoLangRuntime, context: Map<String, MoValue> = emptyMap()): MoValue
fun getString(): String = toString()
fun resolve(runtime: MoLangRuntime): MoValue
fun resolveDouble(runtime: MoLangRuntime) = resolve(runtime).asDouble()
fun resolveFloat(runtime: MoLangRuntime) = resolveDouble(runtime).toFloat()
@@ -30,5 +28,4 @@ interface ExpressionLike {
fun resolveInt(runtime: MoLangRuntime) = resolveDouble(runtime).toInt()
fun resolveBoolean(runtime: MoLangRuntime) = resolveDouble(runtime) == 1.0
fun resolveObject(runtime: MoLangRuntime) = resolve(runtime) as ObjectValue<*>
}
@@ -10,8 +10,6 @@ package com.cobblemon.mod.common.api.molang
import com.bedrockk.molang.Expression
import com.bedrockk.molang.runtime.MoLangRuntime
import com.bedrockk.molang.runtime.value.MoValue
import com.cobblemon.mod.common.util.getString
import com.cobblemon.mod.common.util.resolve
/**
@@ -21,6 +19,5 @@ import com.cobblemon.mod.common.util.resolve
* @since October 22nd, 2023
*/
class ListExpression(val exprs: List<Expression>): ExpressionLike {
override fun toString() = exprs.joinToString("\n") { it.getString().let { if (it.endsWith(";")) it else "$it;" } }
override fun resolve(runtime: MoLangRuntime, context: Map<String, MoValue>) = exprs.resolve(runtime, context)
override fun resolve(runtime: MoLangRuntime) = exprs.resolve(runtime)
}
@@ -18,27 +18,12 @@ import com.bedrockk.molang.runtime.value.DoubleValue
import com.bedrockk.molang.runtime.value.MoValue
import com.bedrockk.molang.runtime.value.StringValue
import com.cobblemon.mod.common.Cobblemon
import com.cobblemon.mod.common.api.battles.model.PokemonBattle
import com.cobblemon.mod.common.api.dialogue.PlayerDialogueFaceProvider
import com.cobblemon.mod.common.api.dialogue.ReferenceDialogueFaceProvider
import com.cobblemon.mod.common.api.scripting.CobblemonScripts
import com.cobblemon.mod.common.api.text.text
import com.cobblemon.mod.common.client.render.models.blockbench.wavefunction.WaveFunction
import com.cobblemon.mod.common.client.render.models.blockbench.wavefunction.WaveFunctions
import com.cobblemon.mod.common.entity.npc.NPCEntity
import com.cobblemon.mod.common.net.messages.client.effect.RunPosableMoLangPacket
import com.cobblemon.mod.common.util.asIdentifierDefaultingNamespace
import com.cobblemon.mod.common.util.getBooleanOrNull
import com.cobblemon.mod.common.util.getDoubleOrNull
import com.cobblemon.mod.common.util.isInt
import com.cobblemon.mod.common.util.itemRegistry
import com.cobblemon.mod.common.util.server
import com.cobblemon.mod.common.util.worldRegistry
import com.mojang.datafixers.util.Either
import net.minecraft.block.Block
import net.minecraft.entity.LivingEntity
import net.minecraft.entity.damage.DamageSource
import net.minecraft.entity.damage.DamageTypes
import net.minecraft.entity.player.PlayerEntity
import net.minecraft.nbt.NbtCompound
import net.minecraft.nbt.NbtDouble
import net.minecraft.nbt.NbtElement
@@ -50,7 +35,6 @@ import net.minecraft.registry.RegistryKeys
import net.minecraft.registry.entry.RegistryEntry
import net.minecraft.registry.tag.TagKey
import net.minecraft.server.network.ServerPlayerEntity
import net.minecraft.server.world.ServerWorld
import net.minecraft.util.Identifier
import net.minecraft.world.World
import net.minecraft.world.biome.Biome
@@ -64,11 +48,6 @@ import net.minecraft.world.dimension.DimensionType
*/
object MoLangFunctions {
val generalFunctions = hashMapOf<String, java.util.function.Function<MoParams, Any>>(
"run_command" to java.util.function.Function { params ->
val command = params.getString(0)
val server = server() ?: return@Function DoubleValue(0)
server.commandManager.executeWithPrefix(server.commandSource, command)
},
"is_int" to java.util.function.Function { params -> DoubleValue(params.get<MoValue>(0).asString().isInt()) },
"is_number" to java.util.function.Function { params -> DoubleValue(params.get<MoValue>(0).asString().toDoubleOrNull() != null) },
"to_number" to java.util.function.Function { params -> DoubleValue(params.get<MoValue>(0).asString().toDoubleOrNull() ?: 0.0) },
@@ -96,134 +75,23 @@ object MoLangFunctions {
val array = ArrayStruct(hashMapOf())
values.forEachIndexed { index, moValue -> array.setDirectly("$index", moValue) }
return@Function array
},
"run_script" to java.util.function.Function { params ->
val runtime = MoLangRuntime()
runtime.environment.structs.putAll(params.environment.structs)
val script = params.getString(0).asIdentifierDefaultingNamespace()
CobblemonScripts.run(script, runtime) ?: DoubleValue(0)
}
)
val biomeFunctions = hashMapOf<String, java.util.function.Function<MoParams, Any>>()
val worldFunctions = hashMapOf<String, java.util.function.Function<MoParams, Any>>()
val dimensionTypeFunctions = hashMapOf<String, java.util.function.Function<MoParams, Any>>()
val blockFunctions = hashMapOf<String, java.util.function.Function<MoParams, Any>>()
val playerFunctions = mutableListOf<(PlayerEntity) -> HashMap<String, java.util.function.Function<MoParams, Any>>>(
val playerFunctions = mutableListOf<(ServerPlayerEntity) -> HashMap<String, java.util.function.Function<MoParams, Any>>>(
{ player ->
val map = hashMapOf<String, java.util.function.Function<MoParams, Any>>()
map.put("username") { _ -> StringValue(player.gameProfile.name) }
map.put("uuid") { _ -> StringValue(player.gameProfile.id.toString()) }
map.put("data") { _ -> return@put if (player is ServerPlayerEntity) Cobblemon.molangData.load(player.uuid) else DoubleValue(0) }
map.put("save_data") { _ -> if (player is ServerPlayerEntity) Cobblemon.molangData.save(player.uuid) else DoubleValue(0) }
map.put("main_held_item") { _ -> player.world.itemRegistry.getEntry(player.mainHandStack.item).asMoLangValue(RegistryKeys.ITEM) }
map.put("off_held_item") { _ -> player.world.itemRegistry.getEntry(player.offHandStack.item).asMoLangValue(RegistryKeys.ITEM) }
map.put("face") { _ -> ObjectValue(PlayerDialogueFaceProvider(player.uuid)) }
map.put("swing_hand") { _ -> player.swingHand(player.activeHand) }
map.put("food_level") { _ -> DoubleValue(player.hungerManager.foodLevel) }
map.put("saturation_level") { _ -> DoubleValue(player.hungerManager.saturationLevel) }
map.put("tell") { params ->
val message = params.getString(0).text()
val overlay = params.getBooleanOrNull(1) ?: false
player.sendMessage(message, overlay)
}
map.put("teleport") { params ->
val x = params.getDouble(0)
val y = params.getDouble(1)
val z = params.getDouble(2)
player.teleport(x, y, z)
}
map.put("heal") { params ->
val amount = params.getDoubleOrNull(0) ?: player.maxHealth
player.heal(amount.toFloat())
}
map.put("environment") {
val environment = MoLangEnvironment()
environment.structs["query"] = player.asMoLangValue()
environment
}
map.put("run_command") { params ->
val command = params.getString(0)
val server = server() ?: return@put DoubleValue(0)
server.commandManager.executeWithPrefix(player.commandSource, command)
}
map
}
)
val entityFunctions = mutableListOf<(LivingEntity) -> HashMap<String, java.util.function.Function<MoParams, Any>>>(
{ entity ->
val map = hashMapOf<String, java.util.function.Function<MoParams, Any>>()
map.put("damage") { params ->
val amount = params.getDouble(0)
val source = DamageSource(entity.world.registryManager.get(RegistryKeys.DAMAGE_TYPE).getEntry(DamageTypes.GENERIC).get())
entity.damage(source, amount.toFloat())
}
map.put("is_sneaking") { _ -> DoubleValue(entity.isSneaking) }
map.put("is_sprinting") { _ -> DoubleValue(entity.isSprinting) }
map.put("is_flying") { _ -> DoubleValue(entity.isFallFlying) }
map.put("is_in_water") { _ -> DoubleValue(entity.isSubmergedInWater) }
map.put("is_touching_water_or_rain") { _ -> DoubleValue(entity.isWet) }
map.put("is_touching_water") { _ -> DoubleValue(entity.isTouchingWater) }
map.put("is_in_lava") { _ -> DoubleValue(entity.isInLava) }
map.put("is_on_fire") { _ -> DoubleValue(entity.isOnFire) }
map.put("is_invisible") { _ -> DoubleValue(entity.isInvisible) }
map.put("is_sleeping") { _ -> DoubleValue(entity.isSleeping) }
map.put("is_riding") { _ -> DoubleValue(entity.hasVehicle()) }
map.put("health") { _ -> DoubleValue(entity.health) }
map.put("max_health") { _ -> DoubleValue(entity.maxHealth) }
map.put("name") { _ -> StringValue(entity.entityName) }
map.put("yaw") { _ -> DoubleValue(entity.yaw.toDouble()) }
map.put("pitch") { _ -> DoubleValue(entity.pitch.toDouble()) }
map.put("x") { _ -> DoubleValue(entity.x) }
map.put("y") { _ -> DoubleValue(entity.y) }
map.put("z") { _ -> DoubleValue(entity.z) }
map.put("velocity_x") { _ -> DoubleValue(entity.velocity.x) }
map.put("velocity_y") { _ -> DoubleValue(entity.velocity.y) }
map.put("velocity_z") { _ -> DoubleValue(entity.velocity.z) }
map.put("horizontal_velocity") { _ -> DoubleValue(entity.velocity.horizontalLength()) }
map.put("is_on_ground") { _ -> DoubleValue(entity.isOnGround) }
map.put("world") { _ -> entity.world.worldRegistry.getEntry(entity.world).asWorldMoLangValue() }
map.put("biome") { _ -> entity.world.getBiome(entity.blockPos).asBiomeMoLangValue() }
map
}
)
val npcFunctions = mutableListOf<(NPCEntity) -> HashMap<String, java.util.function.Function<MoParams, Any>>>(
{ npc ->
val map = hashMapOf<String, java.util.function.Function<MoParams, Any>>()
map.put("class") { StringValue(npc.npc.resourceIdentifier.toString()) }
map.put("name") { StringValue(npc.name.string) }
map.put("face") { ObjectValue(ReferenceDialogueFaceProvider(npc.id)) }
map.put("in_battle") { DoubleValue(npc.isInBattle()) }
map.put("run_script_on_client") { params ->
val world = npc.world
if (world is ServerWorld) {
val script = params.getString(0)
val packet = RunPosableMoLangPacket(npc.id, setOf("q.run_script('$script')"))
packet.sendToPlayers(world.players.toList())
}
Unit
}
map.put("run_script") { params ->
val script = params.getString(0).asIdentifierDefaultingNamespace()
val environment = params.environment
val runtime = MoLangRuntime()
runtime.environment.structs.putAll(environment.structs)
CobblemonScripts.run(script, runtime) ?: DoubleValue(0)
}
map.put("environment") { _ -> npc.runtime.environment }
map
}
)
val battleFunctions = mutableListOf<(PokemonBattle) -> HashMap<String, java.util.function.Function<MoParams, Any>>>(
{ battle ->
val map = hashMapOf<String, java.util.function.Function<MoParams, Any>>()
map.put("battle_id") { StringValue(battle.battleId.toString()) }
map.put("is_pvn") { DoubleValue(battle.isPvN) }
map.put("is_pvp") { DoubleValue(battle.isPvP) }
map.put("is_pvw") { DoubleValue(battle.isPvW) }
map.put("battle_type") { StringValue(battle.format.toString()) }
map.put("environment") { battle.runtime.environment }
map
hashMapOf(
"username" to java.util.function.Function { _ -> StringValue(player.gameProfile.name) },
"uuid" to java.util.function.Function { _ -> StringValue(player.gameProfile.id.toString()) },
"data" to java.util.function.Function { _ -> return@Function Cobblemon.molangData.load(player.uuid) },
"save_data" to java.util.function.Function { _ -> Cobblemon.molangData.save(player.uuid) },
"main_held_item" to java.util.function.Function { _ -> player.world.itemRegistry.getEntry(player.mainHandStack.item).asMoLangValue(RegistryKeys.ITEM) },
"off_held_item" to java.util.function.Function { _ -> player.world.itemRegistry.getEntry(player.offHandStack.item).asMoLangValue(RegistryKeys.ITEM) },
"face" to java.util.function.Function { _ -> ObjectValue(PlayerDialogueFaceProvider(player.uuid)) }
)
}
)
@@ -231,35 +99,15 @@ object MoLangFunctions {
fun RegistryEntry<World>.asWorldMoLangValue() = asMoLangValue(RegistryKeys.WORLD).addFunctions(worldFunctions)
fun RegistryEntry<Block>.asBlockMoLangValue() = asMoLangValue(RegistryKeys.BLOCK).addFunctions(blockFunctions)
fun RegistryEntry<DimensionType>.asDimensionTypeMoLangValue() = asMoLangValue(RegistryKeys.DIMENSION_TYPE).addFunctions(dimensionTypeFunctions)
fun PlayerEntity.asMoLangValue(): ObjectValue<PlayerEntity> {
fun ServerPlayerEntity.asMoLangValue(): ObjectValue<ServerPlayerEntity> {
val value = ObjectValue(
obj = this,
stringify = { it.entityName }
)
value.addFunctions(entityFunctions.flatMap { it(this).entries.map { it.key to it.value } }.toMap())
value.addFunctions(playerFunctions.flatMap { it(this).entries.map { it.key to it.value } }.toMap())
return value
}
fun NPCEntity.asMoLangValue(): ObjectValue<NPCEntity> {
val value = ObjectValue(
obj = this,
stringify = { it.name.string }
)
value.addFunctions(entityFunctions.flatMap { it(this).entries.map { it.key to it.value } }.toMap())
value.addFunctions(npcFunctions.flatMap { it(this).entries.map { it.key to it.value } }.toMap())
return value
}
fun PokemonBattle.asMoLangValue(): ObjectValue<PokemonBattle> {
val value = ObjectValue(
obj = this,
stringify = { it.battleId.toString() }
)
value.addFunctions(battleFunctions.flatMap { it(this).entries.map { it.key to it.value } }.toMap())
return value
}
fun <T> RegistryEntry<T>.asMoLangValue(key: RegistryKey<Registry<T>>): ObjectValue<RegistryEntry<T>> {
val value = ObjectValue(
obj = this,
@@ -286,6 +134,11 @@ object MoLangFunctions {
return this
}
fun <T : QueryStruct> T.addFunction(name: String, function: java.util.function.Function<MoParams, Any>): T {
this.functions[name] = function
return this
}
fun MoLangEnvironment.getQueryStruct(name: String = "query") = structs.getOrPut(name) { QueryStruct(hashMapOf()) } as QueryStruct
fun MoLangRuntime.setup(): MoLangRuntime {
@@ -340,6 +193,4 @@ object MoLangFunctions {
else -> null
} ?: throw IllegalArgumentException("Invalid NBT element type: ${nbt.type}")
}
}
fun Either<Identifier, ExpressionLike>.runScript(runtime: MoLangRuntime) = map({ CobblemonScripts.run(it, runtime) }, { it.resolve(runtime) })
}
@@ -10,8 +10,6 @@ package com.cobblemon.mod.common.api.molang
import com.bedrockk.molang.Expression
import com.bedrockk.molang.runtime.MoLangRuntime
import com.bedrockk.molang.runtime.value.MoValue
import com.cobblemon.mod.common.util.getString
import com.cobblemon.mod.common.util.resolve
/**
@@ -22,6 +20,5 @@ import com.cobblemon.mod.common.util.resolve
* @since October 22nd, 2023
*/
class SingleExpression(val expr: Expression) : ExpressionLike {
override fun toString() = expr.getString()
override fun resolve(runtime: MoLangRuntime, context: Map<String, MoValue>) = runtime.resolve(expr, context)
override fun resolve(runtime: MoLangRuntime) = runtime.resolve(expr)
}
@@ -12,6 +12,7 @@ import com.bedrockk.molang.runtime.struct.MoStruct
import com.bedrockk.molang.runtime.struct.QueryStruct
import com.bedrockk.molang.runtime.value.DoubleValue
import com.bedrockk.molang.runtime.value.StringValue
import com.cobblemon.mod.common.api.molang.MoLangFunctions.addFunction
import com.cobblemon.mod.common.api.moves.animations.ActionEffectTimeline
import com.cobblemon.mod.common.api.moves.categories.DamageCategories
import com.cobblemon.mod.common.api.moves.categories.DamageCategory
@@ -10,12 +10,8 @@ package com.cobblemon.mod.common.api.moves.animations
import com.bedrockk.molang.Expression
import com.bedrockk.molang.runtime.MoLangRuntime
import com.bedrockk.molang.runtime.struct.VariableStruct
import com.cobblemon.mod.common.api.molang.ExpressionLike
import com.cobblemon.mod.common.api.moves.animations.keyframes.ActionEffectKeyframe
import com.cobblemon.mod.common.api.scheduling.ScheduledTask
import com.cobblemon.mod.common.util.asExpressionLike
import com.cobblemon.mod.common.util.asExpressions
import com.cobblemon.mod.common.util.asExpression
import com.cobblemon.mod.common.util.resolveBoolean
import java.util.concurrent.CompletableFuture
import net.minecraft.entity.Entity
@@ -31,7 +27,7 @@ import net.minecraft.entity.Entity
*/
class ActionEffectTimeline(
val timeline: List<ActionEffectKeyframe> = mutableListOf(),
val condition: ExpressionLike = "true".asExpressionLike()
val condition: Expression = "true".asExpression()
) {
companion object {
val NONE = ActionEffectTimeline()
@@ -45,6 +41,9 @@ class ActionEffectTimeline(
// .toList copy because I'm paranoid about iterators being trying to share between identical effects playing
chainKeyframes(context, timeline.toList().iterator(), finalFuture)
finalFuture
}.exceptionallyCompose {
it.printStackTrace()
CompletableFuture.completedFuture(Unit)
}
}
@@ -57,6 +56,7 @@ class ActionEffectTimeline(
keyframe.play(context)
.thenRun { context.currentKeyframes.remove(keyframe) }
.thenApply { chainKeyframes(context, iterator, finalFuture) }
.exceptionally { finalFuture.completeExceptionally(it) }
}
}
}
@@ -49,6 +49,6 @@ class AnimationActionEffectKeyframe : ConditionalActionEffectKeyframe(), EntityC
players.forEach { it.sendPacket(pkt) }
}
return delayedFuture(seconds = delay.resolveFloat(context.runtime))
return delayedFuture(seconds = delay.resolveFloat(context.runtime), serverThread = true)
}
}
@@ -46,6 +46,6 @@ class EntityMoLangActionEffectKeyframe : ConditionalActionEffectKeyframe(), Enti
players.forEach { it.sendPacket(pkt) }
}
return delayedFuture(seconds = delay.resolveFloat(context.runtime))
return delayedFuture(seconds = delay.resolveFloat(context.runtime), serverThread = true)
}
}
@@ -8,7 +8,6 @@
package com.cobblemon.mod.common.api.moves.animations.keyframes
import com.cobblemon.mod.common.CobblemonNetwork.sendPacket
import com.cobblemon.mod.common.api.molang.ExpressionLike
import com.cobblemon.mod.common.api.moves.animations.ActionEffectContext
import com.cobblemon.mod.common.api.moves.animations.EntityProvider
@@ -40,7 +39,7 @@ class EntityParticlesActionEffectKeyframe : ConditionalActionEffectKeyframe(), E
.flatMap { prov -> prov.entities.filter { test(context, it, isUser = prov is UsersProvider) } }
val effectIdentifier = try {
effect?.asExpressionLike()?.resolveString(context.runtime)
effect?.asExpressionLike()?.resolveString(context.runtime)?.takeIf { it != "0.0" } ?: effect
} catch (e: Exception) {
effect
}?.asIdentifierDefaultingNamespace() ?: return skip()
@@ -51,6 +50,6 @@ class EntityParticlesActionEffectKeyframe : ConditionalActionEffectKeyframe(), E
packet.sendToPlayers(players)
}
return delayedFuture(seconds = delay.resolveFloat(context.runtime))
return delayedFuture(seconds = delay.resolveFloat(context.runtime), serverThread = true)
}
}
@@ -45,6 +45,6 @@ class EntitySoundActionEffectKeyframe : ConditionalActionEffectKeyframe(), Entit
entity.playSound(soundEvent, 1f, 1f)
}
return delayedFuture(seconds = delay.resolveFloat(context.runtime))
return delayedFuture(seconds = delay.resolveFloat(context.runtime), serverThread = true)
}
}
@@ -25,6 +25,6 @@ class MoLangActionEffectKeyframe : ActionEffectKeyframe {
val delay: ExpressionLike = "0".asExpressionLike()
override fun play(context: ActionEffectContext): CompletableFuture<Unit> {
expressions.resolve(context.runtime)
return delayedFuture(seconds = delay.resolveFloat(context.runtime))
return delayedFuture(seconds = delay.resolveFloat(context.runtime), serverThread = true)
}
}
@@ -14,5 +14,5 @@ import com.cobblemon.mod.common.util.asExpressionLike
class PauseActionEffectKeyframe : ConditionalActionEffectKeyframe() {
val pause = "1".asExpressionLike()
override fun playWhenTrue(context: ActionEffectContext) = delayedFuture(seconds = pause.resolveFloat(context.runtime))
override fun playWhenTrue(context: ActionEffectContext) = delayedFuture(seconds = pause.resolveFloat(context.runtime), serverThread = true)
}
@@ -24,7 +24,7 @@ class RemoveHoldsActionEffectKeyframe : ActionEffectKeyframe {
val delay = 0F
val holds = mutableSetOf<String>()
override fun play(context: ActionEffectContext): CompletableFuture<Unit> {
return delayedFuture(seconds = delay).thenApply {
return delayedFuture(seconds = delay, serverThread = true).thenApply {
if (holds.isEmpty()) {
context.holds.clear()
} else {
@@ -56,7 +56,7 @@ class ReturnToPositionActionEffectKeyframe : ActionEffectKeyframe {
}
)
after(seconds = timeout.resolveFloat(context.runtime)) {
after(seconds = timeout.resolveFloat(context.runtime), serverThread = true) {
if (!future.isDone && !timedOut) {
timedOut = true
timeoutEffect.run(context).thenApply { future.complete(Unit) }
@@ -8,24 +8,30 @@
package com.cobblemon.mod.common.api.mulch
import com.cobblemon.mod.common.BakingOverride
import com.cobblemon.mod.common.client.CobblemonBakingOverrides
import net.minecraft.util.StringIdentifiable
/**
* Represents the different types of Mulch implemented in the mod.
*
*/
enum class MulchVariant(val duration: Int = -1) : StringIdentifiable {
COARSE,
GROWTH(3),
HUMID,
LOAMY,
PEAT,
RICH(3),
SANDY,
SURPRISE(3),
NONE;
enum class MulchVariant(val model: BakingOverride?, val duration: Int = -1) : StringIdentifiable {
COARSE(CobblemonBakingOverrides.COARSE_MULCH),
GROWTH(CobblemonBakingOverrides.GROWTH_MULCH, 5),
HUMID(CobblemonBakingOverrides.HUMID_MULCH),
LOAMY(CobblemonBakingOverrides.LOAMY_MULCH),
PEAT(CobblemonBakingOverrides.PEAT_MULCH),
RICH(CobblemonBakingOverrides.RICH_MULCH, 5),
SANDY(CobblemonBakingOverrides.SANDY_MULCH),
SURPRISE(CobblemonBakingOverrides.SURPRISE_MULCH, 3),
NONE(null);
override fun asString(): String {
return name.lowercase()
}
companion object {
const val GROWTH_TIME_MULTIPLIER = 0.5
}
}
@@ -60,13 +60,14 @@ abstract class MultiblockBlock(properties: Settings) : BlockWithEntity(propertie
}
override fun onBreak(world: World, pos: BlockPos, state: BlockState, player: PlayerEntity?) {
super.onBreak(world, pos, state, player)
if (!world.isClient) {
val entity = world.getBlockEntity(pos)
if (entity is MultiblockEntity && entity.multiblockStructure != null) {
entity.multiblockStructure!!.onBreak(world, pos, state, player)
}
entity?.markRemoved()
}
super.onBreak(world, pos, state, player)
}
override fun createBlockEntity(pos: BlockPos, state: BlockState): BlockEntity? {
@@ -78,6 +79,7 @@ abstract class MultiblockBlock(properties: Settings) : BlockWithEntity(propertie
return BlockRenderType.MODEL
}
//This is done so a block picked with NBT doesnt absolutely DESTROY multiblocks
override fun getPickStack(world: BlockView, pos: BlockPos, state: BlockState): ItemStack {
val blockEntity = world.getBlockEntity(pos) as? MultiblockEntity ?: return ItemStack.EMPTY
return if (blockEntity.multiblockStructure == null) super.getPickStack(world, pos, state) else ItemStack.EMPTY
@@ -29,4 +29,5 @@ object StringSetDataSerializer : TrackedDataHandler<Set<String>> {
}
override fun copy(set: Set<String>) = set.toSet()
}
@@ -1,33 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.net.serializers
import com.cobblemon.mod.common.net.IntSize
import com.cobblemon.mod.common.util.readSizedInt
import com.cobblemon.mod.common.util.writeSizedInt
import java.util.UUID
import net.minecraft.entity.data.TrackedDataHandler
import net.minecraft.network.PacketByteBuf
object UUIDSetDataSerializer : TrackedDataHandler<Set<UUID>> {
override fun write(buffer: PacketByteBuf, set: Set<UUID>) {
buffer.writeSizedInt(IntSize.U_BYTE, set.size)
set.forEach(buffer::writeUuid)
}
override fun read(buffer: PacketByteBuf): Set<UUID> {
val set = mutableSetOf<UUID>()
repeat(times = buffer.readSizedInt(IntSize.U_BYTE)) {
set.add(buffer.readUuid())
}
return set
}
override fun copy(set: Set<UUID>) = set.toSet()
}
@@ -1,82 +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.npc
import com.bedrockk.molang.runtime.value.DoubleValue
import com.bedrockk.molang.runtime.value.MoValue
import com.bedrockk.molang.runtime.value.StringValue
import com.cobblemon.mod.common.api.molang.ExpressionLike
import com.cobblemon.mod.common.api.npc.configuration.NPCBattleConfiguration
import com.cobblemon.mod.common.net.IntSize
import com.cobblemon.mod.common.util.asExpressionLike
import com.cobblemon.mod.common.util.lang
import com.cobblemon.mod.common.util.readMapK
import com.cobblemon.mod.common.util.writeMapK
import com.mojang.datafixers.util.Either
import net.minecraft.entity.EntityDimensions
import net.minecraft.network.PacketByteBuf
import net.minecraft.text.MutableText
import net.minecraft.util.Identifier
/**
* A class of NPC. This can contain a lot of preset information about the NPC's behaviour. Consider this the Pokémon
* species but for NPCs.
*
* @author Hiroku
* @since August 14th, 2023
*/
class NPCClass {
@Transient
lateinit var resourceIdentifier: Identifier
var names = mutableListOf<MutableText>(lang("npc.name.default"))
var hitbox = EntityDimensions(0.6F, 1.8F, false)
var battleConfiguration = NPCBattleConfiguration()
var interaction: Either<Identifier, ExpressionLike>? = null
var variables = mutableMapOf<String, MoValue>()
fun encode(buffer: PacketByteBuf) {
buffer.writeCollection(names, PacketByteBuf::writeText)
buffer.writeFloat(this.hitbox.width)
buffer.writeFloat(this.hitbox.height)
buffer.writeBoolean(this.hitbox.fixed)
battleConfiguration.encode(buffer)
buffer.writeNullable(interaction) { _, value ->
buffer.writeBoolean(value.map({ true }, { false }))
buffer.writeString(value.map({ it.toString() }, { it.toString() }))
}
buffer.writeMapK(size = IntSize.U_BYTE, map = variables) { (key, value) ->
buffer.writeString(key)
buffer.writeString(value.asString())
}
}
fun decode(buffer: PacketByteBuf) {
names = buffer.readList { buffer.readText().copy() }.toMutableList()
hitbox = EntityDimensions(buffer.readFloat(), buffer.readFloat(), buffer.readBoolean())
battleConfiguration = NPCBattleConfiguration()
battleConfiguration.decode(buffer)
interaction = buffer.readNullable {
if (buffer.readBoolean()) {
Either.left(Identifier(buffer.readString()))
} else {
Either.right(buffer.readString().asExpressionLike())
}
}
buffer.readMapK(size = IntSize.U_BYTE, map = variables) {
val key = buffer.readString()
val value = buffer.readString()
if (value.toDoubleOrNull() != null) {
return@readMapK key to DoubleValue(value.toDouble())
} else {
return@readMapK key to StringValue(value)
}
}
}
}
@@ -1,128 +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.npc
import com.bedrockk.molang.runtime.value.MoValue
import com.cobblemon.mod.common.Cobblemon
import com.cobblemon.mod.common.api.ai.SleepDepth
import com.cobblemon.mod.common.api.conditional.RegistryLikeCondition
import com.cobblemon.mod.common.api.data.JsonDataRegistry
import com.cobblemon.mod.common.api.drop.DropEntry
import com.cobblemon.mod.common.api.drop.ItemDropMethod
import com.cobblemon.mod.common.api.entity.EntityDimensionsAdapter
import com.cobblemon.mod.common.api.molang.ExpressionLike
import com.cobblemon.mod.common.api.pokemon.PokemonProperties
import com.cobblemon.mod.common.api.reactive.SimpleObservable
import com.cobblemon.mod.common.api.spawning.TimeRange
import com.cobblemon.mod.common.net.messages.client.data.NPCRegistrySyncPacket
import com.cobblemon.mod.common.pokemon.Species
import com.cobblemon.mod.common.util.adapters.*
import com.cobblemon.mod.common.util.cobblemonResource
import com.google.gson.Gson
import com.google.gson.GsonBuilder
import com.google.gson.reflect.TypeToken
import com.mojang.datafixers.util.Either
import net.minecraft.block.Block
import net.minecraft.entity.EntityDimensions
import net.minecraft.item.Item
import net.minecraft.nbt.NbtCompound
import net.minecraft.resource.ResourceType
import net.minecraft.server.network.ServerPlayerEntity
import net.minecraft.util.Identifier
import net.minecraft.util.math.Box
import net.minecraft.world.biome.Biome
object NPCClasses : JsonDataRegistry<NPCClass> {
override val id = cobblemonResource("npc")
override val type = ResourceType.SERVER_DATA
override val gson: Gson = GsonBuilder()
.registerTypeAdapter(EntityDimensions::class.java, EntityDimensionsAdapter)
.registerTypeAdapter(Box::class.java, BoxAdapter)
.registerTypeAdapter(IntRange::class.java, IntRangeAdapter)
.registerTypeAdapter(PokemonProperties::class.java, pokemonPropertiesShortAdapter)
.registerTypeAdapter(Identifier::class.java, IdentifierAdapter)
.registerTypeAdapter(TimeRange::class.java, IntRangesAdapter(TimeRange.timeRanges) { TimeRange(*it) })
.registerTypeAdapter(ItemDropMethod::class.java, ItemDropMethod.adapter)
.registerTypeAdapter(SleepDepth::class.java, SleepDepth.adapter)
.registerTypeAdapter(DropEntry::class.java, DropEntryAdapter)
.registerTypeAdapter(NbtCompound::class.java, NbtCompoundAdapter)
.registerTypeAdapter(NPCPartyProvider::class.java, NPCPartyProviderAdapter)
.registerTypeAdapter(MoValue::class.java, MoValueAdapter)
.registerTypeAdapter(TypeToken.getParameterized(RegistryLikeCondition::class.java, Biome::class.java).type, BiomeLikeConditionAdapter)
.registerTypeAdapter(TypeToken.getParameterized(RegistryLikeCondition::class.java, Block::class.java).type, BlockLikeConditionAdapter)
.registerTypeAdapter(TypeToken.getParameterized(RegistryLikeCondition::class.java, Item::class.java).type, ItemLikeConditionAdapter)
.registerTypeAdapter(TypeToken.getParameterized(Either::class.java, Identifier::class.java, ExpressionLike::class.java).type, NPCScriptAdapter)
.disableHtmlEscaping()
.enableComplexMapKeySerialization()
.create()
override val typeToken: TypeToken<NPCClass> = TypeToken.get(NPCClass::class.java)
override val resourcePath = "npcs"
override val observable = SimpleObservable<NPCClasses>()
private val npcClassesByIdentifier = hashMapOf<Identifier, NPCClass>()
val classes: Collection<NPCClass>
get() = this.npcClassesByIdentifier.values
init {
// NPC additions would be useful
// SpeciesAdditions.observable.subscribe {
// this.species.forEach(Species::initialize)
// this.species.forEach(Species::resolveEvolutionMoves)
// }
}
/**
* Finds an NPC class by the pathname of their [Identifier].
* This method exists for the convenience of finding Cobble default NPC classes.
* This uses [getByIdentifier] using the [Cobblemon.MODID] as the namespace and the [name] as the path.
*
* @param name The path of the NPC class asset.
* @return The [NPCClass] if existing.
*/
fun getByName(name: String) = this.getByIdentifier(cobblemonResource(name))
/**
* Finds an [NPCClass] by its unique [Identifier].
*
* @param identifier The unique [NPCClass.resourceIdentifier] of the [NPCClass].
* @return The [NPCClass] if existing.
*/
fun getByIdentifier(identifier: Identifier) = this.npcClassesByIdentifier[identifier]
/**
* Counts the currently loaded NPC classes.
*
* @return The loaded NPC class amount.
*/
fun count() = this.npcClassesByIdentifier.size
/**
* Picks a random [NPCClass].
*
* @throws [NoSuchElementException] if there are no NPC classes loaded.
*
* @return A randomly selected [Species].
*/
fun random(): NPCClass = this.npcClassesByIdentifier.values.random()
override fun reload(data: Map<Identifier, NPCClass>) {
this.npcClassesByIdentifier.clear()
data.forEach { (identifier, species) ->
species.resourceIdentifier = identifier
this.npcClassesByIdentifier[identifier] = species
}
}
override fun sync(player: ServerPlayerEntity) {
NPCRegistrySyncPacket(npcClassesByIdentifier.values.toList()).sendToPlayer(player)
}
}
@@ -1,30 +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.npc
import com.cobblemon.mod.common.api.npc.configuration.NPCBattleConfiguration
import com.cobblemon.mod.common.entity.npc.NPCEntity
/**
* An NPC configuration is like a snapshot of an NPC setup. It can be taken from an existing NPC and loaded onto
* others. Useful as a backup mechanism or as shorthand for copying an NPC's configuration without building an
* entire class for them.
*
* @author Hiroku
* @since August 16th, 2023
*/
class NPCConfiguration {
var battle: NPCBattleConfiguration? = null
fun applyTo(npc: NPCEntity) {
}
fun loadFrom(npc: NPCEntity) {
}
}
@@ -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.api.npc
import com.cobblemon.mod.common.api.npc.partyproviders.SimplePartyProvider
import com.cobblemon.mod.common.api.storage.party.PartyStore
import com.cobblemon.mod.common.entity.npc.NPCEntity
import com.google.gson.JsonElement
import net.minecraft.nbt.NbtCompound
import net.minecraft.network.PacketByteBuf
import net.minecraft.server.network.ServerPlayerEntity
/**
* A provider of a party for battling the NPC. Completely custom party providers will only display
* as text labels in any GUIs.
*
* @author Hiroku
* @since August 16th, 2023
*/
interface NPCPartyProvider {
companion object {
val types = mutableMapOf<String, (String) -> NPCPartyProvider>(
SimplePartyProvider.TYPE to { SimplePartyProvider() }
)
}
val type: String
fun provide(npc: NPCEntity, challengers: List<ServerPlayerEntity>): PartyStore
fun encode(buffer: PacketByteBuf)
fun decode(buffer: PacketByteBuf)
fun saveToNBT(nbt: NbtCompound)
fun loadFromNBT(nbt: NbtCompound)
fun loadFromJSON(json: JsonElement)
}
@@ -1,18 +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.npc
import net.minecraft.util.Identifier
class NPCPreset {
lateinit var id: Identifier
var aspects: Set<String>? = null
var party: NPCPartyProvider? = null
// var mergeMode = MergeMode.KEEP
}
@@ -1,70 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.npc.configuration
import com.cobblemon.mod.common.api.npc.NPCPartyProvider
import com.cobblemon.mod.common.util.DataKeys
import net.minecraft.nbt.NbtCompound
import net.minecraft.network.PacketByteBuf
class NPCBattleConfiguration {
var canChallenge = false
var party: NPCPartyProvider? = null
var simultaneousBattles = false
var healAfterwards = true
fun encode(buffer: PacketByteBuf) {
buffer.writeBoolean(canChallenge)
buffer.writeBoolean(simultaneousBattles)
buffer.writeBoolean(healAfterwards)
buffer.writeNullable(party) { _, provider ->
buffer.writeString(provider.type)
provider.encode(buffer)
}
}
fun decode(buffer: PacketByteBuf) {
canChallenge = buffer.readBoolean()
simultaneousBattles = buffer.readBoolean()
healAfterwards = buffer.readBoolean()
party = buffer.readNullable {
val type = buffer.readString()
val providerBuilder = NPCPartyProvider.types[type]
?: throw IllegalArgumentException("Failed to load NPC party provider of type: $type")
providerBuilder(type)
}
}
fun saveToNBT(nbt: NbtCompound) {
nbt.putBoolean(DataKeys.NPC_CAN_CHALLENGE, canChallenge)
nbt.putBoolean(DataKeys.NPC_SIMULTANEOUS_BATTLES, simultaneousBattles)
nbt.putBoolean(DataKeys.NPC_HEAL_AFTERWARDS, healAfterwards)
val party = party
if (party != null) {
val partyNBT = NbtCompound()
partyNBT.putString(DataKeys.NPC_PARTY_TYPE, party.type)
party.saveToNBT(partyNBT)
nbt.put(DataKeys.NPC_PARTY, partyNBT)
}
}
fun loadFromNBT(nbt: NbtCompound) {
canChallenge = nbt.getBoolean(DataKeys.NPC_CAN_CHALLENGE)
simultaneousBattles = nbt.getBoolean(DataKeys.NPC_SIMULTANEOUS_BATTLES)
healAfterwards = nbt.getBoolean(DataKeys.NPC_HEAL_AFTERWARDS)
val partyNBT = nbt.getCompound(DataKeys.NPC_PARTY)
if (!partyNBT.isEmpty) {
val type = partyNBT.getString(DataKeys.NPC_PARTY_TYPE)
val providerBuilder = NPCPartyProvider.types[type]
?: throw IllegalArgumentException("Failed to load NPC party provider of type: $type")
party = providerBuilder(type).also { it.loadFromNBT(partyNBT) }
}
}
}
@@ -1,32 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.npc.configuration
import net.minecraft.nbt.NbtCompound
import net.minecraft.network.PacketByteBuf
class NPCBehaviourConfiguration {
var canBeHurt = true
fun encode(buffer: PacketByteBuf) {
}
fun decode(buffer: PacketByteBuf) {
}
fun saveToNBT(nbt: NbtCompound) {
}
fun loadFromNBT(nbt: NbtCompound) {
}
}
@@ -1,77 +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.npc.partyproviders
import com.cobblemon.mod.common.api.npc.NPCPartyProvider
import com.cobblemon.mod.common.api.pokemon.PokemonProperties
import com.cobblemon.mod.common.api.storage.party.NPCPartyStore
import com.cobblemon.mod.common.api.storage.party.PartyStore
import com.cobblemon.mod.common.entity.npc.NPCEntity
import com.cobblemon.mod.common.net.IntSize
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.JsonElement
import com.google.gson.JsonObject
import net.minecraft.nbt.NbtCompound
import net.minecraft.network.PacketByteBuf
import net.minecraft.server.network.ServerPlayerEntity
class SimplePartyProvider : NPCPartyProvider {
companion object {
const val TYPE = "simple"
}
@Transient
override val type = TYPE
val pokemon = mutableListOf<PokemonProperties>()
override fun encode(buffer: PacketByteBuf) {
buffer.writeSizedInt(IntSize.U_BYTE, pokemon.size)
for (pokemon in this.pokemon) {
buffer.writeString(pokemon.originalString)
}
}
override fun decode(buffer: PacketByteBuf) {
repeat(times = buffer.readSizedInt(IntSize.U_BYTE)) {
pokemon.add(PokemonProperties.parse(buffer.readString()))
}
}
override fun saveToNBT(nbt: NbtCompound) {
for ((index, pokemon) in this.pokemon.withIndex()) {
nbt.putString(DataKeys.NPC_PARTY_POKEMON + index, pokemon.originalString)
}
}
override fun loadFromNBT(nbt: NbtCompound) {
var index = 0
while (nbt.contains(DataKeys.NPC_PARTY_POKEMON + index)) {
this.pokemon.add(PokemonProperties.parse(nbt.getString(DataKeys.POKEMON_PROPERTIES + index)))
index++
}
}
override fun loadFromJSON(json: JsonElement) {
json as JsonObject
if (json.has(DataKeys.NPC_PARTY_POKEMON.lowercase())) {
json.get(DataKeys.NPC_PARTY_POKEMON.lowercase()).asJsonArray.forEach { pokemon.add(PokemonProperties.parse(it.asString)) }
}
}
override fun provide(npc: NPCEntity, challengers: List<ServerPlayerEntity>): PartyStore {
return NPCPartyStore(npc).apply {
for (properties in pokemon) {
add(properties.create())
}
}
}
}
@@ -70,8 +70,6 @@ object CobblemonPermissions {
val CLEAR_PARTY = this.create("${COMMAND_PREFIX}clearparty", PermissionLevel.CHEAT_COMMANDS_AND_COMMAND_BLOCKS)
val CLEAR_PC = this.create("${COMMAND_PREFIX}clearpc", PermissionLevel.CHEAT_COMMANDS_AND_COMMAND_BLOCKS)
val NPC_EDIT = this.create("${COMMAND_PREFIX}npcedit", PermissionLevel.CHEAT_COMMANDS_AND_COMMAND_BLOCKS)
fun all(): Iterable<Permission> = this.permissions
private fun create(node: String, level: PermissionLevel): Permission {
@@ -168,7 +168,7 @@ object PokeBalls : JsonDataRegistry<PokeBall> {
createDefault("fast_ball", BaseStatModifier(Stats.SPEED, { it >= 100 }, 4F))
createDefault("level_ball", CatchRateModifiers.LEVEL)
// ToDo we will need fishing context here once fishing is implemented for a multiplier
createDefault("lure_ball", CatchRateModifiers.LURE)
createDefault("lure_ball", CatchRateModifiers.typeBoosting(2F, ElementalTypes.WATER))
createDefault("heavy_ball", CatchRateModifiers.WEIGHT_BASED)
createDefault("love_ball", CatchRateModifiers.LOVE)
createDefault("friend_ball", effects = listOf(CaptureEffects.friendshipSetter(150)))
@@ -11,7 +11,6 @@ package com.cobblemon.mod.common.api.pokeball.catching.modifiers
import com.cobblemon.mod.common.api.pokeball.PokeBalls
import com.cobblemon.mod.common.api.pokeball.catching.CatchRateModifier
import com.cobblemon.mod.common.api.pokemon.status.Status
import com.cobblemon.mod.common.api.spawning.fishing.FishingSpawnCause
import com.cobblemon.mod.common.api.tags.CobblemonBiomeTags
import com.cobblemon.mod.common.api.types.ElementalType
import com.cobblemon.mod.common.battles.BattleRegistry
@@ -122,18 +121,6 @@ object CatchRateModifiers {
1F
}
/**
* Used by [PokeBalls.LURE_BALL].
* Checks if the entity has an aspect for being spawned from fishing.
* If yes boosts the catch rate by *4
*/
val LURE = WorldStateModifier { _, entity ->
if (FishingSpawnCause.FISHED_ASPECT in entity.aspects)
4f
else
1F
}
/**
* Used by [PokeBalls.HEAVY_BALL].
* The base implementation of the heavy ball modifier mechanics.
@@ -59,9 +59,9 @@ open class PokemonProperties {
val props = PokemonProperties()
props.originalString = string
val keyPairs = string.splitMap(delimiter, assigner)
props.customProperties = CustomPokemonProperty.properties.flatMap { property ->
val matchedKeyPairs = keyPairs.filter { it.first.lowercase() in property.keys }
if (matchedKeyPairs.isEmpty()) {
props.customProperties = CustomPokemonProperty.properties.mapNotNull { property ->
val matchedKeyPair = keyPairs.find { it.first.lowercase() in property.keys }
if (matchedKeyPair == null) {
if (!property.needsKey) {
var savedProperty: CustomPokemonProperty? = null
val keyPair = keyPairs.find { keyPair ->
@@ -71,20 +71,13 @@ open class PokemonProperties {
if (keyPair != null) {
keyPairs.remove(keyPair)
}
return@flatMap savedProperty?.let { listOf(it) } ?: emptyList()
return@mapNotNull savedProperty
} else {
return@flatMap emptyList()
return@mapNotNull null
}
} else {
val properties = mutableListOf<CustomPokemonProperty>()
for ((customKey, customValue) in matchedKeyPairs) {
val property = property.fromString(customValue)
keyPairs.remove(customKey to customValue)
if (property != null) {
properties.add(property)
}
}
return@flatMap properties
keyPairs.remove(matchedKeyPair)
return@mapNotNull property.fromString(matchedKeyPair.second)
}
}.toMutableList()
props.gender = Gender.values().toList().parsePropertyOfCollection(keyPairs, listOf("gender"), labelsOptional = true) { it.name.lowercase() }
@@ -47,6 +47,10 @@ fun interface PokemonPropertyExtractor {
val NICKNAME = add { pokemon, properties -> properties.nickname = pokemon.nickname }
@JvmField
val STATUS = add { pokemon, properties -> properties.status = pokemon.status?.status?.showdownName }
@JvmField
val IVS = add { pokemon, properties -> properties.ivs = pokemon.ivs }
@JvmField
val EVS = add { pokemon, properties -> properties.evs = pokemon.evs }
@JvmField
val ILLUSION = mutableListOf(SPECIES, FORM, ASPECTS, GENDER, NICKNAME, SHINY)
@@ -96,7 +96,7 @@ object PokemonSpecies : JsonDataRegistry<Species> {
.registerTypeAdapter(TypeToken.getParameterized(RegistryLikeCondition::class.java, Item::class.java).type, ItemLikeConditionAdapter)
.registerTypeAdapter(TypeToken.getParameterized(RegistryLikeCondition::class.java, Structure::class.java).type, StructureLikeConditionAdapter)
.registerTypeAdapter(EggGroup::class.java, EggGroupAdapter)
.registerTypeAdapter(StatusEffect::class.java, RegistryElementAdapter<StatusEffect>(Registries::STATUS_EFFECT))
.registerTypeAdapter(StatusEffect::class.java, RegistryElementAdapter<StatusEffect> { Registries.STATUS_EFFECT })
.registerTypeAdapter(NbtItemPredicate::class.java, NbtItemPredicateAdapter)
.disableHtmlEscaping()
.enableComplexMapKeySerialization()
@@ -8,7 +8,11 @@
package com.cobblemon.mod.common.api.pokemon.evolution
import com.cobblemon.mod.common.Cobblemon.playerData
import com.cobblemon.mod.common.CobblemonItems
import com.cobblemon.mod.common.CobblemonSounds
import com.cobblemon.mod.common.advancement.CobblemonCriteria
import com.cobblemon.mod.common.advancement.criterion.EvolvePokemonContext
import com.cobblemon.mod.common.api.events.CobblemonEvents
import com.cobblemon.mod.common.api.events.pokemon.evolution.EvolutionCompleteEvent
import com.cobblemon.mod.common.api.events.pokemon.evolution.EvolutionTestedEvent
@@ -17,7 +21,9 @@ import com.cobblemon.mod.common.api.moves.MoveTemplate
import com.cobblemon.mod.common.api.pokemon.PokemonProperties
import com.cobblemon.mod.common.api.pokemon.evolution.requirement.EvolutionRequirement
import com.cobblemon.mod.common.api.scheduling.afterOnServer
import com.cobblemon.mod.common.api.tags.CobblemonItemTags
import com.cobblemon.mod.common.entity.generic.GenericBedrockEntity
import com.cobblemon.mod.common.item.PokeBallItem
import com.cobblemon.mod.common.pokemon.Pokemon
import com.cobblemon.mod.common.pokemon.activestate.ShoulderedState
import com.cobblemon.mod.common.pokemon.evolution.variants.ItemInteractionEvolution
@@ -25,6 +31,7 @@ import com.cobblemon.mod.common.pokemon.evolution.variants.LevelUpEvolution
import com.cobblemon.mod.common.pokemon.evolution.variants.TradeEvolution
import com.cobblemon.mod.common.util.cobblemonResource
import com.cobblemon.mod.common.util.lang
import com.cobblemon.mod.common.util.party
import net.minecraft.item.ItemStack
import net.minecraft.sound.SoundCategory
@@ -44,6 +51,11 @@ interface Evolution : EvolutionLike {
*/
val result: PokemonProperties
/**
* The shed result of this evolution.
*/
val shedder: PokemonProperties?
/**
* If this evolution allows the user to choose when to start it or not.
*/
@@ -95,6 +107,36 @@ interface Evolution : EvolutionLike {
return true
}
fun shed(pokemon: Pokemon): Boolean {
val innerShedder = shedder ?: return false
val owner = pokemon.getOwnerPlayer() ?: return false
// If the player has at least one Pokeball in their inventory.
var pokeballStack: ItemStack? = null
if (!owner.isCreative) {
for (i in 0 until owner.inventory.size()) {
val stackI = owner.inventory.getStack(i)
if (stackI.isIn(CobblemonItemTags.POKE_BALLS)) {
pokeballStack = stackI
}
}
if (pokeballStack == null) return false
}
// If the player has at least one empty spot in their party.
val emptySlot = owner.party().getFirstAvailablePosition() ?: return false
// Add shed Pokemon to player's party
val shedPokemon = pokemon.clone()
shedPokemon.removeHeldItem()
innerShedder.apply(shedPokemon)
shedPokemon.caughtBall = ((pokeballStack?.item ?: CobblemonItems.POKE_BALL) as PokeBallItem).pokeBall
pokemon.storeCoordinates.get()?.store?.add(shedPokemon)
CobblemonCriteria.EVOLVE_POKEMON.trigger(owner, EvolvePokemonContext(pokemon.preEvolution!!.species.resourceIdentifier, shedPokemon.species.resourceIdentifier, playerData.get(owner).advancementData.totalEvolvedCount))
// Consume one of the balls
pokeballStack?.decrement(1)
return true
}
/**
* Starts this evolution as soon as possible.
@@ -153,8 +195,9 @@ interface Evolution : EvolutionLike {
pokemon.getOwnerPlayer()?.sendMessage(lang("experience.learned_move", pokemon.getDisplayName(), move.displayName))
}
// we want to instantly tick for example you might only evolve your Bulbasaur at level 34 so Venusaur should be immediately available
pokemon.evolutions.filterIsInstance<PassiveEvolution>().forEach { evolution -> evolution.attemptEvolution(pokemon) }
pokemon.lockedEvolutions.filterIsInstance<PassiveEvolution>().forEach { evolution -> evolution.attemptEvolution(pokemon) }
pokemon.getOwnerPlayer()?.playSound(CobblemonSounds.EVOLVING, SoundCategory.NEUTRAL, 1F, 1F)
this.shed(pokemon)
CobblemonEvents.EVOLUTION_COMPLETE.post(EvolutionCompleteEvent(pokemon, this))
}
@@ -101,7 +101,7 @@ open class Learnset : ClientDataSynchronizer<Learnset> {
repeat(times = buffer.readSizedInt(IntSize.U_BYTE)) {
val level = buffer.readSizedInt(IntSize.U_SHORT)
val moves = mutableListOf<MoveTemplate>()
repeat(times = buffer.readSizedInt(IntSize.U_BYTE)) {
repeat(times = buffer.readSizedInt(IntSize.U_SHORT)) {
Moves.getByNumericalId(buffer.readInt())?.let(moves::add)
}
levelUpMoves[level] = moves
@@ -112,7 +112,7 @@ open class Learnset : ClientDataSynchronizer<Learnset> {
buffer.writeSizedInt(IntSize.U_BYTE, levelUpMoves.size)
for ((level, moves) in levelUpMoves) {
buffer.writeSizedInt(IntSize.U_SHORT, level)
buffer.writeSizedInt(IntSize.U_BYTE, moves.size)
buffer.writeSizedInt(IntSize.U_SHORT, moves.size)
for (move in moves) {
buffer.writeInt(move.num)
}
@@ -51,9 +51,8 @@ enum class Stats(override val identifier: Identifier, override val displayName:
/** Gets the [Stat] from the respective Showdown id. */
fun getStat(statKey: String) = when(statKey) {
"hp" -> HP
"atk" -> ATTACK
"def" -> DEFENCE
"atk", "Attack" -> ATTACK // Hyper Cutter states the full stat name "Attack"
"def", "Defense" -> DEFENCE // Big Pecks states the full stat name "Defense"
"spa" -> SPECIAL_ATTACK
"spd" -> SPECIAL_DEFENCE
"spe" -> SPEED
@@ -8,6 +8,9 @@
package com.cobblemon.mod.common.api.pokemon.status
import com.cobblemon.mod.common.api.moves.animations.ActionEffectTimeline
import com.cobblemon.mod.common.api.moves.animations.ActionEffects
import com.cobblemon.mod.common.util.asIdentifierDefaultingNamespace
import net.minecraft.util.Identifier
/**
@@ -20,4 +23,6 @@ open class Status(
val showdownName: String = "",
val applyMessage: String,
val removeMessage: String
)
) {
fun getActionEffect() = ActionEffects.actionEffects[name]
}
@@ -9,21 +9,29 @@
package com.cobblemon.mod.common.api.pokemon.status
import com.cobblemon.mod.common.pokemon.status.PersistentStatus
import com.cobblemon.mod.common.pokemon.status.statuses.BurnStatus
import com.cobblemon.mod.common.pokemon.status.statuses.FrozenStatus
import com.cobblemon.mod.common.pokemon.status.statuses.ParalysisStatus
import com.cobblemon.mod.common.pokemon.status.statuses.PoisonBadlyStatus
import com.cobblemon.mod.common.pokemon.status.statuses.PoisonStatus
import com.cobblemon.mod.common.pokemon.status.statuses.SleepStatus
import com.cobblemon.mod.common.pokemon.status.VolatileStatus
import com.cobblemon.mod.common.pokemon.status.statuses.persistent.BurnStatus
import com.cobblemon.mod.common.pokemon.status.statuses.persistent.FrozenStatus
import com.cobblemon.mod.common.pokemon.status.statuses.persistent.ParalysisStatus
import com.cobblemon.mod.common.pokemon.status.statuses.persistent.PoisonBadlyStatus
import com.cobblemon.mod.common.pokemon.status.statuses.persistent.PoisonStatus
import com.cobblemon.mod.common.pokemon.status.statuses.persistent.SleepStatus
import com.cobblemon.mod.common.pokemon.status.statuses.nonpersistent.ConfuseStatus
import com.cobblemon.mod.common.pokemon.status.statuses.nonpersistent.AttractStatus
import net.minecraft.util.Identifier
/**
* Main API point for Statuses
* Get or register Statuses
*
* NOTE: May seem weird to have so many things called volatile statuses but the package is called nonpersistent.
* Its because volatile is a reserved keyword in Java. Cant use it in a package name
*
* @author Deltric
*/
object Statuses {
private val persistentStatuses = mutableListOf<Status>()
private val volatileStatuses = mutableListOf<Status>()
private val allStatuses = mutableListOf<Status>()
val POISON = registerStatus(PoisonStatus())
@@ -32,13 +40,23 @@ object Statuses {
val SLEEP = registerStatus(SleepStatus())
val FROZEN = registerStatus(FrozenStatus())
val BURN = registerStatus(BurnStatus())
val ATTRACT = registerStatus(AttractStatus())
val CONFUSE = registerStatus(ConfuseStatus())
fun <T: Status> registerStatus(status: T) : T {
if (status is PersistentStatus) {
persistentStatuses.add(status)
}
else if (status is VolatileStatus) {
volatileStatuses.add(status)
}
allStatuses.add(status)
return status
}
fun getStatus(name: Identifier) = allStatuses.find { status -> status.name == name }
fun getStatus(showdownName: String) = allStatuses.find { it.showdownName == showdownName }
fun getPersistentStatuses() = allStatuses.filterIsInstance<PersistentStatus>()
fun getPersistentStatuses() = persistentStatuses
}
@@ -8,8 +8,6 @@
package com.cobblemon.mod.common.api.scheduling
import java.util.concurrent.CompletableFuture
/**
* An interface for which an implementation must provide a [SchedulingTracker] so that the standard scheduling
* functions can be executed.
@@ -54,13 +52,5 @@ interface Schedulable {
}
}
fun delayedFuture(seconds: Float): CompletableFuture<Unit> {
val future = CompletableFuture<Unit>()
after(seconds = seconds) {
future.complete(Unit)
}
return future
}
fun taskBuilder(): ScheduledTask.Builder = ScheduledTask.Builder().tracker(schedulingTracker)
}
@@ -9,7 +9,6 @@
package com.cobblemon.mod.common.api.scheduling
import java.util.concurrent.CompletableFuture
import com.cobblemon.mod.common.util.runOnServer
@Deprecated("Use afterOnServer or afterOnClient; ambiguous side is not good for your health")
@JvmOverloads
@@ -46,12 +45,4 @@ fun lerp(seconds: Float = 0F, serverThread: Boolean = false, action: (Float) ->
fun lerpOnServer(seconds: Float = 0F, action: (Float) -> Unit) = ServerTaskTracker.lerp(seconds = seconds, action = action)
@JvmOverloads
fun lerpOnClient(seconds: Float = 0F, action: (Float) -> Unit) = ClientTaskTracker.lerp(seconds = seconds, action = action)
fun taskBuilder() = ScheduledTask.Builder()
fun delayedFuture(seconds: Float): CompletableFuture<Unit> {
val future = CompletableFuture<Unit>()
afterOnServer(seconds = seconds) {
future.complete(Unit)
}
return future
}
fun taskBuilder() = ScheduledTask.Builder()
@@ -1,69 +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.scripting
import com.bedrockk.molang.runtime.MoLangRuntime
import com.bedrockk.molang.runtime.value.MoValue
import com.cobblemon.mod.common.Cobblemon
import com.cobblemon.mod.common.CobblemonNetwork.sendPacket
import com.cobblemon.mod.common.api.data.DataRegistry
import com.cobblemon.mod.common.api.molang.ExpressionLike
import com.cobblemon.mod.common.api.reactive.SimpleObservable
import com.cobblemon.mod.common.net.messages.client.data.ScriptRegistrySyncPacket
import com.cobblemon.mod.common.util.asExpressionLike
import com.cobblemon.mod.common.util.cobblemonResource
import com.cobblemon.mod.common.util.endsWith
import java.io.File
import java.util.concurrent.ExecutionException
import net.minecraft.resource.ResourceManager
import net.minecraft.resource.ResourceType
import net.minecraft.server.network.ServerPlayerEntity
import net.minecraft.util.Identifier
object CobblemonScripts : DataRegistry {
const val MOLANG_EXTENSION = ".molang"
override val id = cobblemonResource("molang")
override val type = ResourceType.SERVER_DATA
override val observable = SimpleObservable<CobblemonScripts>()
val clientScripts = mutableMapOf<Identifier, ExpressionLike>()
val scripts = mutableMapOf<Identifier, ExpressionLike>()
override fun reload(manager: ResourceManager) {
manager.findResources("molang") { path -> path.endsWith(MOLANG_EXTENSION) }.forEach { (identifier, resource) ->
resource.inputStream.use { stream ->
stream.bufferedReader().use { reader ->
val resolvedIdentifier = Identifier(identifier.namespace, File(identifier.path).nameWithoutExtension)
try {
val expression = reader.readText().asExpressionLike()
if (identifier.path.startsWith("molang/client/")) {
clientScripts[resolvedIdentifier] = expression
} else {
scripts[resolvedIdentifier] = expression
}
} catch (exception: Exception) {
throw ExecutionException("Error loading MoLang script: $identifier", exception)
}
}
}
}
Cobblemon.LOGGER.info("Loaded ${scripts.size} server scripts and ${clientScripts.size} client scripts")
observable.emit(this)
}
override fun sync(player: ServerPlayerEntity) {
player.sendPacket(ScriptRegistrySyncPacket(clientScripts.entries))
}
fun run(identifier: Identifier, runtime: MoLangRuntime): MoValue? {
return scripts[identifier]?.resolve(runtime)
}
}
@@ -79,15 +79,15 @@ class ParticleEvent(
particleEffect?.let { effect ->
val bedrockParticleEffect = BedrockParticleEffectRepository.getEffect(effect.effect) ?: return@let
val rootMatrix = when (effect.type) {
EventParticleEffect.EventParticleType.EMITTER -> MatrixWrapper().updatePosition(storm.matrixWrapper.getOrigin())
EventParticleEffect.EventParticleType.EMITTER_BOUND -> storm.matrixWrapper
EventParticleEffect.EventParticleType.EMITTER,// -> MatrixWrapper().updatePosition(storm.matrixWrapper.getOrigin())
EventParticleEffect.EventParticleType.EMITTER_BOUND,// -> storm.matrixWrapper
EventParticleEffect.EventParticleType.PARTICLE,
EventParticleEffect.EventParticleType.PARTICLE_WITH_VELOCITY -> (particle?.let { Vec3d(it.getX(), it.getY(), it.getZ()) } ?: Vec3d(storm.getX(), storm.getY(), storm.getZ())).let { MatrixWrapper().updatePosition(it) }
}
val sourceVelocity = when (effect.type) {
EventParticleEffect.EventParticleType.EMITTER -> storm.sourceVelocity().let { { it } }
EventParticleEffect.EventParticleType.EMITTER_BOUND -> storm.sourceVelocity
EventParticleEffect.EventParticleType.EMITTER,// -> storm.sourceVelocity().let { { it } }
EventParticleEffect.EventParticleType.EMITTER_BOUND,// -> storm.sourceVelocity
EventParticleEffect.EventParticleType.PARTICLE -> { { Vec3d.ZERO } }
EventParticleEffect.EventParticleType.PARTICLE_WITH_VELOCITY -> (particle?.let { Vec3d(it.getVelocityX(), it.getVelocityY(), it.getVelocityZ()) } ?: Vec3d.ZERO).let { { it } }
}
@@ -15,10 +15,12 @@ import com.bedrockk.molang.runtime.MoLangRuntime
import com.cobblemon.mod.common.api.codec.CodecMapped
import com.cobblemon.mod.common.api.data.ArbitrarilyMappedSerializableCompanion
import com.cobblemon.mod.common.client.particle.ParticleStorm
import com.cobblemon.mod.common.client.render.SnowstormParticle
import com.cobblemon.mod.common.util.codec.EXPRESSION_CODEC
import com.cobblemon.mod.common.util.getString
import com.cobblemon.mod.common.util.math.geometry.transformDirection
import com.cobblemon.mod.common.util.resolveDouble
import com.cobblemon.mod.common.util.resolveVec3d
import com.mojang.serialization.Codec
import com.mojang.serialization.DynamicOps
import com.mojang.serialization.codecs.PrimitiveCodec
@@ -35,20 +37,79 @@ interface ParticleMotion : CodecMapped {
init {
registerSubtype(ParticleMotionType.DYNAMIC, DynamicParticleMotion::class.java, DynamicParticleMotion.CODEC)
registerSubtype(ParticleMotionType.STATIC, StaticParticleMotion::class.java, StaticParticleMotion.CODEC)
registerSubtype(ParticleMotionType.PARAMETRIC, ParametricParticleMotion::class.java, ParametricParticleMotion.CODEC)
}
}
val type: ParticleMotionType
fun getInitialVelocity(runtime: MoLangRuntime, storm: ParticleStorm, particlePos: Vec3d, emitterPos: Vec3d): Vec3d
fun getAcceleration(runtime: MoLangRuntime, velocity: Vec3d): Vec3d
fun getVelocity(runtime: MoLangRuntime, particle: SnowstormParticle, velocity: Vec3d): Vec3d
fun getParticleDirection(runtime: MoLangRuntime, storm: ParticleStorm, velocity: Vec3d, minSpeed: Float): Vec3d
}
enum class ParticleMotionType {
DYNAMIC,
PARAMETRIC, // TODO figure out how that even works
PARAMETRIC,
STATIC
}
class ParametricParticleMotion(
var offset: Triple<Expression, Expression, Expression> = Triple(
NumberExpression(0.0),
NumberExpression(0.0),
NumberExpression(0.0)
),
var direction: Triple<Expression, Expression, Expression> = Triple(
NumberExpression(0.0),
NumberExpression(0.0),
NumberExpression(0.0)
)
) : ParticleMotion {
companion object {
val CODEC: Codec<ParametricParticleMotion> = RecordCodecBuilder.create { instance ->
instance.group(
PrimitiveCodec.STRING.fieldOf("type").forGetter { it.type.name },
EXPRESSION_CODEC.listOf().fieldOf("offset").forGetter { listOf(it.offset.first, it.offset.second, it.offset.third) },
EXPRESSION_CODEC.listOf().fieldOf("direction").forGetter { listOf(it.direction.first, it.direction.second, it.direction.third) }
).apply(instance) { _, offset, direction -> ParametricParticleMotion(Triple(offset[0], offset[1], offset[2]), Triple(direction[0], direction[1], direction[2])) }
}
}
override val type = ParticleMotionType.PARAMETRIC
override fun getInitialVelocity(runtime: MoLangRuntime, storm: ParticleStorm, particlePos: Vec3d, emitterPos: Vec3d) = Vec3d.ZERO
override fun getVelocity(runtime: MoLangRuntime, particle: SnowstormParticle, velocity: Vec3d): Vec3d {
val stormPosition = Vec3d(particle.storm.getX(), particle.storm.getY(), particle.storm.getZ())
val offset = runtime.resolveVec3d(this.offset)
val particlePosition = Vec3d(particle.getX(), particle.getY(), particle.getZ())
val desiredPosition = stormPosition.add(offset)
return desiredPosition.subtract(particlePosition)
}
override fun getParticleDirection(runtime: MoLangRuntime, storm: ParticleStorm, velocity: Vec3d, minSpeed: Float) = runtime.resolveVec3d(direction).normalize()
override fun <T> encode(ops: DynamicOps<T>) = CODEC.encodeStart(ops, this)
override fun readFromBuffer(buffer: PacketByteBuf) {
offset = Triple(
MoLang.createParser(buffer.readString()).parseExpression(),
MoLang.createParser(buffer.readString()).parseExpression(),
MoLang.createParser(buffer.readString()).parseExpression()
)
direction = Triple(
MoLang.createParser(buffer.readString()).parseExpression(),
MoLang.createParser(buffer.readString()).parseExpression(),
MoLang.createParser(buffer.readString()).parseExpression()
)
}
override fun writeToBuffer(buffer: PacketByteBuf) {
buffer.writeString(offset.first.getString())
buffer.writeString(offset.second.getString())
buffer.writeString(offset.third.getString())
buffer.writeString(direction.first.getString())
buffer.writeString(direction.second.getString())
buffer.writeString(direction.third.getString())
}
}
class DynamicParticleMotion(
var direction: ParticleMotionDirection = InwardsMotionDirection(),
var speed: Expression = NumberExpression(0.0),
@@ -79,14 +140,23 @@ class DynamicParticleMotion(
return direction.getDirectionVector(runtime, storm, emitterPos, particlePos).normalize().multiply(runtime.resolveDouble(speed))
}
override fun getAcceleration(runtime: MoLangRuntime, velocity: Vec3d): Vec3d {
return Vec3d(
override fun getVelocity(runtime: MoLangRuntime, particle: SnowstormParticle, velocity: Vec3d): Vec3d {
val acceleration = Vec3d(
runtime.resolveDouble(acceleration.first),
runtime.resolveDouble(acceleration.second),
runtime.resolveDouble(acceleration.third)
).subtract(velocity.multiply(runtime.resolveDouble(drag)))
)
.subtract(velocity.multiply(20 * runtime.resolveDouble(drag)))
.multiply(1 / 20.0).multiply(1 / 20.0) // blocks per second per second -> blocks per tick per tick
return Vec3d(
velocity.x + acceleration.x,
velocity.y + acceleration.y,
velocity.z + acceleration.z
)
}
override fun getParticleDirection(runtime: MoLangRuntime, storm: ParticleStorm, velocity: Vec3d, minSpeed: Float) = velocity.normalize()
override fun <T> encode(ops: DynamicOps<T>) = CODEC.encodeStart(ops, this)
override fun readFromBuffer(buffer: PacketByteBuf) {
@@ -234,7 +304,8 @@ class StaticParticleMotion : ParticleMotion {
override val type = ParticleMotionType.STATIC
override fun getInitialVelocity(runtime: MoLangRuntime, storm: ParticleStorm, particlePos: Vec3d, emitterPos: Vec3d) = Vec3d.ZERO
override fun getAcceleration(runtime: MoLangRuntime, velocity: Vec3d) = Vec3d.ZERO
override fun getVelocity(runtime: MoLangRuntime, particle: SnowstormParticle, velocity: Vec3d) = velocity
override fun getParticleDirection(runtime: MoLangRuntime, storm: ParticleStorm, velocity: Vec3d, minSpeed: Float) = velocity.normalize()
override fun <T> encode(ops: DynamicOps<T>) = CODEC.encodeStart(ops, this)
override fun readFromBuffer(buffer: PacketByteBuf) {}
override fun writeToBuffer(buffer: PacketByteBuf) {}
@@ -32,6 +32,7 @@ interface ParticleRotation : CodecMapped {
) {
init {
registerSubtype(ParticleRotationType.DYNAMIC, DynamicParticleRotation::class.java, DynamicParticleRotation.CODEC)
registerSubtype(ParticleRotationType.PARAMETRIC, ParametricParticleRotation::class.java, ParametricParticleRotation.CODEC)
}
}
@@ -39,7 +40,34 @@ interface ParticleRotation : CodecMapped {
fun getInitialRotation(runtime: MoLangRuntime): Double
fun getInitialAngularVelocity(runtime: MoLangRuntime): Double
fun getAngularAcceleration(runtime: MoLangRuntime, angularVelocity: Double): Double
fun getAngularVelocity(runtime: MoLangRuntime, angle: Double, angularVelocity: Double): Double
}
class ParametricParticleRotation(var expression: Expression = NumberExpression(0.0)): ParticleRotation {
companion object {
val CODEC: Codec<ParametricParticleRotation> = RecordCodecBuilder.create { instance ->
instance.group(
PrimitiveCodec.STRING.fieldOf("type").forGetter { it.type.name },
EXPRESSION_CODEC.fieldOf("expression").forGetter { it.expression }
).apply(instance) { _, expression ->
ParametricParticleRotation(expression)
}
}
}
override val type = ParticleRotationType.PARAMETRIC
override fun <T> encode(ops: DynamicOps<T>) = CODEC.encodeStart(ops, this)
override fun getInitialRotation(runtime: MoLangRuntime) = runtime.resolveDouble(expression)
override fun getInitialAngularVelocity(runtime: MoLangRuntime) = 0.0
override fun getAngularVelocity(runtime: MoLangRuntime, angle: Double, angularVelocity: Double) = runtime.resolveDouble(expression) - angle
override fun readFromBuffer(buffer: PacketByteBuf) {
expression = MoLang.createParser(buffer.readString()).parseExpression()
}
override fun writeToBuffer(buffer: PacketByteBuf) {
buffer.writeString(expression.getString())
}
}
class DynamicParticleRotation(
@@ -66,15 +94,15 @@ class DynamicParticleRotation(
override fun <T> encode(ops: DynamicOps<T>) = CODEC.encodeStart(ops, this)
override fun getInitialRotation(runtime: MoLangRuntime) = runtime.resolveDouble(startRotation)
override fun getInitialAngularVelocity(runtime: MoLangRuntime) = runtime.resolveDouble(speed) / 20
override fun getAngularAcceleration(runtime: MoLangRuntime, angularVelocity: Double): Double {
override fun getAngularVelocity(runtime: MoLangRuntime, angle: Double, angularVelocity: Double): Double {
val acceleration = runtime.resolveDouble(acceleration)
val nextVelocity = angularVelocity + acceleration
val nextVelocity = angularVelocity * 20 + acceleration
val drag = nextVelocity * runtime.resolveDouble(drag)
return if (abs(drag) > abs(nextVelocity)) {
return angularVelocity + (if (abs(drag) > abs(nextVelocity)) {
0.0
} else {
nextVelocity - drag - angularVelocity
}
nextVelocity - drag - angularVelocity * 20
})
}
override fun readFromBuffer(buffer: PacketByteBuf) {
@@ -10,15 +10,8 @@ package com.cobblemon.mod.common.api.spawning
import com.cobblemon.mod.common.Cobblemon.LOGGER
import com.cobblemon.mod.common.api.entity.Despawner
import com.cobblemon.mod.common.api.spawning.condition.AreaSpawningCondition
import com.cobblemon.mod.common.api.spawning.condition.BasicSpawningCondition
import com.cobblemon.mod.common.api.spawning.condition.FishingSpawningCondition
import com.cobblemon.mod.common.api.spawning.condition.GroundedSpawningCondition
import com.cobblemon.mod.common.api.spawning.condition.SpawningCondition
import com.cobblemon.mod.common.api.spawning.condition.SubmergedSpawningCondition
import com.cobblemon.mod.common.api.spawning.condition.SurfaceSpawningCondition
import com.cobblemon.mod.common.api.spawning.condition.*
import com.cobblemon.mod.common.api.spawning.context.AreaContextResolver
import com.cobblemon.mod.common.api.spawning.context.FishingSpawningContext
import com.cobblemon.mod.common.api.spawning.context.GroundedSpawningContext
import com.cobblemon.mod.common.api.spawning.context.LavafloorSpawningContext
import com.cobblemon.mod.common.api.spawning.context.SeafloorSpawningContext
@@ -31,11 +24,9 @@ import com.cobblemon.mod.common.api.spawning.context.calculators.SeafloorSpawnin
import com.cobblemon.mod.common.api.spawning.context.calculators.SpawningContextCalculator
import com.cobblemon.mod.common.api.spawning.context.calculators.SubmergedSpawningContextCalculator
import com.cobblemon.mod.common.api.spawning.context.calculators.SurfaceSpawningContextCalculator
import com.cobblemon.mod.common.api.spawning.detail.NPCSpawnDetail
import com.cobblemon.mod.common.api.spawning.detail.PokemonSpawnDetail
import com.cobblemon.mod.common.api.spawning.detail.SpawnAction
import com.cobblemon.mod.common.api.spawning.detail.SpawnDetail
import com.cobblemon.mod.common.api.spawning.fishing.FishingSpawner
import com.cobblemon.mod.common.api.spawning.influence.SpawningInfluence
import com.cobblemon.mod.common.api.spawning.preset.BasicSpawnDetailPreset
import com.cobblemon.mod.common.api.spawning.preset.BestSpawnerConfig
@@ -87,7 +78,6 @@ object BestSpawner {
var config = BestSpawnerConfig()
val spawnerManagers = mutableListOf<SpawnerManager>(CobblemonWorldSpawnerManager)
var defaultPokemonDespawner: Despawner<PokemonEntity> = CobblemonAgingDespawner(getAgeTicks = { it.ticksLived })
lateinit var fishingSpawner: FishingSpawner
fun loadConfig() {
LOGGER.info("Starting the Best Spawner...")
@@ -96,7 +86,7 @@ object BestSpawner {
SpawningCondition.register(SubmergedSpawningCondition.NAME, SubmergedSpawningCondition::class.java)
SpawningCondition.register(GroundedSpawningCondition.NAME, GroundedSpawningCondition::class.java)
SpawningCondition.register(SurfaceSpawningCondition.NAME, SurfaceSpawningCondition::class.java)
SpawningCondition.register(FishingSpawningCondition.NAME, FishingSpawningCondition::class.java)
SpawningCondition.register(SeafloorSpawningCondition.NAME, SeafloorSpawningCondition::class.java)
LOGGER.info("Loaded ${SpawningCondition.conditionTypes.size} spawning condition types.")
SpawningContextCalculator.register(GroundedSpawningContextCalculator)
@@ -106,16 +96,14 @@ object BestSpawner {
SpawningContextCalculator.register(SurfaceSpawningContextCalculator)
SpawningContext.register(name = "grounded", clazz = GroundedSpawningContext::class.java, defaultCondition = GroundedSpawningCondition.NAME)
SpawningContext.register(name = "seafloor", clazz = SeafloorSpawningContext::class.java, defaultCondition = GroundedSpawningCondition.NAME)
SpawningContext.register(name = "seafloor", clazz = SeafloorSpawningContext::class.java, defaultCondition = SeafloorSpawningCondition.NAME)
SpawningContext.register(name = "lavafloor", clazz = LavafloorSpawningContext::class.java, defaultCondition = GroundedSpawningCondition.NAME)
SpawningContext.register(name = "submerged", clazz = SubmergedSpawningContext::class.java, defaultCondition = SubmergedSpawningCondition.NAME)
SpawningContext.register(name = "surface", clazz = SurfaceSpawningContext::class.java, defaultCondition = SurfaceSpawningCondition.NAME)
SpawningContext.register(name = "fishing", clazz = FishingSpawningContext::class.java, defaultCondition = FishingSpawningCondition.NAME)
LOGGER.info("Loaded ${SpawningContext.contexts.size} spawning context types.")
SpawnDetail.registerSpawnType(name = PokemonSpawnDetail.TYPE, PokemonSpawnDetail::class.java)
SpawnDetail.registerSpawnType(name = NPCSpawnDetail.TYPE, NPCSpawnDetail::class.java)
LOGGER.info("Loaded ${SpawnDetail.spawnDetailTypes.size} spawn detail types.")
config = BestSpawnerConfig.load()
@@ -126,6 +114,5 @@ object BestSpawner {
fun onServerStarted() {
spawnerManagers.forEach(SpawnerManager::onServerStarted)
fishingSpawner = FishingSpawner()
}
}
@@ -10,7 +10,6 @@ package com.cobblemon.mod.common.api.spawning
import com.bedrockk.molang.Expression
import com.cobblemon.mod.common.api.data.JsonDataRegistry
import com.cobblemon.mod.common.api.molang.ExpressionLike
import com.cobblemon.mod.common.api.reactive.SimpleObservable
import com.cobblemon.mod.common.api.spawning.condition.SpawningCondition
import com.cobblemon.mod.common.api.spawning.influence.SpawningInfluence
@@ -25,7 +24,6 @@ import com.cobblemon.mod.common.api.spawning.rules.selector.ExpressionSpawningCo
import com.cobblemon.mod.common.api.spawning.rules.selector.SpawnDetailSelector
import com.cobblemon.mod.common.api.spawning.rules.selector.SpawningContextSelector
import com.cobblemon.mod.common.util.adapters.ExpressionAdapter
import com.cobblemon.mod.common.util.adapters.ExpressionLikeAdapter
import com.cobblemon.mod.common.util.adapters.SpawnDetailSelectorAdapter
import com.cobblemon.mod.common.util.adapters.SpawnRuleComponentAdapter
import com.cobblemon.mod.common.util.adapters.SpawningConditionAdapter
@@ -52,7 +50,6 @@ object CobblemonSpawnRules : JsonDataRegistry<SpawnRule> {
.registerTypeAdapter(SpawningContextSelector::class.java, SpawningContextSelectorAdapter)
.registerTypeAdapter(SpawningCondition::class.java, SpawningConditionAdapter)
.registerTypeAdapter(Expression::class.java, ExpressionAdapter)
.registerTypeAdapter(ExpressionLike::class.java, ExpressionLikeAdapter)
.registerTypeAdapter(Text::class.java, TextAdapter)
.create()
@@ -8,22 +8,11 @@
package com.cobblemon.mod.common.api.spawning
import com.cobblemon.mod.common.api.spawning.influence.SpawningInfluence
import com.cobblemon.mod.common.api.spawning.spawner.Spawner
import com.cobblemon.mod.common.util.server
import net.minecraft.entity.Entity
import net.minecraft.entity.EntityType
open class SpawnCause(
val spawner: Spawner,
val bucket: SpawnBucket,
entity: Entity? = null
): SpawningInfluence {
val entityWorldId = entity?.world?.registryKey
val entityId = entity?.id
val entityUUID = entity?.uuid
val entityType = entity?.type
val entity: Entity?
get() = if (entityType == EntityType.PLAYER) server()?.playerManager?.getPlayer(entityUUID) else server()?.getWorld(entityWorldId)?.getEntityById(entityId!!)
}
val entity: Entity? = null
)
@@ -1,44 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.spawning.condition
import com.cobblemon.mod.common.api.conditional.RegistryLikeCondition
import com.cobblemon.mod.common.api.spawning.context.FishingSpawningContext
import com.cobblemon.mod.common.util.itemRegistry
import net.minecraft.block.Block
import net.minecraft.item.Item
/**
* A spawning condition that applies to [FishingSpawningContext]s.
*
* @author Hiroku
* @since February 3rd, 2024
*/
class FishingSpawningCondition: SpawningCondition<FishingSpawningContext>() {
override fun contextClass() = FishingSpawningContext::class.java
var rod: RegistryLikeCondition<Item>? = null
var neededNearbyBlocks: MutableList<RegistryLikeCondition<Block>>? = null
override fun fits(ctx: FishingSpawningContext): Boolean {
if (!super.fits(ctx)) {
return false
} else if (rod != null && !rod!!.fits(ctx.rodItem ?: return false, ctx.world.itemRegistry)) {
return false
} else if (neededNearbyBlocks != null && neededNearbyBlocks!!.none { cond -> ctx.nearbyBlockTypes.any { cond.fits(it, ctx.blockRegistry) } }) {
return false
} else {
return true
}
}
companion object {
const val NAME = "fishing"
}
}
@@ -0,0 +1,58 @@
/*
* 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.spawning.condition
import com.cobblemon.mod.common.api.conditional.RegistryLikeCondition
import com.cobblemon.mod.common.api.spawning.context.SeafloorSpawningContext
import com.cobblemon.mod.common.util.Merger
import net.minecraft.block.Block
/**
* Base type for a spawning condition that applies to some kind of [SeafloorSpawningContext]. This
* can be extended for subclasses of [SeafloorSpawningContext].
*
* Borrowed the Grounded context code since it was unintentionally spawning Pokémon on the sea floor
* already. Seems to be working fine /shrug
*
* @author FrankTheFarmer
* @since May 22nd, 2024
*/
abstract class SeafloorTypeSpawningCondition<T : SeafloorSpawningContext> : AreaTypeSpawningCondition<T>() {
var neededBaseBlocks: MutableList<RegistryLikeCondition<Block>>? = null
override fun fits(ctx: T): Boolean {
return if (!super.fits(ctx)) {
false
} else if (minHeight != null && ctx.height < minHeight!!) {
return false
} else if (maxHeight != null && ctx.height > maxHeight!!) {
return false
} else !(neededBaseBlocks != null && neededBaseBlocks!!.none { it.fits(ctx.baseBlock.block, ctx.blockRegistry) })
}
override fun copyFrom(other: SpawningCondition<*>, merger: Merger) {
super.copyFrom(other, merger)
if (other is SeafloorTypeSpawningCondition) {
neededBaseBlocks = merger.merge(neededBaseBlocks, other.neededBaseBlocks)?.toMutableList()
}
}
}
/**
* A spawning condition for a [SeafloorSpawningContext].
*
* @author FrankTheFarmer
* @since May 22nd, 2024
*/
open class SeafloorSpawningCondition : SeafloorTypeSpawningCondition<SeafloorSpawningContext>() {
override fun contextClass() = SeafloorSpawningContext::class.java
companion object {
const val NAME = "seafloor"
}
}
@@ -11,17 +11,12 @@ package com.cobblemon.mod.common.api.spawning.condition
import com.cobblemon.mod.common.api.conditional.RegistryLikeCondition
import com.cobblemon.mod.common.api.spawning.MoonPhaseRange
import com.cobblemon.mod.common.api.spawning.TimeRange
import com.cobblemon.mod.common.api.spawning.context.FishingSpawningContext
import com.cobblemon.mod.common.api.spawning.context.SpawningContext
import com.cobblemon.mod.common.api.spawning.detail.SpawnDetail
import com.cobblemon.mod.common.item.interactive.PokerodItem
import com.cobblemon.mod.common.util.Merger
import com.cobblemon.mod.common.util.math.orMax
import com.cobblemon.mod.common.util.math.orMin
import com.mojang.datafixers.util.Either
import net.minecraft.enchantment.EnchantmentHelper
import net.minecraft.item.ItemStack
import net.minecraft.registry.Registries
import net.minecraft.registry.tag.TagKey
import net.minecraft.util.Identifier
import net.minecraft.world.biome.Biome
@@ -61,10 +56,6 @@ abstract class SpawningCondition<T : SpawningContext> {
var isThundering: Boolean? = null
var timeRange: TimeRange? = null
var structures: MutableList<Either<Identifier, TagKey<Structure>>>? = null
var minLureLevel: Int? = null
var maxLureLevel: Int? = null
var bait: String? = null
var rodType: String? = null
@Transient
var appendages = mutableListOf<AppendageCondition>()
@@ -87,7 +78,7 @@ abstract class SpawningCondition<T : SpawningContext> {
return false
} else if (ctx.position.z < minZ.orMin() || ctx.position.z > maxZ.orMax()) {
return false
} else if (dimensions != null && dimensions!!.isNotEmpty() && ctx.world.dimension.effects !in dimensions!!) {
} else if (dimensions != null && dimensions!!.isNotEmpty() && ctx.world.dimensionKey.value !in dimensions!!) {
return false
} else if (moonPhase != null && ctx.moonPhase !in moonPhase!!) {
return false
@@ -117,34 +108,8 @@ abstract class SpawningCondition<T : SpawningContext> {
}
) {
return false
} else if (minLureLevel != null && ctx is FishingSpawningContext) { // check for the lureLevel of the rod
val pokerodStack = (ctx as FishingSpawningContext).rodStack
if (EnchantmentHelper.getLure(pokerodStack) < minLureLevel!!)
return false
if (maxLureLevel != null && EnchantmentHelper.getLure(pokerodStack) > maxLureLevel!!)
return false
} else if (bait != null && ctx is FishingSpawningContext) { // check for the bait on the bobber
val pokerodBait = (ctx as FishingSpawningContext).rodBait
if (Registries.ITEM.getId(PokerodItem.getBait(pokerodBait)?.item).path != bait)
return false
} else if (rodType != null && ctx is FishingSpawningContext) { // check for the type of pokerod being used
val pokerodItem = (ctx as FishingSpawningContext).rodItem
if (pokerodItem?.pokeRodId?.path != rodType)
return false
}
/*else if (ctx is FishingSpawningContext && (ctx as FishingSpawningContext).rodItem != null) { // check if the bait attracts certain EV yields
val pokerodItem = (ctx as FishingSpawningContext).rodItem
// todo check if the EV yield of the berry matches the bait EV attract maybe?
if (// todo if bait EV yield != EV yield of pokemon consideration //Registries.ITEM.getId(pokerodItem?.bait?.item).path == )
return false
}*/
return true
}
@@ -56,10 +56,9 @@ interface AreaContextResolver {
if (context != null) {
contexts.add(context)
// The position BlockPos has been used in a context, editing the same one
// will cause entities to spawn at the wrong location (buried in walls, usually).
// I made it so that built-in context calculators explicitly take a copy of the
// BlockPos but it'd still be exposed in custom contexts so fixing it here too so
// custom context calculators don't have to remember to do it. - Hiroku
// will cause entities to spawn at the wrong location (buried in walls, usually)
// I made it so that our context calculators specifically take a copy of the
// BlockPos but it'd still be exposed in custom contexts so fixing it here too.
pos = BlockPos.Mutable(1, 2, 3)
input.position = pos
}
@@ -77,51 +76,4 @@ interface AreaContextResolver {
return contexts
}
// fun resolveFishing(
// spawner: Spawner,
// contextCalculators: List<AreaSpawningContextCalculator<*>>,
// slice: WorldSlice
// ): List<AreaSpawningContext> {
// var pos = BlockPos.Mutable(1, 2, 3)
// val input = AreaSpawningInput(spawner, pos, slice)
// val contexts = mutableListOf<AreaSpawningContext>()
//
// var x = slice.baseX
// var y = slice.baseY
// var z = slice.baseZ
//
// while (x < slice.baseX + slice.length) {
// while (y < slice.baseY + slice.height) {
// while (z < slice.baseZ + slice.width) {
// pos.set(x, y, z)
// val vec = pos.toVec3d()
// if (slice.nearbyEntityPositions.none { it.isInRange(vec, 50.0) && it != slice.cause.entity }) {
// val fittedContextCalculator = contextCalculators
// .firstOrNull { calc -> calc.fits(input) && input.spawner.influences.none { !it.isAllowedPosition(input.world, input.position, calc) } }
// if (fittedContextCalculator != null) {
// val context = fittedContextCalculator.calculate(input)
// if (context != null) {
// contexts.add(context)
// // The position BlockPos has been used in a context, editing the same one
// // will cause entities to spawn at the wrong location (buried in walls, usually)
// // I made it so that our context calculators specifically take a copy of the
// // BlockPos but it'd still be exposed in custom contexts so fixing it here too.
// pos = BlockPos.Mutable(1, 2, 3)
// input.position = pos
// }
// }
// }
// z++
// }
// y++
// z = slice.baseZ
// }
// x++
// y = slice.baseY
// z = slice.baseZ
// }
//
// return contexts
// }
}
@@ -49,7 +49,7 @@ open class AreaSpawningContext(
* This is not considering the provided state as what the entity would be on top of,
* but rather the space its hitbox would fill.
*/
open fun isSafeSpace(world: ServerWorld, pos: BlockPos, state: BlockState): Boolean = !state.isFullCube(world, pos)
open fun isSafeSpace(world: ServerWorld, pos: BlockPos, state: BlockState): Boolean = !state.isSolid
override fun postFilter(detail: SpawnDetail): Boolean {
if (!super.postFilter(detail)) {
@@ -1,45 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.spawning.context
import com.cobblemon.mod.common.api.spawning.fishing.FishingSpawnCause
import com.cobblemon.mod.common.api.spawning.influence.SpawningInfluence
import com.cobblemon.mod.common.util.getBlockStates
import com.cobblemon.mod.common.util.toVec3d
import net.minecraft.block.Block
import net.minecraft.server.world.ServerWorld
import net.minecraft.util.math.BlockPos
import net.minecraft.util.math.Box
/**
* A spawning context that was generated for a fishing action.
*
* @author Hiroku
* @since February 3rd, 2024
*/
class FishingSpawningContext(
cause: FishingSpawnCause,
world: ServerWorld,
pos: BlockPos,
influences: MutableList<SpawningInfluence>
) : TriggerSpawningContext(
cause = cause,
world = world,
position = pos,
light = world.getLightLevel(pos),
skyLight = world.getLightLevel(pos.up()),
canSeeSky = world.isSkyVisibleAllowingSea(pos),
influences = influences
) {
val nearbyBlocks = world.getBlockStates(Box.of(pos.toVec3d(), 10.0, 10.0, 10.0))
val nearbyBlockTypes: List<Block> by lazy { nearbyBlocks.mapNotNull { it.block }.distinct() }
val rodStack = cause.rodStack
val rodItem = cause.rodItem
val rodBait = cause.bait
}
@@ -68,7 +68,7 @@ abstract class SpawningContext {
abstract val skyLight: Int
/** Whether or not the sky is visible at this location. */
abstract val canSeeSky: Boolean
/** A list of [SpawningInfluence]s that apply due to this specific context. This generally shouldn't be consumed; use [getAllInfluences].*/
/** A list of [SpawningInfluence]s that apply due to this specific context. */
abstract val influences: MutableList<SpawningInfluence>
/** Gets a cache of structures by block coordinates, grouped by chunk. */
abstract fun getStructureCache(pos: BlockPos): StructureChunkCache
@@ -147,7 +147,7 @@ abstract class SpawningContext {
*/
open fun preFilter(detail: SpawnDetail): Boolean {
/** Returns true if none of the influences.affectSpawnable return false */
return !anyForInfluences { !it.affectSpawnable(detail, this) }
return influences.none { !it.affectSpawnable(detail, this) }
}
/**
@@ -157,12 +157,14 @@ abstract class SpawningContext {
open fun postFilter(detail: SpawnDetail): Boolean = true
open fun afterSpawn(entity: Entity) {
applyInfluences { it.affectSpawn(entity) }
influences.forEach { it.affectSpawn(entity) }
}
open fun getWeight(detail: SpawnDetail): Float {
var weight = detail.weight
applyInfluences(extraInfluences = detail.weightMultipliers) { weight = it.affectWeight(detail, this, weight) }
for (influence in influences + detail.weightMultipliers) {
weight = influence.affectWeight(detail, this, weight)
}
return weight
}
@@ -182,34 +184,4 @@ abstract class SpawningContext {
structCompiled = true
return struct
}
/**
* Gets all influences that apply to this context, including the cause, and does something with them.
*
* Technically we could simple make a list of influences + cause and run that, but influences MUST be able
* to run extremely frequently in performance-critical code, so we don't want to have to allocate a list.
*/
fun applyInfluences(extraInfluences: List<SpawningInfluence>? = null, usage: (SpawningInfluence) -> Unit) {
influences.forEach(usage)
usage(cause)
extraInfluences?.forEach(usage)
}
/**
* Iterates through every operable influence to find if any match the predicate.
*/
fun anyForInfluences(extraInfluences: List<SpawningInfluence>? = null, usage: (SpawningInfluence) -> Boolean): Boolean {
if (influences.any(usage)) {
return true
}
if (usage(cause)) {
return true
}
extraInfluences?.forEach {
if (usage(it)) {
return true
}
}
return false
}
}
@@ -1,34 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.spawning.context
import com.cobblemon.mod.common.api.spawning.SpawnCause
import com.cobblemon.mod.common.api.spawning.influence.SpawningInfluence
import net.minecraft.server.world.ServerWorld
import net.minecraft.util.math.BlockPos
/**
* A spawning context relating to triggered spawning. Uses a single-point structure cache which is
* the only contribution of this implementation.
*
* @author Hiroku
* @since February 3rd, 2024
*/
open class TriggerSpawningContext(
override val cause: SpawnCause,
override val world: ServerWorld,
override val position: BlockPos,
override val light: Int,
override val skyLight: Int,
override val canSeeSky: Boolean,
override val influences: MutableList<SpawningInfluence>
) : SpawningContext() {
val triggerStructureCache = StructureChunkCache()
override fun getStructureCache(pos: BlockPos) = triggerStructureCache
}
@@ -1,27 +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.spawning.detail
import com.cobblemon.mod.common.api.spawning.context.SpawningContext
import com.cobblemon.mod.common.entity.npc.NPCEntity
/**
* A [SpawnAction] for creating [NPCEntity]s.
*
* @author Hiroku
* @since October 8th, 2023
*/
class NPCSpawnAction(ctx: SpawningContext, override val detail: NPCSpawnDetail) : SpawnAction<NPCEntity>(ctx, detail) {
override fun run(): NPCEntity {
val npc = NPCEntity(ctx.world)
npc.npc = detail.npcClass
npc.appliedAspects.addAll(detail.aspects)
return npc
}
}
@@ -1,37 +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.spawning.detail
import com.cobblemon.mod.common.api.npc.NPCClass
import com.cobblemon.mod.common.api.npc.NPCConfiguration
import com.cobblemon.mod.common.api.spawning.context.SpawningContext
import com.cobblemon.mod.common.entity.npc.NPCEntity
import com.google.gson.annotations.SerializedName
/**
* A [SpawnDetail] describing an [NPCEntity] spawn.
*
* @author Hiroku
* @since October 8th, 2023
*/
class NPCSpawnDetail : SpawnDetail() {
companion object {
val TYPE = "npc"
val blankClass = NPCClass()
}
override val type = TYPE
@SerializedName(value = "npcClass", alternate = ["class", "npc"])
val npcClass: NPCClass = blankClass
val configuration: NPCConfiguration? = null
val aspects: Set<String> = emptySet()
override fun doSpawn(ctx: SpawningContext) = NPCSpawnAction(ctx, this)
}
@@ -45,7 +45,6 @@ class PokemonSpawnAction(
null
}?.createStack(ctx)
val entity = props.createEntity(ctx.world)
entity.spawnCause = ctx.cause
SeasonFeatureHandler.updateSeason(entity.pokemon, Cobblemon.seasonResolver(ctx.world, ctx.position))
if (heldItem != null) {
entity.pokemon.swapHeldItem(heldItem)
@@ -39,7 +39,7 @@ abstract class SpawnAction<R>(
return null
}
ctx.applyInfluences { it.affectAction(this) }
ctx.influences.forEach { it.affectAction(this) }
val result = run()
if (result != null) {
future.complete(result)
@@ -1,71 +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.spawning.fishing
import com.cobblemon.mod.common.api.fishing.FishingBait
import com.cobblemon.mod.common.api.fishing.FishingBaits
import com.cobblemon.mod.common.api.pokemon.PokemonSpecies
import com.cobblemon.mod.common.api.pokemon.stats.Stats
import com.cobblemon.mod.common.api.spawning.SpawnBucket
import com.cobblemon.mod.common.api.spawning.SpawnCause
import com.cobblemon.mod.common.api.spawning.context.SpawningContext
import com.cobblemon.mod.common.api.spawning.detail.PokemonSpawnDetail
import com.cobblemon.mod.common.api.spawning.detail.SpawnDetail
import com.cobblemon.mod.common.api.spawning.spawner.Spawner
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import com.cobblemon.mod.common.item.interactive.PokerodItem
import com.cobblemon.mod.common.pokemon.Species
import net.minecraft.entity.Entity
import net.minecraft.item.FishingRodItem
import net.minecraft.item.ItemStack
/**
* A spawning cause that is embellished with fishing information. Could probably also
* have the bobber entity or something.
*
* @author Hiroku
* @since February 3rd, 2024
*/
class FishingSpawnCause(
spawner: Spawner,
bucket: SpawnBucket,
entity: Entity?,
val rodStack: ItemStack
) : SpawnCause(spawner, bucket, entity) {
companion object {
const val FISHED_ASPECT = "fished"
}
val rodItem = rodStack.item as? PokerodItem
val bait = PokerodItem.getBait(rodStack)
override fun affectSpawn(entity: Entity) {
super.affectSpawn(entity)
if (entity is PokemonEntity) {
entity.pokemon.forcedAspects += FISHED_ASPECT
}
}
override fun affectWeight(detail: SpawnDetail, ctx: SpawningContext, weight: Float): Float {
if (!ItemStack.areItemsEqual(ItemStack.EMPTY, bait) && bait != null ){
val bait = FishingBaits.getFromItemStack(bait)
if (detail is PokemonSpawnDetail) {
val detailSpecies = detail.pokemon.species?.let { PokemonSpecies.getByName(it) }
val baitEVEffect = bait!!.effects.firstOrNull() { it.type == FishingBait.Effects.EV && detailSpecies?.evYield?.get(Stats.getStat(it.subcategory?.path.toString()))!! > 0 }
if(detailSpecies != null && baitEVEffect != null) {
return super.affectWeight(detail, ctx, weight * baitEVEffect.value.toFloat())
}
}
}
return super.affectWeight(detail, ctx, weight)
}
}
@@ -1,39 +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.spawning.fishing
import com.cobblemon.mod.common.api.spawning.CobblemonSpawnPools
import com.cobblemon.mod.common.api.spawning.context.FishingSpawningContext
import com.cobblemon.mod.common.api.spawning.detail.SpawnPool
import com.cobblemon.mod.common.api.spawning.influence.SpawningInfluence
import com.cobblemon.mod.common.api.spawning.spawner.TriggerSpawner
import net.minecraft.server.world.ServerWorld
import net.minecraft.util.math.BlockPos
/**
* A spawner that takes in a [FishingSpawnCause] and spawns things.
*
* @author Hiroku
* @since February 3rd, 2024
*/
open class FishingSpawner(
override val name: String = "fishing",
pool: SpawnPool = CobblemonSpawnPools.WORLD_SPAWN_POOL
) : TriggerSpawner<FishingSpawnCause>(name, pool) {
override fun parseContext(cause: FishingSpawnCause, world: ServerWorld, pos: BlockPos): FishingSpawningContext? {
// Maybe confirm that it's water we're fishing in?
val ctx = FishingSpawningContext(
cause = cause,
world = world,
pos = pos,
influences = influences
)
return ctx
}
}
@@ -34,7 +34,8 @@ class BestSpawnerConfig {
val contextWeights = mutableMapOf(
"grounded" to 1F,
"submerged" to 0.99F,
"surface" to 0.01F
"surface" to 0.01F,
"seafloor" to 1F
)
val buckets = mutableListOf(
SpawnBucket("common", 93.8F),
@@ -19,7 +19,6 @@ import com.cobblemon.mod.common.api.molang.ObjectValue
import com.cobblemon.mod.common.api.spawning.context.SpawningContext
import com.cobblemon.mod.common.api.spawning.context.calculators.SpawningContextCalculator
import com.cobblemon.mod.common.util.asExpression
import com.cobblemon.mod.common.util.asExpressionLike
import com.cobblemon.mod.common.util.resolveBoolean
import net.minecraft.registry.RegistryKeys
import net.minecraft.registry.entry.RegistryEntry
@@ -50,7 +49,7 @@ class LocationRuleCalculator : SpawnRuleComponent {
@Transient
private lateinit var reusableDimensionTypeValue: ObjectValue<RegistryEntry<DimensionType>>
val allow = "true".asExpressionLike()
val allow = "true".asExpression()
override fun isAllowedPosition(
world: ServerWorld,
@@ -19,7 +19,6 @@ import com.cobblemon.mod.common.api.spawning.rules.selector.AllSpawningContextSe
import com.cobblemon.mod.common.api.spawning.rules.selector.SpawnDetailSelector
import com.cobblemon.mod.common.api.spawning.rules.selector.SpawningContextSelector
import com.cobblemon.mod.common.util.asExpression
import com.cobblemon.mod.common.util.asExpressionLike
import com.cobblemon.mod.common.util.resolveFloat
/**
@@ -31,7 +30,7 @@ import com.cobblemon.mod.common.util.resolveFloat
class WeightTweakRuleComponent : SpawnRuleComponent {
val spawnSelector: SpawnDetailSelector = AllSpawnDetailSelector
val contextSelector: SpawningContextSelector = AllSpawningContextSelector
val weight = "v.weight".asExpressionLike()
val weight: Expression = "v.weight".asExpression()
@Transient
val runtime = MoLangRuntime().setup()
@@ -12,13 +12,12 @@ import com.bedrockk.molang.runtime.MoLangRuntime
import com.cobblemon.mod.common.api.molang.MoLangFunctions.setup
import com.cobblemon.mod.common.api.spawning.detail.SpawnDetail
import com.cobblemon.mod.common.util.asExpression
import com.cobblemon.mod.common.util.asExpressionLike
import com.cobblemon.mod.common.util.resolveBoolean
class ExpressionSpawnDetailSelector : SpawnDetailSelector {
@Transient
val runtime = MoLangRuntime().setup()
var expression = "true".asExpressionLike()
var expression = "true".asExpression()
override fun selects(spawnDetail: SpawnDetail): Boolean {
runtime.environment.setSimpleVariable("spawn", spawnDetail.struct)
@@ -12,13 +12,12 @@ import com.bedrockk.molang.runtime.MoLangRuntime
import com.cobblemon.mod.common.api.molang.MoLangFunctions.setup
import com.cobblemon.mod.common.api.spawning.context.SpawningContext
import com.cobblemon.mod.common.util.asExpression
import com.cobblemon.mod.common.util.asExpressionLike
import com.cobblemon.mod.common.util.resolveBoolean
class ExpressionSpawningContextSelector : SpawningContextSelector {
@Transient
val runtime = MoLangRuntime().setup()
var expression = "true".asExpressionLike()
var expression = "true".asExpression()
override fun selects(ctx: SpawningContext): Boolean {
runtime.environment.setSimpleVariable("context", ctx.getOrSetupStruct())
@@ -1,51 +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.spawning.spawner
import com.cobblemon.mod.common.api.spawning.SpawnCause
import com.cobblemon.mod.common.api.spawning.context.SpawningContext
import com.cobblemon.mod.common.api.spawning.detail.SpawnPool
import com.cobblemon.mod.common.api.spawning.influence.SpawningInfluence
import com.cobblemon.mod.common.api.spawning.selection.FlatContextWeightedSelector
import com.cobblemon.mod.common.api.spawning.selection.SpawningSelector
import java.util.concurrent.CompletableFuture
import net.minecraft.server.world.ServerWorld
import net.minecraft.util.math.BlockPos
/**
* A type of spawner that occurs at a single point and provides its own means of generating a
* context from a particular cause and position. The trigger spawner must be directly called to
* spawn things (almost as if it was being triggered) as opposed to being scheduled on a ticker.
*
* @author Hiroku
* @since February 3rd, 2024
*/
abstract class TriggerSpawner<T : SpawnCause>(override val name: String, var spawns: SpawnPool) : Spawner {
private var selector: SpawningSelector = FlatContextWeightedSelector()
override val influences = mutableListOf<SpawningInfluence>()
open fun run(cause: T, world: ServerWorld, pos: BlockPos): CompletableFuture<*>? {
val context = parseContext(cause, world, pos) ?: return null
selector.select(this, listOf(context))?.let { (_, spawn) ->
val action = spawn.doSpawn(context)
action.complete()
return action.future
}
return null
}
/** Parses a context, if possible, from the given cause and position. */
abstract fun parseContext(cause: T, world: ServerWorld, pos: BlockPos): SpawningContext?
override fun canSpawn() = true
override fun getSpawningSelector() = selector
override fun setSpawningSelector(selector: SpawningSelector) { this.selector = selector }
override fun getSpawnPool() = spawns
override fun setSpawnPool(spawnPool: SpawnPool) { spawns = spawnPool }
}

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